Update springfox swagger version.
This commit is contained in:
parent
944b2f7572
commit
d110f5a005
@ -250,8 +250,8 @@
|
|||||||
<artifactId>grpc-stub</artifactId>
|
<artifactId>grpc-stub</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.springfox</groupId>
|
<groupId>org.thingsboard</groupId>
|
||||||
<artifactId>springfox-swagger2</artifactId>
|
<artifactId>springfox-boot-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.sun.winsw</groupId>
|
<groupId>com.sun.winsw</groupId>
|
||||||
@ -319,10 +319,6 @@
|
|||||||
<groupId>org.javadelight</groupId>
|
<groupId>org.javadelight</groupId>
|
||||||
<artifactId>delight-nashorn-sandbox</artifactId>
|
<artifactId>delight-nashorn-sandbox</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>io.springfox.ui</groupId>
|
|
||||||
<artifactId>springfox-swagger-ui-rfc6570</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.passay</groupId>
|
<groupId>org.passay</groupId>
|
||||||
<artifactId>passay</artifactId>
|
<artifactId>passay</artifactId>
|
||||||
|
|||||||
@ -20,13 +20,11 @@ import org.springframework.boot.SpringBootConfiguration;
|
|||||||
import org.springframework.context.annotation.ComponentScan;
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
import org.springframework.scheduling.annotation.EnableAsync;
|
import org.springframework.scheduling.annotation.EnableAsync;
|
||||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
@SpringBootConfiguration
|
@SpringBootConfiguration
|
||||||
@EnableAsync
|
@EnableAsync
|
||||||
@EnableSwagger2
|
|
||||||
@EnableScheduling
|
@EnableScheduling
|
||||||
@ComponentScan({"org.thingsboard.server"})
|
@ComponentScan({"org.thingsboard.server"})
|
||||||
public class ThingsboardServerApplication {
|
public class ThingsboardServerApplication {
|
||||||
|
|||||||
@ -18,27 +18,60 @@ package org.thingsboard.server.config;
|
|||||||
import com.fasterxml.classmate.ResolvedType;
|
import com.fasterxml.classmate.ResolvedType;
|
||||||
import com.fasterxml.classmate.TypeResolver;
|
import com.fasterxml.classmate.TypeResolver;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.google.common.base.Predicate;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
import org.thingsboard.server.common.data.security.Authority;
|
import org.thingsboard.server.common.data.security.Authority;
|
||||||
|
import org.thingsboard.server.exception.ThingsboardErrorResponse;
|
||||||
|
import org.thingsboard.server.service.security.auth.rest.LoginRequest;
|
||||||
|
import org.thingsboard.server.service.security.auth.rest.LoginResponse;
|
||||||
import springfox.documentation.builders.ApiInfoBuilder;
|
import springfox.documentation.builders.ApiInfoBuilder;
|
||||||
import springfox.documentation.schema.AlternateTypeRule;
|
import springfox.documentation.builders.OperationBuilder;
|
||||||
|
import springfox.documentation.builders.RepresentationBuilder;
|
||||||
|
import springfox.documentation.builders.RequestParameterBuilder;
|
||||||
|
import springfox.documentation.builders.ResponseBuilder;
|
||||||
|
import springfox.documentation.service.ApiDescription;
|
||||||
import springfox.documentation.service.ApiInfo;
|
import springfox.documentation.service.ApiInfo;
|
||||||
import springfox.documentation.service.ApiKey;
|
import springfox.documentation.service.ApiListing;
|
||||||
import springfox.documentation.service.AuthorizationScope;
|
import springfox.documentation.service.AuthorizationScope;
|
||||||
import springfox.documentation.service.Contact;
|
import springfox.documentation.service.Contact;
|
||||||
|
import springfox.documentation.service.HttpLoginPasswordScheme;
|
||||||
|
import springfox.documentation.service.ParameterType;
|
||||||
|
import springfox.documentation.service.Response;
|
||||||
import springfox.documentation.service.SecurityReference;
|
import springfox.documentation.service.SecurityReference;
|
||||||
|
import springfox.documentation.service.SecurityScheme;
|
||||||
|
import springfox.documentation.service.Tag;
|
||||||
import springfox.documentation.spi.DocumentationType;
|
import springfox.documentation.spi.DocumentationType;
|
||||||
|
import springfox.documentation.spi.service.ApiListingBuilderPlugin;
|
||||||
|
import springfox.documentation.spi.service.ApiListingScannerPlugin;
|
||||||
|
import springfox.documentation.spi.service.contexts.ApiListingContext;
|
||||||
|
import springfox.documentation.spi.service.contexts.DocumentationContext;
|
||||||
|
import springfox.documentation.spi.service.contexts.OperationContext;
|
||||||
import springfox.documentation.spi.service.contexts.SecurityContext;
|
import springfox.documentation.spi.service.contexts.SecurityContext;
|
||||||
import springfox.documentation.spring.web.plugins.Docket;
|
import springfox.documentation.spring.web.plugins.Docket;
|
||||||
|
import springfox.documentation.spring.web.readers.operation.CachingOperationNameGenerator;
|
||||||
|
import springfox.documentation.swagger.common.SwaggerPluginSupport;
|
||||||
|
import springfox.documentation.swagger.web.DocExpansion;
|
||||||
|
import springfox.documentation.swagger.web.ModelRendering;
|
||||||
|
import springfox.documentation.swagger.web.OperationsSorter;
|
||||||
|
import springfox.documentation.swagger.web.UiConfiguration;
|
||||||
|
import springfox.documentation.swagger.web.UiConfigurationBuilder;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import static com.google.common.base.Predicates.and;
|
|
||||||
import static com.google.common.base.Predicates.not;
|
|
||||||
import static com.google.common.collect.Lists.newArrayList;
|
import static com.google.common.collect.Lists.newArrayList;
|
||||||
|
import static java.util.function.Predicate.not;
|
||||||
|
import static springfox.documentation.builders.PathSelectors.any;
|
||||||
import static springfox.documentation.builders.PathSelectors.regex;
|
import static springfox.documentation.builders.PathSelectors.regex;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@ -67,6 +100,9 @@ public class SwaggerConfiguration {
|
|||||||
@Value("${swagger.version}")
|
@Value("${swagger.version}")
|
||||||
private String version;
|
private String version;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CachingOperationNameGenerator operationNames;
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public Docket thingsboardApi() {
|
public Docket thingsboardApi() {
|
||||||
TypeResolver typeResolver = new TypeResolver();
|
TypeResolver typeResolver = new TypeResolver();
|
||||||
@ -77,29 +113,110 @@ public class SwaggerConfiguration {
|
|||||||
typeResolver.resolve(
|
typeResolver.resolve(
|
||||||
String.class);
|
String.class);
|
||||||
|
|
||||||
return new Docket(DocumentationType.SWAGGER_2)
|
return new Docket(DocumentationType.OAS_30)
|
||||||
.groupName("thingsboard")
|
.groupName("thingsboard")
|
||||||
.apiInfo(apiInfo())
|
.apiInfo(apiInfo())
|
||||||
.alternateTypeRules(
|
.additionalModels(
|
||||||
|
typeResolver.resolve(ThingsboardErrorResponse.class),
|
||||||
|
typeResolver.resolve(LoginRequest.class),
|
||||||
|
typeResolver.resolve(LoginResponse.class)
|
||||||
|
)
|
||||||
|
/* .alternateTypeRules(
|
||||||
new AlternateTypeRule(
|
new AlternateTypeRule(
|
||||||
jsonNodeType,
|
jsonNodeType,
|
||||||
stringType))
|
stringType))*/
|
||||||
.select()
|
.select()
|
||||||
.paths(apiPaths())
|
.paths(apiPaths())
|
||||||
|
.paths(any())
|
||||||
.build()
|
.build()
|
||||||
.securitySchemes(newArrayList(jwtTokenKey()))
|
.globalResponses(HttpMethod.GET,
|
||||||
|
List.of(
|
||||||
|
new ResponseBuilder()
|
||||||
|
.code("401")
|
||||||
|
.description("Unauthorized")
|
||||||
|
.representation(MediaType.APPLICATION_JSON)
|
||||||
|
.apply(classRepresentation(ThingsboardErrorResponse.class, true))
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.securitySchemes(newArrayList(httpLogin()))
|
||||||
.securityContexts(newArrayList(securityContext()))
|
.securityContexts(newArrayList(securityContext()))
|
||||||
.enableUrlTemplating(true);
|
.enableUrlTemplating(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ApiKey jwtTokenKey() {
|
@Bean
|
||||||
return new ApiKey("X-Authorization", "JWT token", "header");
|
@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER)
|
||||||
|
ApiListingScannerPlugin loginEndpointListingScanner() {
|
||||||
|
return new ApiListingScannerPlugin() {
|
||||||
|
@Override
|
||||||
|
public List<ApiDescription> apply(DocumentationContext context) {
|
||||||
|
return List.of(loginEndpointApiDescription());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supports(DocumentationType delimiter) {
|
||||||
|
return DocumentationType.SWAGGER_2.equals(delimiter) || DocumentationType.OAS_30.equals(delimiter);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER)
|
||||||
|
ApiListingBuilderPlugin loginEndpointListingBuilder() {
|
||||||
|
return new ApiListingBuilderPlugin() {
|
||||||
|
@Override
|
||||||
|
public void apply(ApiListingContext apiListingContext) {
|
||||||
|
if (apiListingContext.getResourceGroup().getGroupName().equals("default")) {
|
||||||
|
ApiListing apiListing = apiListingContext.apiListingBuilder().build();
|
||||||
|
if (apiListing.getResourcePath().equals("/api/auth/login")) {
|
||||||
|
apiListingContext.apiListingBuilder().tags(Set.of(new Tag("login-endpoint", "Login Endpoint")));
|
||||||
|
apiListingContext.apiListingBuilder().description("Login Endpoint");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supports(DocumentationType delimiter) {
|
||||||
|
return DocumentationType.SWAGGER_2.equals(delimiter) || DocumentationType.OAS_30.equals(delimiter);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
UiConfiguration uiConfig() {
|
||||||
|
return UiConfigurationBuilder.builder()
|
||||||
|
.deepLinking(true)
|
||||||
|
.displayOperationId(false)
|
||||||
|
.defaultModelsExpandDepth(1)
|
||||||
|
.defaultModelExpandDepth(1)
|
||||||
|
.defaultModelRendering(ModelRendering.EXAMPLE)
|
||||||
|
.displayRequestDuration(false)
|
||||||
|
.docExpansion(DocExpansion.NONE)
|
||||||
|
.filter(false)
|
||||||
|
.maxDisplayedTags(null)
|
||||||
|
.operationsSorter(OperationsSorter.ALPHA)
|
||||||
|
.showExtensions(false)
|
||||||
|
.showCommonExtensions(false)
|
||||||
|
.supportedSubmitMethods(UiConfiguration.Constants.DEFAULT_SUBMIT_METHODS)
|
||||||
|
.validatorUrl(null)
|
||||||
|
.syntaxHighlightActivate(true)
|
||||||
|
.syntaxHighlightTheme("agate")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private SecurityScheme httpLogin() {
|
||||||
|
return HttpLoginPasswordScheme
|
||||||
|
.X_AUTHORIZATION_BUILDER
|
||||||
|
.loginEndpoint("/api/auth/login")
|
||||||
|
.name("HTTP login form")
|
||||||
|
.description("Enter Username / Password")
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private SecurityContext securityContext() {
|
private SecurityContext securityContext() {
|
||||||
return SecurityContext.builder()
|
return SecurityContext.builder()
|
||||||
.securityReferences(defaultAuth())
|
.securityReferences(defaultAuth())
|
||||||
.forPaths(securityPaths())
|
.operationSelector(securityPathOperationSelector())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,11 +224,8 @@ public class SwaggerConfiguration {
|
|||||||
return regex(apiPathRegex);
|
return regex(apiPathRegex);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Predicate<String> securityPaths() {
|
private Predicate<OperationContext> securityPathOperationSelector() {
|
||||||
return and(
|
return new SecurityPathOperationSelector(securityPathRegex, nonSecurityPathRegex);
|
||||||
regex(securityPathRegex),
|
|
||||||
not(regex(nonSecurityPathRegex))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<SecurityReference> defaultAuth() {
|
List<SecurityReference> defaultAuth() {
|
||||||
@ -120,7 +234,7 @@ public class SwaggerConfiguration {
|
|||||||
authorizationScopes[1] = new AuthorizationScope(Authority.TENANT_ADMIN.name(), "Tenant administrator");
|
authorizationScopes[1] = new AuthorizationScope(Authority.TENANT_ADMIN.name(), "Tenant administrator");
|
||||||
authorizationScopes[2] = new AuthorizationScope(Authority.CUSTOMER_USER.name(), "Customer");
|
authorizationScopes[2] = new AuthorizationScope(Authority.CUSTOMER_USER.name(), "Customer");
|
||||||
return newArrayList(
|
return newArrayList(
|
||||||
new SecurityReference("X-Authorization", authorizationScopes));
|
new SecurityReference("HTTP login form", authorizationScopes));
|
||||||
}
|
}
|
||||||
|
|
||||||
private ApiInfo apiInfo() {
|
private ApiInfo apiInfo() {
|
||||||
@ -134,4 +248,75 @@ public class SwaggerConfiguration {
|
|||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ApiDescription loginEndpointApiDescription() {
|
||||||
|
return new ApiDescription(null, "/api/auth/login", "Login method to get user JWT token data", "Login endpoint", Collections.singletonList(
|
||||||
|
new OperationBuilder(operationNames)
|
||||||
|
.summary("Login method to get user JWT token data")
|
||||||
|
.tags(Set.of("login-endpoint"))
|
||||||
|
.authorizations(new ArrayList<>())
|
||||||
|
.position(0)
|
||||||
|
.codegenMethodNameStem("loginPost")
|
||||||
|
.method(HttpMethod.POST)
|
||||||
|
.notes("Login method to get user JWT token data.\n\nValue of the response **token** field can be used as JWT token value for authorization.")
|
||||||
|
.requestParameters(
|
||||||
|
List.of(
|
||||||
|
new RequestParameterBuilder()
|
||||||
|
.in(ParameterType.BODY)
|
||||||
|
.required(true)
|
||||||
|
.description("Login request")
|
||||||
|
.content(c ->
|
||||||
|
c.requestBody(true)
|
||||||
|
.representation(MediaType.APPLICATION_JSON)
|
||||||
|
.apply(classRepresentation(LoginRequest.class, false))
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.responses(loginResponses())
|
||||||
|
.build()
|
||||||
|
), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Collection<Response> loginResponses() {
|
||||||
|
return List.of(
|
||||||
|
new ResponseBuilder()
|
||||||
|
.code("200")
|
||||||
|
.description("OK")
|
||||||
|
.representation(MediaType.APPLICATION_JSON)
|
||||||
|
.apply(classRepresentation(LoginResponse.class, true)).
|
||||||
|
build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Helper methods **/
|
||||||
|
|
||||||
|
private Consumer<RepresentationBuilder> classRepresentation(Class clazz, boolean isResponse) {
|
||||||
|
return r -> r.model(
|
||||||
|
m ->
|
||||||
|
m.referenceModel(ref ->
|
||||||
|
ref.key(k ->
|
||||||
|
k.qualifiedModelName(q ->
|
||||||
|
q.namespace(clazz.getPackageName())
|
||||||
|
.name(clazz.getSimpleName())).isResponse(isResponse)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SecurityPathOperationSelector implements Predicate<OperationContext> {
|
||||||
|
|
||||||
|
private final Predicate<String> securityPathSelector;
|
||||||
|
|
||||||
|
SecurityPathOperationSelector(String securityPathRegex, String nonSecurityPathRegex) {
|
||||||
|
this.securityPathSelector = regex(securityPathRegex).and(
|
||||||
|
not(
|
||||||
|
regex(nonSecurityPathRegex)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(OperationContext operationContext) {
|
||||||
|
return this.securityPathSelector.test(operationContext.requestMappingPattern());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -64,6 +64,7 @@ import java.util.List;
|
|||||||
public class ThingsboardSecurityConfiguration extends WebSecurityConfigurerAdapter {
|
public class ThingsboardSecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||||
|
|
||||||
public static final String JWT_TOKEN_HEADER_PARAM = "X-Authorization";
|
public static final String JWT_TOKEN_HEADER_PARAM = "X-Authorization";
|
||||||
|
public static final String JWT_TOKEN_HEADER_PARAM_V2 = "Authorization";
|
||||||
public static final String JWT_TOKEN_QUERY_PARAM = "token";
|
public static final String JWT_TOKEN_QUERY_PARAM = "token";
|
||||||
|
|
||||||
public static final String WEBJARS_ENTRY_POINT = "/webjars/**";
|
public static final String WEBJARS_ENTRY_POINT = "/webjars/**";
|
||||||
|
|||||||
@ -18,12 +18,20 @@ package org.thingsboard.server.config;
|
|||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
public class WebConfig {
|
public class WebConfig {
|
||||||
|
|
||||||
@RequestMapping(value = {"/assets", "/assets/", "/{path:^(?!api$)(?!assets$)(?!static$)(?!webjars$)[^\\.]*}/**"})
|
@RequestMapping(value = {"/assets", "/assets/", "/{path:^(?!api$)(?!assets$)(?!static$)(?!webjars$)(?!swagger-ui$)[^\\.]*}/**"})
|
||||||
public String redirect() {
|
public String redirect() {
|
||||||
return "forward:/index.html";
|
return "forward:/index.html";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/swagger-ui.html")
|
||||||
|
public void redirectSwagger(HttpServletResponse response) throws IOException {
|
||||||
|
response.sendRedirect("/swagger-ui/");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,6 +44,7 @@ public class ControllerConstants {
|
|||||||
protected static final String OTA_PACKAGE_ID_PARAM_DESCRIPTION = "A string value representing the ota package id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
|
protected static final String OTA_PACKAGE_ID_PARAM_DESCRIPTION = "A string value representing the ota package id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
|
||||||
protected static final String ENTITY_TYPE_PARAM_DESCRIPTION = "A string value representing the entity type. For example, 'DEVICE'";
|
protected static final String ENTITY_TYPE_PARAM_DESCRIPTION = "A string value representing the entity type. For example, 'DEVICE'";
|
||||||
protected static final String RULE_CHAIN_ID_PARAM_DESCRIPTION = "A string value representing the rule chain id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
|
protected static final String RULE_CHAIN_ID_PARAM_DESCRIPTION = "A string value representing the rule chain id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
|
||||||
|
protected static final String RULE_NODE_ID_PARAM_DESCRIPTION = "A string value representing the rule node id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
|
||||||
protected static final String WIDGET_BUNDLE_ID_PARAM_DESCRIPTION = "A string value representing the widget bundle id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
|
protected static final String WIDGET_BUNDLE_ID_PARAM_DESCRIPTION = "A string value representing the widget bundle id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
|
||||||
protected static final String WIDGET_TYPE_ID_PARAM_DESCRIPTION = "A string value representing the widget type id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
|
protected static final String WIDGET_TYPE_ID_PARAM_DESCRIPTION = "A string value representing the widget type id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
|
||||||
protected static final String RESOURCE_ID_PARAM_DESCRIPTION = "A string value representing the resource id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
|
protected static final String RESOURCE_ID_PARAM_DESCRIPTION = "A string value representing the resource id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
|
||||||
|
|||||||
@ -95,6 +95,7 @@ import static org.thingsboard.server.controller.ControllerConstants.RULE_CHAIN_S
|
|||||||
import static org.thingsboard.server.controller.ControllerConstants.RULE_CHAIN_TEXT_SEARCH_DESCRIPTION;
|
import static org.thingsboard.server.controller.ControllerConstants.RULE_CHAIN_TEXT_SEARCH_DESCRIPTION;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.RULE_CHAIN_TYPES_ALLOWABLE_VALUES;
|
import static org.thingsboard.server.controller.ControllerConstants.RULE_CHAIN_TYPES_ALLOWABLE_VALUES;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.RULE_CHAIN_TYPE_DESCRIPTION;
|
import static org.thingsboard.server.controller.ControllerConstants.RULE_CHAIN_TYPE_DESCRIPTION;
|
||||||
|
import static org.thingsboard.server.controller.ControllerConstants.RULE_NODE_ID_PARAM_DESCRIPTION;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES;
|
import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION;
|
import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION;
|
import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION;
|
||||||
@ -434,7 +435,7 @@ public class RuleChainController extends BaseController {
|
|||||||
@RequestMapping(value = "/ruleNode/{ruleNodeId}/debugIn", method = RequestMethod.GET)
|
@RequestMapping(value = "/ruleNode/{ruleNodeId}/debugIn", method = RequestMethod.GET)
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public JsonNode getLatestRuleNodeDebugInput(
|
public JsonNode getLatestRuleNodeDebugInput(
|
||||||
@ApiParam(value = RULE_CHAIN_ID_PARAM_DESCRIPTION)
|
@ApiParam(value = RULE_NODE_ID_PARAM_DESCRIPTION)
|
||||||
@PathVariable(RULE_NODE_ID) String strRuleNodeId) throws ThingsboardException {
|
@PathVariable(RULE_NODE_ID) String strRuleNodeId) throws ThingsboardException {
|
||||||
checkParameter(RULE_NODE_ID, strRuleNodeId);
|
checkParameter(RULE_NODE_ID, strRuleNodeId);
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -79,7 +79,7 @@ public class WidgetsBundleController extends BaseController {
|
|||||||
|
|
||||||
@ApiOperation(value = "Create Or Update Widget Bundle (saveWidgetsBundle)",
|
@ApiOperation(value = "Create Or Update Widget Bundle (saveWidgetsBundle)",
|
||||||
notes = "Create or update the Widget Bundle. " + WIDGET_BUNDLE_DESCRIPTION + " " +
|
notes = "Create or update the Widget Bundle. " + WIDGET_BUNDLE_DESCRIPTION + " " +
|
||||||
"When creating the bundle, platform generates Widget Bundle Id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address). " +
|
"When creating the bundle, platform generates Widget Bundle Id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address)). " +
|
||||||
"The newly created Widget Bundle Id will be present in the response. " +
|
"The newly created Widget Bundle Id will be present in the response. " +
|
||||||
"Specify existing Widget Bundle id to update the Widget Bundle. " +
|
"Specify existing Widget Bundle id to update the Widget Bundle. " +
|
||||||
"Referencing non-existing Widget Bundle Id will cause 'Not Found' error." +
|
"Referencing non-existing Widget Bundle Id will cause 'Not Found' error." +
|
||||||
|
|||||||
@ -30,7 +30,10 @@ public class JwtHeaderTokenExtractor implements TokenExtractor {
|
|||||||
public String extract(HttpServletRequest request) {
|
public String extract(HttpServletRequest request) {
|
||||||
String header = request.getHeader(ThingsboardSecurityConfiguration.JWT_TOKEN_HEADER_PARAM);
|
String header = request.getHeader(ThingsboardSecurityConfiguration.JWT_TOKEN_HEADER_PARAM);
|
||||||
if (StringUtils.isBlank(header)) {
|
if (StringUtils.isBlank(header)) {
|
||||||
throw new AuthenticationServiceException("Authorization header cannot be blank!");
|
header = request.getHeader(ThingsboardSecurityConfiguration.JWT_TOKEN_HEADER_PARAM_V2);
|
||||||
|
if (StringUtils.isBlank(header)) {
|
||||||
|
throw new AuthenticationServiceException("Authorization header cannot be blank!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header.length() < HEADER_PREFIX.length()) {
|
if (header.length() < HEADER_PREFIX.length()) {
|
||||||
|
|||||||
@ -17,9 +17,14 @@ package org.thingsboard.server.service.security.auth.rest;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
|
||||||
|
@ApiModel
|
||||||
public class LoginRequest {
|
public class LoginRequest {
|
||||||
|
|
||||||
private String username;
|
private String username;
|
||||||
|
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
@JsonCreator
|
@JsonCreator
|
||||||
@ -28,10 +33,12 @@ public class LoginRequest {
|
|||||||
this.password = password;
|
this.password = password;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ApiModelProperty(position = 1, required = true, value = "User email", example = "tenant@thingsboard.org")
|
||||||
public String getUsername() {
|
public String getUsername() {
|
||||||
return username;
|
return username;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ApiModelProperty(position = 2, required = true, value = "User password", example = "tenant")
|
||||||
public String getPassword() {
|
public String getPassword() {
|
||||||
return password;
|
return password;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* Copyright © 2016-2021 The Thingsboard Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.thingsboard.server.service.security.auth.rest;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@ApiModel
|
||||||
|
@Data
|
||||||
|
public class LoginResponse {
|
||||||
|
|
||||||
|
@ApiModelProperty(position = 1, required = true, value = "JWT token",
|
||||||
|
example = "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZW5hbnRAdGhpbmdzYm9hcmQub3JnIi...")
|
||||||
|
private String token;
|
||||||
|
|
||||||
|
@ApiModelProperty(position = 2, required = true, value = "Refresh token",
|
||||||
|
example = "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZW5hbnRAdGhpbmdzYm9hcmQub3JnIi...")
|
||||||
|
private String refreshToken;
|
||||||
|
|
||||||
|
}
|
||||||
@ -845,9 +845,9 @@ edges:
|
|||||||
persistToTelemetry: "${EDGES_PERSIST_STATE_TO_TELEMETRY:false}"
|
persistToTelemetry: "${EDGES_PERSIST_STATE_TO_TELEMETRY:false}"
|
||||||
|
|
||||||
swagger:
|
swagger:
|
||||||
api_path_regex: "${SWAGGER_API_PATH_REGEX:/api.*}"
|
api_path_regex: "${SWAGGER_API_PATH_REGEX:/api/.*}"
|
||||||
security_path_regex: "${SWAGGER_SECURITY_PATH_REGEX:/api.*}"
|
security_path_regex: "${SWAGGER_SECURITY_PATH_REGEX:/api/.*}"
|
||||||
non_security_path_regex: "${SWAGGER_NON_SECURITY_PATH_REGEX:/api/noauth.*}"
|
non_security_path_regex: "${SWAGGER_NON_SECURITY_PATH_REGEX:/api/(?:noauth|v1)/.*}"
|
||||||
title: "${SWAGGER_TITLE:ThingsBoard REST API}"
|
title: "${SWAGGER_TITLE:ThingsBoard REST API}"
|
||||||
description: "${SWAGGER_DESCRIPTION:For instructions how to authorize requests please visit <a href='http://thingsboard.io/docs/reference/rest-api/'>REST API documentation page</a>.}"
|
description: "${SWAGGER_DESCRIPTION:For instructions how to authorize requests please visit <a href='http://thingsboard.io/docs/reference/rest-api/'>REST API documentation page</a>.}"
|
||||||
contact:
|
contact:
|
||||||
|
|||||||
18
pom.xml
18
pom.xml
@ -46,8 +46,8 @@
|
|||||||
<spring-data-redis.version>2.4.3</spring-data-redis.version>
|
<spring-data-redis.version>2.4.3</spring-data-redis.version>
|
||||||
<jedis.version>3.3.0</jedis.version>
|
<jedis.version>3.3.0</jedis.version>
|
||||||
<jjwt.version>0.7.0</jjwt.version>
|
<jjwt.version>0.7.0</jjwt.version>
|
||||||
<slf4j.version>1.7.7</slf4j.version>
|
<slf4j.version>1.7.32</slf4j.version>
|
||||||
<logback.version>1.2.3</logback.version>
|
<logback.version>1.2.6</logback.version>
|
||||||
<rat.version>0.10</rat.version>
|
<rat.version>0.10</rat.version>
|
||||||
<cassandra.version>4.10.0</cassandra.version>
|
<cassandra.version>4.10.0</cassandra.version>
|
||||||
<metrics.version>4.0.5</metrics.version>
|
<metrics.version>4.0.5</metrics.version>
|
||||||
@ -83,9 +83,8 @@
|
|||||||
<rabbitmq.version>4.8.0</rabbitmq.version>
|
<rabbitmq.version>4.8.0</rabbitmq.version>
|
||||||
<surfire.version>2.19.1</surfire.version>
|
<surfire.version>2.19.1</surfire.version>
|
||||||
<jar-plugin.version>3.0.2</jar-plugin.version>
|
<jar-plugin.version>3.0.2</jar-plugin.version>
|
||||||
<springfox-swagger.version>2.6.1</springfox-swagger.version>
|
<springfox-swagger.version>3.0.1</springfox-swagger.version>
|
||||||
<springfox-swagger-ui-rfc6570.version>1.0.0</springfox-swagger-ui-rfc6570.version>
|
<swagger-annotations.version>1.6.3</swagger-annotations.version>
|
||||||
<swagger-annotations.version>1.5.10</swagger-annotations.version>
|
|
||||||
<spatial4j.version>0.7</spatial4j.version>
|
<spatial4j.version>0.7</spatial4j.version>
|
||||||
<jts.version>1.15.0</jts.version>
|
<jts.version>1.15.0</jts.version>
|
||||||
<bouncycastle.version>1.67</bouncycastle.version>
|
<bouncycastle.version>1.67</bouncycastle.version>
|
||||||
@ -1620,8 +1619,8 @@
|
|||||||
<version>${curator.version}</version>
|
<version>${curator.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.springfox</groupId>
|
<groupId>org.thingsboard</groupId>
|
||||||
<artifactId>springfox-swagger2</artifactId>
|
<artifactId>springfox-boot-starter</artifactId>
|
||||||
<version>${springfox-swagger.version}</version>
|
<version>${springfox-swagger.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -1699,11 +1698,6 @@
|
|||||||
<artifactId>fst</artifactId>
|
<artifactId>fst</artifactId>
|
||||||
<version>${fst.version}</version>
|
<version>${fst.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>io.springfox.ui</groupId>
|
|
||||||
<artifactId>springfox-swagger-ui-rfc6570</artifactId>
|
|
||||||
<version>${springfox-swagger-ui-rfc6570.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.locationtech.spatial4j</groupId>
|
<groupId>org.locationtech.spatial4j</groupId>
|
||||||
<artifactId>spatial4j</artifactId>
|
<artifactId>spatial4j</artifactId>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user