Browse Source

Swagger docs Open API 3.1

pull/10443/head
Igor Kulikov 3 years ago
parent
commit
8910b4b1df
  1. 2
      application/pom.xml
  2. 402
      application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java
  3. 5
      application/src/main/java/org/thingsboard/server/config/WebConfig.java
  4. 6
      application/src/main/java/org/thingsboard/server/controller/AdminController.java
  5. 7
      application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java
  6. 29
      application/src/main/java/org/thingsboard/server/controller/AlarmController.java
  7. 39
      application/src/main/java/org/thingsboard/server/controller/AssetController.java
  8. 24
      application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java
  9. 12
      application/src/main/java/org/thingsboard/server/controller/AuditLogController.java
  10. 61
      application/src/main/java/org/thingsboard/server/controller/DashboardController.java
  11. 9
      application/src/main/java/org/thingsboard/server/controller/DeviceController.java
  12. 27
      application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java
  13. 53
      application/src/main/java/org/thingsboard/server/controller/EdgeController.java
  14. 2
      application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java
  15. 25
      application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java
  16. 18
      application/src/main/java/org/thingsboard/server/controller/EntityViewController.java
  17. 7
      application/src/main/java/org/thingsboard/server/controller/EventController.java
  18. 3
      application/src/main/java/org/thingsboard/server/controller/Lwm2mController.java
  19. 19
      application/src/main/java/org/thingsboard/server/controller/OtaPackageController.java
  20. 8
      application/src/main/java/org/thingsboard/server/controller/RuleChainController.java
  21. 21
      application/src/main/java/org/thingsboard/server/controller/TbResourceController.java
  22. 51
      application/src/main/java/org/thingsboard/server/controller/TelemetryController.java
  23. 2
      application/src/main/resources/thingsboard.yml
  24. 11
      common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java
  25. 4
      common/data/src/main/java/org/thingsboard/server/common/data/id/EntityId.java
  26. 3
      common/data/src/main/java/org/thingsboard/server/common/data/id/UserId.java
  27. 42
      common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java
  28. 8
      pom.xml

2
application/pom.xml

@ -262,7 +262,7 @@
<artifactId>opensmpp-core</artifactId> <artifactId>opensmpp-core</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springdoc</groupId> <groupId>org.thingsboard</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
</dependency> </dependency>
<dependency> <dependency>

402
application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java

@ -15,12 +15,17 @@
*/ */
package org.thingsboard.server.config; package org.thingsboard.server.config;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import io.swagger.v3.core.converter.AnnotatedType; import io.swagger.v3.core.converter.AnnotatedType;
import io.swagger.v3.core.converter.ModelConverter;
import io.swagger.v3.core.converter.ModelConverters; import io.swagger.v3.core.converter.ModelConverters;
import io.swagger.v3.core.util.Json;
import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.PathItem;
import io.swagger.v3.oas.models.Paths;
import io.swagger.v3.oas.models.examples.Example; import io.swagger.v3.oas.models.examples.Example;
import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.info.Info;
@ -33,29 +38,42 @@ import io.swagger.v3.oas.models.responses.ApiResponse;
import io.swagger.v3.oas.models.responses.ApiResponses; import io.swagger.v3.oas.models.responses.ApiResponses;
import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme; import io.swagger.v3.oas.models.security.SecurityScheme;
import io.swagger.v3.oas.models.servers.Server;
import io.swagger.v3.oas.models.tags.Tag; import io.swagger.v3.oas.models.tags.Tag;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springdoc.core.customizers.OpenApiCustomizer; import org.springdoc.core.customizers.OpenApiCustomizer;
import org.springdoc.core.customizers.OperationCustomizer;
import org.springdoc.core.customizers.RouterOperationCustomizer;
import org.springdoc.core.discoverer.SpringDocParameterNameDiscoverer;
import org.springdoc.core.models.GroupedOpenApi; import org.springdoc.core.models.GroupedOpenApi;
import org.springdoc.core.properties.SpringDocConfigProperties;
import org.springdoc.core.properties.SwaggerUiConfigProperties; import org.springdoc.core.properties.SwaggerUiConfigProperties;
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.context.annotation.Lazy;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Profile; import org.springframework.context.annotation.Profile;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestParam;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.exception.ThingsboardCredentialsExpiredResponse; import org.thingsboard.server.exception.ThingsboardCredentialsExpiredResponse;
import org.thingsboard.server.exception.ThingsboardErrorResponse; import org.thingsboard.server.exception.ThingsboardErrorResponse;
import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.security.auth.rest.LoginRequest; import org.thingsboard.server.service.security.auth.rest.LoginRequest;
import org.thingsboard.server.service.security.auth.rest.LoginResponse; import org.thingsboard.server.service.security.auth.rest.LoginResponse;
import java.util.Collections; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
@ -67,8 +85,14 @@ public class SwaggerConfiguration {
public static final String LOGIN_ENDPOINT = "/api/auth/login"; public static final String LOGIN_ENDPOINT = "/api/auth/login";
private static final ApiResponses loginResponses = loginResponses();
private static final ApiResponses defaultErrorResponses = defaultErrorResponses(false);
private static final ApiResponses defaultPostErrorResponses = defaultErrorResponses(true);
@Value("${swagger.api_path:/api/**}") @Value("${swagger.api_path:/api/**}")
private String apiPath; private String apiPath;
@Value("${swagger.security_path_regex}")
private String securityPathRegex;
@Value("${swagger.non_security_path_regex}") @Value("${swagger.non_security_path_regex}")
private String nonSecurityPathRegex; private String nonSecurityPathRegex;
@Value("${swagger.title}") @Value("${swagger.title}")
@ -90,6 +114,7 @@ public class SwaggerConfiguration {
@Value("${app.version:unknown}") @Value("${app.version:unknown}")
private String appVersion; private String appVersion;
@Bean @Bean
public OpenAPI thingsboardApi() { public OpenAPI thingsboardApi() {
Contact contact = new Contact() Contact contact = new Contact()
@ -115,93 +140,24 @@ public class SwaggerConfiguration {
SecurityScheme securityScheme = new SecurityScheme() SecurityScheme securityScheme = new SecurityScheme()
.type(SecurityScheme.Type.HTTP) .type(SecurityScheme.Type.HTTP)
.scheme("bearer") .description("Enter Username / Password")
.bearerFormat("JWT") .scheme("loginPassword")
.in(SecurityScheme.In.HEADER) .bearerFormat("/api/auth/login|X-Authorization");
.description("Enter Username / Password");
var openApi = new OpenAPI() var openApi = new OpenAPI()
.addServersItem(new Server().url("/").description("Default Server URL"))
.components(new Components().addSecuritySchemes("HTTP login form", securityScheme)) .components(new Components().addSecuritySchemes("HTTP login form", securityScheme))
.info(info); .info(info);
addDefaultSchemas(openApi);
addLoginOperation(openApi); addLoginOperation(openApi);
return openApi; return openApi;
} }
public void addLoginOperation(OpenAPI openAPI) {
openAPI.getComponents()
.addSchemas("LoginRequest", ModelConverters.getInstance().readAllAsResolvedSchema(new AnnotatedType().type(LoginRequest.class)).schema)
.addSchemas("LoginResponse", ModelConverters.getInstance().readAllAsResolvedSchema(new AnnotatedType().type(LoginResponse.class)).schema)
.addSchemas("ThingsboardErrorResponse", ModelConverters.getInstance().readAllAsResolvedSchema(new AnnotatedType().type(ThingsboardErrorResponse.class)).schema)
.addSchemas("ThingsboardCredentialsExpiredResponse", ModelConverters.getInstance().readAllAsResolvedSchema(new AnnotatedType().type(ThingsboardCredentialsExpiredResponse.class)).schema);
var operation = new Operation();
operation.summary("Login method to get user JWT token data");
operation.description("Login method used to authenticate user and get JWT token data.\n\nValue of the response **token** " +
"field can be used as **X-Authorization** header value:\n\n`X-Authorization: Bearer $JWT_TOKEN_VALUE`.");
var requestBody = new RequestBody().content(new Content().addMediaType(APPLICATION_JSON_VALUE,
new MediaType().schema(new Schema<LoginRequest>().$ref("#/components/schemas/LoginRequest"))));
operation.requestBody(requestBody);
operation.responses(getResponses());
operation.addTagsItem("login-endpoint");
var pathItem = new PathItem().post(operation);
openAPI.path(LOGIN_ENDPOINT, pathItem);
}
private ApiResponses getResponses() {
ApiResponses apiResponses = new ApiResponses();
apiResponses.addApiResponse("200", new ApiResponse().description("OK")
.content(new Content().addMediaType(APPLICATION_JSON_VALUE,
new MediaType().schema(new Schema<LoginResponse>().$ref("#/components/schemas/LoginResponse")))));
ApiResponse unauthorizedResponse = new ApiResponse().description("Unauthorized");
Content content = new Content();
MediaType mediaType = new MediaType().schema(new Schema<ThingsboardErrorResponse>().$ref("#/components/schemas/ThingsboardErrorResponse"));
Map<String, Example> examples = Map.of(
"bad-credentials", errorExample("Bad credentials",
ThingsboardErrorResponse.of("Invalid username or password", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)),
"token-expired", errorExample("JWT token expired",
ThingsboardErrorResponse.of("Token has expired", ThingsboardErrorCode.JWT_TOKEN_EXPIRED, HttpStatus.UNAUTHORIZED)),
"account-disabled", errorExample("Disabled account",
ThingsboardErrorResponse.of("User account is not active", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)),
"account-locked", errorExample("Locked account",
ThingsboardErrorResponse.of("User account is locked due to security policy", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)),
"authentication-failed", errorExample("General authentication error",
ThingsboardErrorResponse.of("Authentication failed", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED))
);
mediaType.setExamples(examples);
content.addMediaType(APPLICATION_JSON_VALUE, mediaType);
unauthorizedResponse.setContent(content);
apiResponses.addApiResponse("401", unauthorizedResponse);
ApiResponse expiredCredentialsResponse = new ApiResponse().description("Unauthorized (**Expired credentials**)");
Content expiredContent = new Content();
MediaType expiredMediaType = new MediaType().schema(new Schema<ThingsboardCredentialsExpiredResponse>().$ref("#/components/schemas/ThingsboardCredentialsExpiredResponse"));
expiredMediaType.addExamples("credentials-expired", errorExample("Expired credentials",
ThingsboardCredentialsExpiredResponse.of("User password expired!", StringUtils.randomAlphanumeric(30))));
expiredContent.addMediaType(APPLICATION_JSON_VALUE, expiredMediaType);
expiredCredentialsResponse.setContent(expiredContent);
apiResponses.addApiResponse("401 ", expiredCredentialsResponse);
return apiResponses;
}
private Example errorExample(String summary, ThingsboardErrorResponse example) {
return new Example()
.summary(summary)
.value(example);
}
@Bean @Bean
public GroupedOpenApi groupedApi() { @Primary
return GroupedOpenApi.builder() public SpringDocConfigProperties springDocConfig(SpringDocConfigProperties springDocProperties) {
.group("thingsboard") springDocProperties.getApiDocs().setVersion(SpringDocConfigProperties.ApiDocs.OpenApiVersion.OPENAPI_3_1);
.pathsToMatch(apiPath) springDocProperties.setRemoveBrokenReferenceDefinitions(false);
.addOpenApiCustomizer(customOpenApiCustomizer()) return springDocProperties;
.build();
} }
@Bean @Bean
@ -232,35 +188,166 @@ public class SwaggerConfiguration {
return uiProperties; return uiProperties;
} }
public OpenApiCustomizer customOpenApiCustomizer() { private void addLoginOperation(OpenAPI openAPI) {
var loginForm = new SecurityRequirement().addList("HTTP login form"); var operation = new Operation();
return openAPI -> openAPI.getPaths().entrySet().stream().peek(entry -> { operation.summary("Login method to get user JWT token data");
securityCustomization(loginForm, entry); operation.description("""
if (!entry.getKey().equals(LOGIN_ENDPOINT)) { Login method used to authenticate user and get JWT token data.
defaultErrorResponsesCustomization(entry.getValue());
Value of the response **token** field can be used as **X-Authorization** header value:
`X-Authorization: Bearer $JWT_TOKEN_VALUE`.""");
var requestBody = new RequestBody().description("Login request")
.content(new Content().addMediaType(APPLICATION_JSON_VALUE,
new MediaType().schema(new Schema<LoginRequest>().$ref("#/components/schemas/LoginRequest"))));
operation.requestBody(requestBody);
operation.responses(loginResponses);
operation.addTagsItem("login-endpoint");
var pathItem = new PathItem().post(operation);
openAPI.path(LOGIN_ENDPOINT, pathItem);
}
@Bean
public GroupedOpenApi groupedApi(SpringDocParameterNameDiscoverer localSpringDocParameterNameDiscoverer) {
return GroupedOpenApi.builder()
.group("thingsboard")
.pathsToMatch(apiPath)
.addRouterOperationCustomizer(routerOperationCustomizer(localSpringDocParameterNameDiscoverer))
.addOperationCustomizer(operationCustomizer())
.addOpenApiCustomizer(customOpenApiCustomizer())
.build();
}
@Bean
@Lazy(false)
ModelConverter mapAwareConverter() {
return (type, context, chain) -> {
if (chain.hasNext()) {
Schema schema = chain.next().resolve(type, context, chain);
JavaType javaType = Json.mapper().constructType(type.getType());
if (javaType != null) {
Class<?> cls = javaType.getRawClass();
if (Map.class.isAssignableFrom(cls)) {
if (schema != null && schema.getProperties() != null) {
schema.getProperties().remove("empty");
if (schema.getProperties().isEmpty()) {
schema.setProperties(null);
}
}
}
}
return schema;
} else {
return null;
} }
}).map(this::tagsCustomization).forEach(openAPI::addTagsItem); };
} }
private Tag tagsCustomization(Map.Entry<String, PathItem> entry) { private void addDefaultSchemas(OpenAPI openAPI) {
var operations = entry.getValue().readOperationsMap().values(); var jsonNodeSchema = ModelConverters.getInstance().readAllAsResolvedSchema(new AnnotatedType().type(JsonNode.class)).schema;
var tagItem = operations.stream().findAny().get().getTags().get(0); jsonNodeSchema.setType("any");
return tagFromTagItem(tagItem); //noinspection unchecked
jsonNodeSchema.setExamples(List.of(JacksonUtil.newObjectNode()));
jsonNodeSchema.setDescription("A value representing the any type (object or primitive)");
openAPI.getComponents()
.addSchemas("JsonNode", jsonNodeSchema)
.addSchemas("LoginRequest", ModelConverters.getInstance().readAllAsResolvedSchema(new AnnotatedType().type(LoginRequest.class)).schema)
.addSchemas("LoginResponse", ModelConverters.getInstance().readAllAsResolvedSchema(new AnnotatedType().type(LoginResponse.class)).schema)
.addSchemas("ThingsboardErrorResponse", ModelConverters.getInstance().readAllAsResolvedSchema(new AnnotatedType().type(ThingsboardErrorResponse.class)).schema)
.addSchemas("ThingsboardCredentialsExpiredResponse", ModelConverters.getInstance().readAllAsResolvedSchema(new AnnotatedType().type(ThingsboardCredentialsExpiredResponse.class)).schema);
} }
private void defaultErrorResponsesCustomization(PathItem pathItem) { private RouterOperationCustomizer routerOperationCustomizer(SpringDocParameterNameDiscoverer localSpringDocParameterNameDiscoverer) {
pathItem.readOperationsMap().forEach(((httpMethod, operation) -> { return (routerOperation, handlerMethod) -> {
operation.setResponses(getResponses(operation.getResponses(), httpMethod.equals(PathItem.HttpMethod.POST))); String[] pNames = localSpringDocParameterNameDiscoverer.getParameterNames(handlerMethod.getMethod());
})); String[] reflectionParametersNames = Arrays.stream(handlerMethod.getMethod().getParameters()).map(java.lang.reflect.Parameter::getName).toArray(String[]::new);
if (pNames == null || Arrays.stream(pNames).anyMatch(Objects::isNull))
pNames = reflectionParametersNames;
MethodParameter[] parameters = handlerMethod.getMethodParameters();
List<String> requestParams = new ArrayList<>();
for (var i = 0; i < parameters.length; i++) {
var methodParameter = parameters[i];
RequestParam requestParam = methodParameter.getParameterAnnotation(RequestParam.class);
if (requestParam != null) {
String pName = StringUtils.isNotBlank(requestParam.value()) ? requestParam.value() :
pNames[i];
if (StringUtils.isNotBlank(pName)) {
requestParams.add(pName);
}
}
}
if (!requestParams.isEmpty()) {
var path = routerOperation.getPath() + "{?" + String.join(",", requestParams) + "}";
routerOperation.setPath(path);
}
return routerOperation;
};
} }
private void securityCustomization(SecurityRequirement loginForm, Map.Entry<String, PathItem> entry) { private OperationCustomizer operationCustomizer() {
if (!(entry.getKey().matches(nonSecurityPathRegex) || entry.getKey().equals(LOGIN_ENDPOINT))) { return (operation, handlerMethod) -> {
entry.getValue() if (StringUtils.isBlank(operation.getSummary())) {
.readOperationsMap() operation.setSummary(operation.getOperationId());
.values() }
.forEach(operation -> operation.addSecurityItem(loginForm)); return operation;
};
}
private OpenApiCustomizer customOpenApiCustomizer() {
var loginForm = new SecurityRequirement().addList("HTTP login form", Arrays.asList(
Authority.SYS_ADMIN.name(),
Authority.TENANT_ADMIN.name(),
Authority.CUSTOMER_USER.name()
));
return openAPI -> {
var paths = openAPI.getPaths();
paths.entrySet().stream().peek(entry -> {
securityCustomization(loginForm, entry);
if (!entry.getKey().equals(LOGIN_ENDPOINT)) {
defaultErrorResponsesCustomization(entry.getValue());
}
}).map(this::tagsCustomization).filter(Objects::nonNull).distinct().sorted(Comparator.comparing(Tag::getName)).forEach(openAPI::addTagsItem);
var pathItemsByTags = new TreeMap<String, Map<String, PathItem>>();
paths.forEach((k, v) -> {
var tagItem = tagItemFromPathItem(v);
if (tagItem != null) {
var pathItemMap = pathItemsByTags.computeIfAbsent(tagItem, k1 -> new TreeMap<>());
pathItemMap.put(k, v);
}
});
var sortedPaths = new Paths();
pathItemsByTags.forEach((tagItem, pathItemMap) -> {
pathItemMap.forEach(sortedPaths::addPathItem);
});
sortedPaths.setExtensions(paths.getExtensions());
openAPI.setPaths(sortedPaths);
var sortedSchemas = new TreeMap<>(openAPI.getComponents().getSchemas());
openAPI.getComponents().setSchemas(new LinkedHashMap<>(sortedSchemas));
};
}
private Tag tagsCustomization(Map.Entry<String, PathItem> entry) {
var tagItem = tagItemFromPathItem(entry.getValue());
if (tagItem != null) {
return tagFromTagItem(tagItem);
} }
return null;
}
private String tagItemFromPathItem(PathItem item) {
var operations = item.readOperationsMap().values();
var operation = operations.stream().findAny();
if (operation.isPresent()) {
var tags = operation.get().getTags();
if (tags != null && !tags.isEmpty()) {
return tags.get(0);
}
}
return null;
} }
private Tag tagFromTagItem(String tagItem) { private Tag tagFromTagItem(String tagItem) {
@ -276,32 +363,113 @@ public class SwaggerConfiguration {
return new Tag().name(tagItem).description(sb.toString().trim()); return new Tag().name(tagItem).description(sb.toString().trim());
} }
private ApiResponses getResponses(ApiResponses apiResponses, boolean isPost) { private void defaultErrorResponsesCustomization(PathItem pathItem) {
if (apiResponses == null) { pathItem.readOperationsMap().forEach(((httpMethod, operation) -> {
apiResponses = new ApiResponses(); var errorResponses = httpMethod.equals(PathItem.HttpMethod.POST) ? defaultPostErrorResponses : defaultErrorResponses;
var responses = operation.getResponses();
if (responses == null) {
responses = errorResponses;
} else {
ApiResponses updated = responses;
errorResponses.forEach((key, apiResponse) -> {
if (!updated.containsKey(key)) {
updated.put(key, apiResponse);
}
});
}
operation.setResponses(responses);
}));
}
private void securityCustomization(SecurityRequirement loginForm, Map.Entry<String, PathItem> entry) {
var path = entry.getKey();
if (path.matches(securityPathRegex) && !path.matches(nonSecurityPathRegex) && !path.equals(LOGIN_ENDPOINT)) {
entry.getValue()
.readOperationsMap()
.values()
.forEach(operation -> operation.addSecurityItem(loginForm));
} }
}
apiResponses.addApiResponse("400", new ApiResponse().description("Bad Request") private static ApiResponses loginResponses() {
.content(getErrorContent(ThingsboardErrorResponse.of(isPost ? "Invalid request body" : "Invalid UUID string: 123", ThingsboardErrorCode.BAD_REQUEST_PARAMS, HttpStatus.BAD_REQUEST)))); ApiResponses apiResponses = new ApiResponses();
apiResponses.addApiResponse("200", new ApiResponse().description("OK")
.content(new Content().addMediaType(APPLICATION_JSON_VALUE,
new MediaType().schema(new Schema<LoginResponse>().$ref("#/components/schemas/LoginResponse")))));
apiResponses.putAll(loginErrorResponses());
return apiResponses;
}
private static ApiResponses defaultErrorResponses(boolean isPost) {
ApiResponses apiResponses = new ApiResponses();
apiResponses.addApiResponse("400", errorResponse("400", "Bad Request",
ThingsboardErrorResponse.of(isPost ? "Invalid request body" : "Invalid UUID string: 123", ThingsboardErrorCode.BAD_REQUEST_PARAMS, HttpStatus.BAD_REQUEST)));
apiResponses.addApiResponse("401", new ApiResponse().description("Unauthorized") apiResponses.addApiResponse("401", errorResponse("401", "Unauthorized",
.content(getErrorContent(ThingsboardErrorResponse.of("Authentication failed", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)))); ThingsboardErrorResponse.of("Authentication failed", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)));
apiResponses.addApiResponse("403", new ApiResponse().description("Forbidden") apiResponses.addApiResponse("403", errorResponse("403", "Forbidden",
.content(getErrorContent(ThingsboardErrorResponse.of("You don't have permission to perform this operation!", ThingsboardErrorCode.PERMISSION_DENIED, HttpStatus.FORBIDDEN)))); ThingsboardErrorResponse.of("You don't have permission to perform this operation!", ThingsboardErrorCode.PERMISSION_DENIED, HttpStatus.FORBIDDEN)));
apiResponses.addApiResponse("404", new ApiResponse().description("Not Found") apiResponses.addApiResponse("404", errorResponse("404", "Not Found",
.content(getErrorContent(ThingsboardErrorResponse.of("Requested item wasn't found!", ThingsboardErrorCode.ITEM_NOT_FOUND, HttpStatus.NOT_FOUND)))); ThingsboardErrorResponse.of("Requested item wasn't found!", ThingsboardErrorCode.ITEM_NOT_FOUND, HttpStatus.NOT_FOUND)));
apiResponses.addApiResponse("429", new ApiResponse().description("Too Many Requests") apiResponses.addApiResponse("429", errorResponse("429", "Too Many Requests",
.content(getErrorContent(ThingsboardErrorResponse.of("Too many requests for current tenant!", ThingsboardErrorCode.TOO_MANY_REQUESTS, HttpStatus.TOO_MANY_REQUESTS)))); ThingsboardErrorResponse.of("Too many requests for current tenant!", ThingsboardErrorCode.TOO_MANY_REQUESTS, HttpStatus.TOO_MANY_REQUESTS)));
return apiResponses; return apiResponses;
} }
private Content getErrorContent(ThingsboardErrorResponse errorResponse) { private static ApiResponses loginErrorResponses() {
return new Content().addMediaType(org.springframework.http.MediaType.APPLICATION_JSON_VALUE, ApiResponses apiResponses = new ApiResponses();
new MediaType().schema(new Schema<ThingsboardErrorResponse>().example(errorResponse)));
apiResponses.addApiResponse("401", errorResponse("Unauthorized",
Map.of(
"bad-credentials", errorExample("Bad credentials",
ThingsboardErrorResponse.of("Invalid username or password", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)),
"token-expired", errorExample("JWT token expired",
ThingsboardErrorResponse.of("Token has expired", ThingsboardErrorCode.JWT_TOKEN_EXPIRED, HttpStatus.UNAUTHORIZED)),
"account-disabled", errorExample("Disabled account",
ThingsboardErrorResponse.of("User account is not active", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)),
"account-locked", errorExample("Locked account",
ThingsboardErrorResponse.of("User account is locked due to security policy", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)),
"authentication-failed", errorExample("General authentication error",
ThingsboardErrorResponse.of("Authentication failed", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED))
)
));
var credentialsExpiredSchema = new Schema<ThingsboardCredentialsExpiredResponse>();
credentialsExpiredSchema.$ref("#/components/schemas/ThingsboardCredentialsExpiredResponse");
apiResponses.addApiResponse("401 ", errorResponse("Unauthorized (**Expired credentials**)",
Map.of(
"credentials-expired", errorExample("Expired credentials",
ThingsboardCredentialsExpiredResponse.of("User password expired!", StringUtils.randomAlphanumeric(30)))
),
credentialsExpiredSchema
));
return apiResponses;
}
private static ApiResponse errorResponse(String code, String description, ThingsboardErrorResponse example) {
return errorResponse(description, Map.of("error-code-" + code, errorExample(description, example)));
}
private static ApiResponse errorResponse(String description, Map<String, Example> examples) {
var schema = new Schema<ThingsboardErrorResponse>();
schema.$ref("#/components/schemas/ThingsboardErrorResponse");
return errorResponse(description, examples, schema);
}
private static ApiResponse errorResponse(String description, Map<String, Example> examples, Schema<? extends ThingsboardErrorResponse> errorResponseSchema) {
MediaType mediaType = new MediaType().schema(errorResponseSchema);
mediaType.setExamples(examples);
Content content = new Content().addMediaType(org.springframework.http.MediaType.APPLICATION_JSON_VALUE, mediaType);
return new ApiResponse().description(description).content(content);
}
private static Example errorExample(String summary, ThingsboardErrorResponse example) {
return new Example()
.summary(summary)
.value(example);
} }
} }

5
application/src/main/java/org/thingsboard/server/config/WebConfig.java

@ -37,4 +37,9 @@ public class WebConfig {
response.sendRedirect(baseUrl + "/swagger-ui/"); response.sendRedirect(baseUrl + "/swagger-ui/");
} }
@RequestMapping("/swagger-ui/")
public String redirectSwaggerIndex() throws IOException {
return "forward:/swagger-ui/index.html";
}
} }

6
application/src/main/java/org/thingsboard/server/controller/AdminController.java

@ -184,8 +184,7 @@ public class AdminController extends BaseController {
} }
@ApiOperation(value = "Get the JWT Settings object (getJwtSettings)", @ApiOperation(value = "Get the JWT Settings object (getJwtSettings)",
notes = "Get the JWT Settings object that contains JWT token policy, etc. " + SYSTEM_AUTHORITY_PARAGRAPH, notes = "Get the JWT Settings object that contains JWT token policy, etc. " + SYSTEM_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('SYS_ADMIN')") @PreAuthorize("hasAuthority('SYS_ADMIN')")
@RequestMapping(value = "/jwtSettings", method = RequestMethod.GET) @RequestMapping(value = "/jwtSettings", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -195,8 +194,7 @@ public class AdminController extends BaseController {
} }
@ApiOperation(value = "Update JWT Settings (saveJwtSettings)", @ApiOperation(value = "Update JWT Settings (saveJwtSettings)",
notes = "Updates the JWT Settings object that contains JWT token policy, etc. The tokenSigningKey field is a Base64 encoded string." + SYSTEM_AUTHORITY_PARAGRAPH, notes = "Updates the JWT Settings object that contains JWT token policy, etc. The tokenSigningKey field is a Base64 encoded string." + SYSTEM_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('SYS_ADMIN')") @PreAuthorize("hasAuthority('SYS_ADMIN')")
@RequestMapping(value = "/jwtSettings", method = RequestMethod.POST) @RequestMapping(value = "/jwtSettings", method = RequestMethod.POST)
@ResponseBody @ResponseBody

7
application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java

@ -69,8 +69,7 @@ public class AlarmCommentController extends BaseController {
"Referencing non-existing Alarm Comment Id will cause 'Not Found' error. " + "Referencing non-existing Alarm Comment Id will cause 'Not Found' error. " +
"\n\n To create new Alarm comment entity it is enough to specify 'comment' json element with 'text' node, for example: {\"comment\": { \"text\": \"my comment\"}}. " + "\n\n To create new Alarm comment entity it is enough to specify 'comment' json element with 'text' node, for example: {\"comment\": { \"text\": \"my comment\"}}. " +
"\n\n If comment type is not specified the default value 'OTHER' will be saved. If 'alarmId' or 'userId' specified in body it will be ignored." + "\n\n If comment type is not specified the default value 'OTHER' will be saved. If 'alarmId' or 'userId' specified in body it will be ignored." +
TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/alarm/{alarmId}/comment", method = RequestMethod.POST) @RequestMapping(value = "/alarm/{alarmId}/comment", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@ -84,7 +83,7 @@ public class AlarmCommentController extends BaseController {
} }
@ApiOperation(value = "Delete Alarm comment (deleteAlarmComment)", @ApiOperation(value = "Delete Alarm comment (deleteAlarmComment)",
notes = "Deletes the Alarm comment. Referencing non-existing Alarm comment Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) notes = "Deletes the Alarm comment. Referencing non-existing Alarm comment Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/alarm/{alarmId}/comment/{commentId}", method = RequestMethod.DELETE) @RequestMapping(value = "/alarm/{alarmId}/comment/{commentId}", method = RequestMethod.DELETE)
@ResponseBody @ResponseBody
@ -100,7 +99,7 @@ public class AlarmCommentController extends BaseController {
@ApiOperation(value = "Get Alarm comments (getAlarmComments)", @ApiOperation(value = "Get Alarm comments (getAlarmComments)",
notes = "Returns a page of alarm comments for specified alarm. " + notes = "Returns a page of alarm comments for specified alarm. " +
PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/alarm/{alarmId}/comment", method = RequestMethod.GET) @RequestMapping(value = "/alarm/{alarmId}/comment", method = RequestMethod.GET)
@ResponseBody @ResponseBody

29
application/src/main/java/org/thingsboard/server/controller/AlarmController.java

@ -104,7 +104,7 @@ public class AlarmController extends BaseController {
"filled in the AlarmInfo object field: 'originatorName' or will returns as null."; "filled in the AlarmInfo object field: 'originatorName' or will returns as null.";
@ApiOperation(value = "Get Alarm (getAlarmById)", @ApiOperation(value = "Get Alarm (getAlarmById)",
notes = "Fetch the Alarm object based on the provided Alarm Id. " + ALARM_SECURITY_CHECK, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) notes = "Fetch the Alarm object based on the provided Alarm Id. " + ALARM_SECURITY_CHECK)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/alarm/{alarmId}", method = RequestMethod.GET) @RequestMapping(value = "/alarm/{alarmId}", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -117,7 +117,7 @@ public class AlarmController extends BaseController {
@ApiOperation(value = "Get Alarm Info (getAlarmInfoById)", @ApiOperation(value = "Get Alarm Info (getAlarmInfoById)",
notes = "Fetch the Alarm Info object based on the provided Alarm Id. " + notes = "Fetch the Alarm Info object based on the provided Alarm Id. " +
ALARM_SECURITY_CHECK + ALARM_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) ALARM_SECURITY_CHECK + ALARM_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/alarm/info/{alarmId}", method = RequestMethod.GET) @RequestMapping(value = "/alarm/info/{alarmId}", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -139,7 +139,7 @@ public class AlarmController extends BaseController {
"If the user clears the alarm (see 'Clear Alarm(clearAlarm)'), than new alarm with the same type and same device may be created. " + "If the user clears the alarm (see 'Clear Alarm(clearAlarm)'), than new alarm with the same type and same device may be created. " +
"Remove 'id', 'tenantId' and optionally 'customerId' from the request body example (below) to create new Alarm entity. " + "Remove 'id', 'tenantId' and optionally 'customerId' from the request body example (below) to create new Alarm entity. " +
TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH
, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) )
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/alarm", method = RequestMethod.POST) @RequestMapping(value = "/alarm", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@ -155,7 +155,7 @@ public class AlarmController extends BaseController {
} }
@ApiOperation(value = "Delete Alarm (deleteAlarm)", @ApiOperation(value = "Delete Alarm (deleteAlarm)",
notes = "Deletes the Alarm. Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) notes = "Deletes the Alarm. Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/alarm/{alarmId}", method = RequestMethod.DELETE) @RequestMapping(value = "/alarm/{alarmId}", method = RequestMethod.DELETE)
@ResponseBody @ResponseBody
@ -169,7 +169,7 @@ public class AlarmController extends BaseController {
@ApiOperation(value = "Acknowledge Alarm (ackAlarm)", @ApiOperation(value = "Acknowledge Alarm (ackAlarm)",
notes = "Acknowledge the Alarm. " + notes = "Acknowledge the Alarm. " +
"Once acknowledged, the 'ack_ts' field will be set to current timestamp and special rule chain event 'ALARM_ACK' will be generated. " + "Once acknowledged, the 'ack_ts' field will be set to current timestamp and special rule chain event 'ALARM_ACK' will be generated. " +
"Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) "Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/alarm/{alarmId}/ack", method = RequestMethod.POST) @RequestMapping(value = "/alarm/{alarmId}/ack", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK) @ResponseStatus(value = HttpStatus.OK)
@ -184,7 +184,7 @@ public class AlarmController extends BaseController {
@ApiOperation(value = "Clear Alarm (clearAlarm)", @ApiOperation(value = "Clear Alarm (clearAlarm)",
notes = "Clear the Alarm. " + notes = "Clear the Alarm. " +
"Once cleared, the 'clear_ts' field will be set to current timestamp and special rule chain event 'ALARM_CLEAR' will be generated. " + "Once cleared, the 'clear_ts' field will be set to current timestamp and special rule chain event 'ALARM_CLEAR' will be generated. " +
"Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) "Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/alarm/{alarmId}/clear", method = RequestMethod.POST) @RequestMapping(value = "/alarm/{alarmId}/clear", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK) @ResponseStatus(value = HttpStatus.OK)
@ -200,7 +200,7 @@ public class AlarmController extends BaseController {
notes = "Assign the Alarm. " + notes = "Assign the Alarm. " +
"Once assigned, the 'assign_ts' field will be set to current timestamp and special rule chain event 'ALARM_ASSIGNED' " + "Once assigned, the 'assign_ts' field will be set to current timestamp and special rule chain event 'ALARM_ASSIGNED' " +
"(or ALARM_REASSIGNED in case of assigning already assigned alarm) will be generated. " + "(or ALARM_REASSIGNED in case of assigning already assigned alarm) will be generated. " +
"Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) "Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/alarm/{alarmId}/assign/{assigneeId}", method = RequestMethod.POST) @RequestMapping(value = "/alarm/{alarmId}/assign/{assigneeId}", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK) @ResponseStatus(value = HttpStatus.OK)
@ -221,7 +221,7 @@ public class AlarmController extends BaseController {
@ApiOperation(value = "Unassign Alarm (unassignAlarm)", @ApiOperation(value = "Unassign Alarm (unassignAlarm)",
notes = "Unassign the Alarm. " + notes = "Unassign the Alarm. " +
"Once unassigned, the 'assign_ts' field will be set to current timestamp and special rule chain event 'ALARM_UNASSIGNED' will be generated. " + "Once unassigned, the 'assign_ts' field will be set to current timestamp and special rule chain event 'ALARM_UNASSIGNED' will be generated. " +
"Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) "Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/alarm/{alarmId}/assign", method = RequestMethod.DELETE) @RequestMapping(value = "/alarm/{alarmId}/assign", method = RequestMethod.DELETE)
@ResponseStatus(value = HttpStatus.OK) @ResponseStatus(value = HttpStatus.OK)
@ -236,7 +236,7 @@ public class AlarmController extends BaseController {
@ApiOperation(value = "Get Alarms (getAlarms)", @ApiOperation(value = "Get Alarms (getAlarms)",
notes = "Returns a page of alarms for the selected entity. Specifying both parameters 'searchStatus' and 'status' at the same time will cause an error. " + notes = "Returns a page of alarms for the selected entity. Specifying both parameters 'searchStatus' and 'status' at the same time will cause an error. " +
PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/alarm/{entityType}/{entityId}", method = RequestMethod.GET) @RequestMapping(value = "/alarm/{entityType}/{entityId}", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -292,7 +292,7 @@ public class AlarmController extends BaseController {
"If the user has the authority of 'Tenant Administrator', the server returns alarms that belongs to the tenant of current user. " + "If the user has the authority of 'Tenant Administrator', the server returns alarms that belongs to the tenant of current user. " +
"If the user has the authority of 'Customer User', the server returns alarms that belongs to the customer of current user. " + "If the user has the authority of 'Customer User', the server returns alarms that belongs to the customer of current user. " +
"Specifying both parameters 'searchStatus' and 'status' at the same time will cause an error. " + "Specifying both parameters 'searchStatus' and 'status' at the same time will cause an error. " +
PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/alarms", method = RequestMethod.GET) @RequestMapping(value = "/alarms", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -341,7 +341,7 @@ public class AlarmController extends BaseController {
@ApiOperation(value = "Get Alarms (getAlarmsV2)", @ApiOperation(value = "Get Alarms (getAlarmsV2)",
notes = "Returns a page of alarms for the selected entity. " + notes = "Returns a page of alarms for the selected entity. " +
PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/v2/alarm/{entityType}/{entityId}", method = RequestMethod.GET) @RequestMapping(value = "/v2/alarm/{entityType}/{entityId}", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -407,7 +407,7 @@ public class AlarmController extends BaseController {
notes = "Returns a page of alarms that belongs to the current user owner. " + notes = "Returns a page of alarms that belongs to the current user owner. " +
"If the user has the authority of 'Tenant Administrator', the server returns alarms that belongs to the tenant of current user. " + "If the user has the authority of 'Tenant Administrator', the server returns alarms that belongs to the tenant of current user. " +
"If the user has the authority of 'Customer User', the server returns alarms that belongs to the customer of current user. " + "If the user has the authority of 'Customer User', the server returns alarms that belongs to the customer of current user. " +
PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/v2/alarms", method = RequestMethod.GET) @RequestMapping(value = "/v2/alarms", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -468,7 +468,7 @@ public class AlarmController extends BaseController {
@ApiOperation(value = "Get Highest Alarm Severity (getHighestAlarmSeverity)", @ApiOperation(value = "Get Highest Alarm Severity (getHighestAlarmSeverity)",
notes = "Search the alarms by originator ('entityType' and entityId') and optional 'status' or 'searchStatus' filters and returns the highest AlarmSeverity(CRITICAL, MAJOR, MINOR, WARNING or INDETERMINATE). " + notes = "Search the alarms by originator ('entityType' and entityId') and optional 'status' or 'searchStatus' filters and returns the highest AlarmSeverity(CRITICAL, MAJOR, MINOR, WARNING or INDETERMINATE). " +
"Specifying both parameters 'searchStatus' and 'status' at the same time will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH "Specifying both parameters 'searchStatus' and 'status' at the same time will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH
, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) )
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/alarm/highestSeverity/{entityType}/{entityId}", method = RequestMethod.GET) @RequestMapping(value = "/alarm/highestSeverity/{entityType}/{entityId}", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -499,8 +499,7 @@ public class AlarmController extends BaseController {
} }
@ApiOperation(value = "Get Alarm Types (getAlarmTypes)", @ApiOperation(value = "Get Alarm Types (getAlarmTypes)",
notes = "Returns a set of unique alarm types based on alarms that are either owned by the tenant or assigned to the customer which user is performing the request.", notes = "Returns a set of unique alarm types based on alarms that are either owned by the tenant or assigned to the customer which user is performing the request.")
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/alarm/types", method = RequestMethod.GET) @RequestMapping(value = "/alarm/types", method = RequestMethod.GET)
@ResponseBody @ResponseBody

39
application/src/main/java/org/thingsboard/server/controller/AssetController.java

@ -103,7 +103,7 @@ public class AssetController extends BaseController {
notes = "Fetch the Asset object based on the provided Asset Id. " + notes = "Fetch the Asset object based on the provided Asset Id. " +
"If the user has the authority of 'Tenant Administrator', the server checks that the asset is owned by the same tenant. " + "If the user has the authority of 'Tenant Administrator', the server checks that the asset is owned by the same tenant. " +
"If the user has the authority of 'Customer User', the server checks that the asset is assigned to the same customer." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH "If the user has the authority of 'Customer User', the server checks that the asset is assigned to the same customer." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH
, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) )
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/asset/{assetId}", method = RequestMethod.GET) @RequestMapping(value = "/asset/{assetId}", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -118,7 +118,7 @@ public class AssetController extends BaseController {
notes = "Fetch the Asset Info object based on the provided Asset Id. " + notes = "Fetch the Asset Info object based on the provided Asset Id. " +
"If the user has the authority of 'Tenant Administrator', the server checks that the asset is owned by the same tenant. " + "If the user has the authority of 'Tenant Administrator', the server checks that the asset is owned by the same tenant. " +
"If the user has the authority of 'Customer User', the server checks that the asset is assigned to the same customer. " "If the user has the authority of 'Customer User', the server checks that the asset is assigned to the same customer. "
+ ASSET_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + ASSET_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/asset/info/{assetId}", method = RequestMethod.GET) @RequestMapping(value = "/asset/info/{assetId}", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -135,7 +135,7 @@ public class AssetController extends BaseController {
"Specify existing Asset id to update the asset. " + "Specify existing Asset id to update the asset. " +
"Referencing non-existing Asset Id will cause 'Not Found' error. " + "Referencing non-existing Asset Id will cause 'Not Found' error. " +
"Remove 'id', 'tenantId' and optionally 'customerId' from the request body example (below) to create new Asset entity. " "Remove 'id', 'tenantId' and optionally 'customerId' from the request body example (below) to create new Asset entity. "
+ TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/asset", method = RequestMethod.POST) @RequestMapping(value = "/asset", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@ -158,7 +158,7 @@ public class AssetController extends BaseController {
} }
@ApiOperation(value = "Assign asset to customer (assignAssetToCustomer)", @ApiOperation(value = "Assign asset to customer (assignAssetToCustomer)",
notes = "Creates assignment of the asset to customer. Customer will be able to query asset afterwards." + TENANT_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) notes = "Creates assignment of the asset to customer. Customer will be able to query asset afterwards." + TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/customer/{customerId}/asset/{assetId}", method = RequestMethod.POST) @RequestMapping(value = "/customer/{customerId}/asset/{assetId}", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@ -174,7 +174,7 @@ public class AssetController extends BaseController {
} }
@ApiOperation(value = "Unassign asset from customer (unassignAssetFromCustomer)", @ApiOperation(value = "Unassign asset from customer (unassignAssetFromCustomer)",
notes = "Clears assignment of the asset to customer. Customer will not be able to query asset afterwards." + TENANT_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) notes = "Clears assignment of the asset to customer. Customer will not be able to query asset afterwards." + TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/customer/asset/{assetId}", method = RequestMethod.DELETE) @RequestMapping(value = "/customer/asset/{assetId}", method = RequestMethod.DELETE)
@ResponseBody @ResponseBody
@ -192,7 +192,7 @@ public class AssetController extends BaseController {
@ApiOperation(value = "Make asset publicly available (assignAssetToPublicCustomer)", @ApiOperation(value = "Make asset publicly available (assignAssetToPublicCustomer)",
notes = "Asset will be available for non-authorized (not logged-in) users. " + notes = "Asset will be available for non-authorized (not logged-in) users. " +
"This is useful to create dashboards that you plan to share/embed on a publicly available website. " + "This is useful to create dashboards that you plan to share/embed on a publicly available website. " +
"However, users that are logged-in and belong to different tenant will not be able to access the asset." + TENANT_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) "However, users that are logged-in and belong to different tenant will not be able to access the asset." + TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/customer/public/asset/{assetId}", method = RequestMethod.POST) @RequestMapping(value = "/customer/public/asset/{assetId}", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@ -205,7 +205,7 @@ public class AssetController extends BaseController {
@ApiOperation(value = "Get Tenant Assets (getTenantAssets)", @ApiOperation(value = "Get Tenant Assets (getTenantAssets)",
notes = "Returns a page of assets owned by tenant. " + notes = "Returns a page of assets owned by tenant. " +
PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/tenant/assets", params = {"pageSize", "page"}, method = RequestMethod.GET) @RequestMapping(value = "/tenant/assets", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -233,7 +233,7 @@ public class AssetController extends BaseController {
@ApiOperation(value = "Get Tenant Asset Infos (getTenantAssetInfos)", @ApiOperation(value = "Get Tenant Asset Infos (getTenantAssetInfos)",
notes = "Returns a page of assets info objects owned by tenant. " + notes = "Returns a page of assets info objects owned by tenant. " +
PAGE_DATA_PARAMETERS + ASSET_INFO_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) PAGE_DATA_PARAMETERS + ASSET_INFO_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/tenant/assetInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) @RequestMapping(value = "/tenant/assetInfos", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -266,7 +266,7 @@ public class AssetController extends BaseController {
@ApiOperation(value = "Get Tenant Asset (getTenantAsset)", @ApiOperation(value = "Get Tenant Asset (getTenantAsset)",
notes = "Requested asset must be owned by tenant that the user belongs to. " + notes = "Requested asset must be owned by tenant that the user belongs to. " +
"Asset name is an unique property of asset. So it can be used to identify the asset." + TENANT_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) "Asset name is an unique property of asset. So it can be used to identify the asset." + TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/tenant/assets", params = {"assetName"}, method = RequestMethod.GET) @RequestMapping(value = "/tenant/assets", params = {"assetName"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -279,7 +279,7 @@ public class AssetController extends BaseController {
@ApiOperation(value = "Get Customer Assets (getCustomerAssets)", @ApiOperation(value = "Get Customer Assets (getCustomerAssets)",
notes = "Returns a page of assets objects assigned to customer. " + notes = "Returns a page of assets objects assigned to customer. " +
PAGE_DATA_PARAMETERS, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) PAGE_DATA_PARAMETERS)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/customer/{customerId}/assets", params = {"pageSize", "page"}, method = RequestMethod.GET) @RequestMapping(value = "/customer/{customerId}/assets", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -312,7 +312,7 @@ public class AssetController extends BaseController {
@ApiOperation(value = "Get Customer Asset Infos (getCustomerAssetInfos)", @ApiOperation(value = "Get Customer Asset Infos (getCustomerAssetInfos)",
notes = "Returns a page of assets info objects assigned to customer. " + notes = "Returns a page of assets info objects assigned to customer. " +
PAGE_DATA_PARAMETERS + ASSET_INFO_DESCRIPTION, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) PAGE_DATA_PARAMETERS + ASSET_INFO_DESCRIPTION)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/customer/{customerId}/assetInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) @RequestMapping(value = "/customer/{customerId}/assetInfos", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -349,7 +349,7 @@ public class AssetController extends BaseController {
} }
@ApiOperation(value = "Get Assets By Ids (getAssetsByIds)", @ApiOperation(value = "Get Assets By Ids (getAssetsByIds)",
notes = "Requested assets must be owned by tenant or assigned to customer which user is performing the request. ", responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) notes = "Requested assets must be owned by tenant or assigned to customer which user is performing the request. ")
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/assets", params = {"assetIds"}, method = RequestMethod.GET) @RequestMapping(value = "/assets", params = {"assetIds"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -376,7 +376,7 @@ public class AssetController extends BaseController {
@ApiOperation(value = "Find related assets (findByQuery)", @ApiOperation(value = "Find related assets (findByQuery)",
notes = "Returns all assets that are related to the specific entity. " + notes = "Returns all assets that are related to the specific entity. " +
"The entity id, relation type, asset types, depth of the search, and other query parameters defined using complex 'AssetSearchQuery' object. " + "The entity id, relation type, asset types, depth of the search, and other query parameters defined using complex 'AssetSearchQuery' object. " +
"See 'Model' tab of the Parameters for more info.", responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) "See 'Model' tab of the Parameters for more info.")
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/assets", method = RequestMethod.POST) @RequestMapping(value = "/assets", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@ -398,8 +398,7 @@ public class AssetController extends BaseController {
} }
@ApiOperation(value = "Get Asset Types (getAssetTypes)", @ApiOperation(value = "Get Asset Types (getAssetTypes)",
notes = "Deprecated. See 'getAssetProfileNames' API from Asset Profile Controller instead." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, notes = "Deprecated. See 'getAssetProfileNames' API from Asset Profile Controller instead." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/asset/types", method = RequestMethod.GET) @RequestMapping(value = "/asset/types", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -416,8 +415,7 @@ public class AssetController extends BaseController {
EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION + EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION +
"Second, remote edge service will receive a copy of assignment asset " + "Second, remote edge service will receive a copy of assignment asset " +
EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION + EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION +
"Third, once asset will be delivered to edge service, it's going to be available for usage on remote edge instance.", "Third, once asset will be delivered to edge service, it's going to be available for usage on remote edge instance.")
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/edge/{edgeId}/asset/{assetId}", method = RequestMethod.POST) @RequestMapping(value = "/edge/{edgeId}/asset/{assetId}", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@ -440,8 +438,7 @@ public class AssetController extends BaseController {
EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION + EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION +
"Second, remote edge service will receive an 'unassign' command to remove asset " + "Second, remote edge service will receive an 'unassign' command to remove asset " +
EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION + EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION +
"Third, once 'unassign' command will be delivered to edge service, it's going to remove asset locally.", "Third, once 'unassign' command will be delivered to edge service, it's going to remove asset locally.")
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/edge/{edgeId}/asset/{assetId}", method = RequestMethod.DELETE) @RequestMapping(value = "/edge/{edgeId}/asset/{assetId}", method = RequestMethod.DELETE)
@ResponseBody @ResponseBody
@ -460,7 +457,7 @@ public class AssetController extends BaseController {
@ApiOperation(value = "Get assets assigned to edge (getEdgeAssets)", @ApiOperation(value = "Get assets assigned to edge (getEdgeAssets)",
notes = "Returns a page of assets assigned to edge. " + notes = "Returns a page of assets assigned to edge. " +
PAGE_DATA_PARAMETERS, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) PAGE_DATA_PARAMETERS)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/edge/{edgeId}/assets", params = {"pageSize", "page"}, method = RequestMethod.GET) @RequestMapping(value = "/edge/{edgeId}/assets", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -510,7 +507,7 @@ public class AssetController extends BaseController {
} }
@ApiOperation(value = "Import the bulk of assets (processAssetsBulkImport)", @ApiOperation(value = "Import the bulk of assets (processAssetsBulkImport)",
notes = "There's an ability to import the bulk of assets using the only .csv file.", responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) notes = "There's an ability to import the bulk of assets using the only .csv file.")
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@PostMapping("/asset/bulk_import") @PostMapping("/asset/bulk_import")
public BulkImportResult<Asset> processAssetsBulkImport(@RequestBody BulkImportRequest request) throws Exception { public BulkImportResult<Asset> processAssetsBulkImport(@RequestBody BulkImportRequest request) throws Exception {

24
application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java

@ -78,8 +78,7 @@ public class AssetProfileController extends BaseController {
@ApiOperation(value = "Get Asset Profile (getAssetProfileById)", @ApiOperation(value = "Get Asset Profile (getAssetProfileById)",
notes = "Fetch the Asset Profile object based on the provided Asset Profile Id. " + notes = "Fetch the Asset Profile object based on the provided Asset Profile Id. " +
"The server checks that the asset profile is owned by the same tenant. " + TENANT_AUTHORITY_PARAGRAPH, "The server checks that the asset profile is owned by the same tenant. " + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/assetProfile/{assetProfileId}", method = RequestMethod.GET) @RequestMapping(value = "/assetProfile/{assetProfileId}", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -99,8 +98,7 @@ public class AssetProfileController extends BaseController {
@ApiOperation(value = "Get Asset Profile Info (getAssetProfileInfoById)", @ApiOperation(value = "Get Asset Profile Info (getAssetProfileInfoById)",
notes = "Fetch the Asset Profile Info object based on the provided Asset Profile Id. " notes = "Fetch the Asset Profile Info object based on the provided Asset Profile Id. "
+ ASSET_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, + ASSET_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/assetProfileInfo/{assetProfileId}", method = RequestMethod.GET) @RequestMapping(value = "/assetProfileInfo/{assetProfileId}", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -114,8 +112,7 @@ public class AssetProfileController extends BaseController {
@ApiOperation(value = "Get Default Asset Profile (getDefaultAssetProfileInfo)", @ApiOperation(value = "Get Default Asset Profile (getDefaultAssetProfileInfo)",
notes = "Fetch the Default Asset Profile Info object. " + notes = "Fetch the Default Asset Profile Info object. " +
ASSET_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, ASSET_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/assetProfileInfo/default", method = RequestMethod.GET) @RequestMapping(value = "/assetProfileInfo/default", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -130,8 +127,7 @@ public class AssetProfileController extends BaseController {
"Referencing non-existing asset profile Id will cause 'Not Found' error. " + NEW_LINE + "Referencing non-existing asset profile Id will cause 'Not Found' error. " + NEW_LINE +
"Asset profile name is unique in the scope of tenant. Only one 'default' asset profile may exist in scope of tenant. " + "Asset profile name is unique in the scope of tenant. Only one 'default' asset profile may exist in scope of tenant. " +
"Remove 'id', 'tenantId' from the request body example (below) to create new Asset Profile entity. " + "Remove 'id', 'tenantId' from the request body example (below) to create new Asset Profile entity. " +
TENANT_AUTHORITY_PARAGRAPH, TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/assetProfile", method = RequestMethod.POST) @RequestMapping(value = "/assetProfile", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@ -145,8 +141,7 @@ public class AssetProfileController extends BaseController {
@ApiOperation(value = "Delete asset profile (deleteAssetProfile)", @ApiOperation(value = "Delete asset profile (deleteAssetProfile)",
notes = "Deletes the asset profile. Referencing non-existing asset profile Id will cause an error. " + notes = "Deletes the asset profile. Referencing non-existing asset profile Id will cause an error. " +
"Can't delete the asset profile if it is referenced by existing assets." + TENANT_AUTHORITY_PARAGRAPH, "Can't delete the asset profile if it is referenced by existing assets." + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/assetProfile/{assetProfileId}", method = RequestMethod.DELETE) @RequestMapping(value = "/assetProfile/{assetProfileId}", method = RequestMethod.DELETE)
@ResponseStatus(value = HttpStatus.OK) @ResponseStatus(value = HttpStatus.OK)
@ -160,8 +155,7 @@ public class AssetProfileController extends BaseController {
} }
@ApiOperation(value = "Make Asset Profile Default (setDefaultAssetProfile)", @ApiOperation(value = "Make Asset Profile Default (setDefaultAssetProfile)",
notes = "Marks asset profile as default within a tenant scope." + TENANT_AUTHORITY_PARAGRAPH, notes = "Marks asset profile as default within a tenant scope." + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/assetProfile/{assetProfileId}/default", method = RequestMethod.POST) @RequestMapping(value = "/assetProfile/{assetProfileId}/default", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@ -177,8 +171,7 @@ public class AssetProfileController extends BaseController {
@ApiOperation(value = "Get Asset Profiles (getAssetProfiles)", @ApiOperation(value = "Get Asset Profiles (getAssetProfiles)",
notes = "Returns a page of asset profile objects owned by tenant. " + notes = "Returns a page of asset profile objects owned by tenant. " +
PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/assetProfiles", params = {"pageSize", "page"}, method = RequestMethod.GET) @RequestMapping(value = "/assetProfiles", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -199,8 +192,7 @@ public class AssetProfileController extends BaseController {
@ApiOperation(value = "Get Asset Profile infos (getAssetProfileInfos)", @ApiOperation(value = "Get Asset Profile infos (getAssetProfileInfos)",
notes = "Returns a page of asset profile info objects owned by tenant. " + notes = "Returns a page of asset profile info objects owned by tenant. " +
PAGE_DATA_PARAMETERS + ASSET_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, PAGE_DATA_PARAMETERS + ASSET_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/assetProfileInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) @RequestMapping(value = "/assetProfileInfos", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody

12
application/src/main/java/org/thingsboard/server/controller/AuditLogController.java

@ -74,8 +74,7 @@ public class AuditLogController extends BaseController {
@ApiOperation(value = "Get audit logs by customer id (getAuditLogsByCustomerId)", @ApiOperation(value = "Get audit logs by customer id (getAuditLogsByCustomerId)",
notes = "Returns a page of audit logs related to the targeted customer entities (devices, assets, etc.), " + notes = "Returns a page of audit logs related to the targeted customer entities (devices, assets, etc.), " +
"and users actions (login, logout, etc.) that belong to this customer. " + "and users actions (login, logout, etc.) that belong to this customer. " +
PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/audit/logs/customer/{customerId}", params = {"pageSize", "page"}, method = RequestMethod.GET) @RequestMapping(value = "/audit/logs/customer/{customerId}", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -108,8 +107,7 @@ public class AuditLogController extends BaseController {
@ApiOperation(value = "Get audit logs by user id (getAuditLogsByUserId)", @ApiOperation(value = "Get audit logs by user id (getAuditLogsByUserId)",
notes = "Returns a page of audit logs related to the actions of targeted user. " + notes = "Returns a page of audit logs related to the actions of targeted user. " +
"For example, RPC call to a particular device, or alarm acknowledgment for a specific device, etc. " + "For example, RPC call to a particular device, or alarm acknowledgment for a specific device, etc. " +
PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/audit/logs/user/{userId}", params = {"pageSize", "page"}, method = RequestMethod.GET) @RequestMapping(value = "/audit/logs/user/{userId}", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -143,8 +141,7 @@ public class AuditLogController extends BaseController {
notes = "Returns a page of audit logs related to the actions on the targeted entity. " + notes = "Returns a page of audit logs related to the actions on the targeted entity. " +
"Basically, this API call is used to get the full lifecycle of some specific entity. " + "Basically, this API call is used to get the full lifecycle of some specific entity. " +
"For example to see when a device was created, updated, assigned to some customer, or even deleted from the system. " + "For example to see when a device was created, updated, assigned to some customer, or even deleted from the system. " +
PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/audit/logs/entity/{entityType}/{entityId}", params = {"pageSize", "page"}, method = RequestMethod.GET) @RequestMapping(value = "/audit/logs/entity/{entityType}/{entityId}", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -179,8 +176,7 @@ public class AuditLogController extends BaseController {
@ApiOperation(value = "Get all audit logs (getAuditLogs)", @ApiOperation(value = "Get all audit logs (getAuditLogs)",
notes = "Returns a page of audit logs related to all entities in the scope of the current user's Tenant. " + notes = "Returns a page of audit logs related to all entities in the scope of the current user's Tenant. " +
PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/audit/logs", params = {"pageSize", "page"}, method = RequestMethod.GET) @RequestMapping(value = "/audit/logs", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody

61
application/src/main/java/org/thingsboard/server/controller/DashboardController.java

@ -133,9 +133,7 @@ public class DashboardController extends BaseController {
} }
@ApiOperation(value = "Get Dashboard Info (getDashboardInfoById)", @ApiOperation(value = "Get Dashboard Info (getDashboardInfoById)",
notes = "Get the information about the dashboard based on 'dashboardId' parameter. " + DASHBOARD_INFO_DEFINITION, notes = "Get the information about the dashboard based on 'dashboardId' parameter. " + DASHBOARD_INFO_DEFINITION)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))
)
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/dashboard/info/{dashboardId}", method = RequestMethod.GET) @RequestMapping(value = "/dashboard/info/{dashboardId}", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -148,8 +146,7 @@ public class DashboardController extends BaseController {
} }
@ApiOperation(value = "Get Dashboard (getDashboardById)", @ApiOperation(value = "Get Dashboard (getDashboardById)",
notes = "Get the dashboard based on 'dashboardId' parameter. " + DASHBOARD_DEFINITION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, notes = "Get the dashboard based on 'dashboardId' parameter. " + DASHBOARD_DEFINITION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))
) )
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/dashboard/{dashboardId}", method = RequestMethod.GET) @RequestMapping(value = "/dashboard/{dashboardId}", method = RequestMethod.GET)
@ -174,8 +171,7 @@ public class DashboardController extends BaseController {
"Specify existing Dashboard id to update the dashboard. " + "Specify existing Dashboard id to update the dashboard. " +
"Referencing non-existing dashboard Id will cause 'Not Found' error. " + "Referencing non-existing dashboard Id will cause 'Not Found' error. " +
"Remove 'id', 'tenantId' and optionally 'customerId' from the request body example (below) to create new Dashboard entity. " + "Remove 'id', 'tenantId' and optionally 'customerId' from the request body example (below) to create new Dashboard entity. " +
TENANT_AUTHORITY_PARAGRAPH, TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/dashboard", method = RequestMethod.POST) @RequestMapping(value = "/dashboard", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@ -203,8 +199,7 @@ public class DashboardController extends BaseController {
@ApiOperation(value = "Assign the Dashboard (assignDashboardToCustomer)", @ApiOperation(value = "Assign the Dashboard (assignDashboardToCustomer)",
notes = "Assign the Dashboard to specified Customer or do nothing if the Dashboard is already assigned to that Customer. " + notes = "Assign the Dashboard to specified Customer or do nothing if the Dashboard is already assigned to that Customer. " +
"Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH, "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/customer/{customerId}/dashboard/{dashboardId}", method = RequestMethod.POST) @RequestMapping(value = "/customer/{customerId}/dashboard/{dashboardId}", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@ -226,8 +221,7 @@ public class DashboardController extends BaseController {
@ApiOperation(value = "Unassign the Dashboard (unassignDashboardFromCustomer)", @ApiOperation(value = "Unassign the Dashboard (unassignDashboardFromCustomer)",
notes = "Unassign the Dashboard from specified Customer or do nothing if the Dashboard is already assigned to that Customer. " + notes = "Unassign the Dashboard from specified Customer or do nothing if the Dashboard is already assigned to that Customer. " +
"Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH, "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/customer/{customerId}/dashboard/{dashboardId}", method = RequestMethod.DELETE) @RequestMapping(value = "/customer/{customerId}/dashboard/{dashboardId}", method = RequestMethod.DELETE)
@ResponseBody @ResponseBody
@ -247,8 +241,7 @@ public class DashboardController extends BaseController {
@ApiOperation(value = "Update the Dashboard Customers (updateDashboardCustomers)", @ApiOperation(value = "Update the Dashboard Customers (updateDashboardCustomers)",
notes = "Updates the list of Customers that this Dashboard is assigned to. Removes previous assignments to customers that are not in the provided list. " + notes = "Updates the list of Customers that this Dashboard is assigned to. Removes previous assignments to customers that are not in the provided list. " +
"Returns the Dashboard object. " + TENANT_AUTHORITY_PARAGRAPH, "Returns the Dashboard object. " + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/dashboard/{dashboardId}/customers", method = RequestMethod.POST) @RequestMapping(value = "/dashboard/{dashboardId}/customers", method = RequestMethod.POST)
@ -267,8 +260,7 @@ public class DashboardController extends BaseController {
@ApiOperation(value = "Adds the Dashboard Customers (addDashboardCustomers)", @ApiOperation(value = "Adds the Dashboard Customers (addDashboardCustomers)",
notes = "Adds the list of Customers to the existing list of assignments for the Dashboard. Keeps previous assignments to customers that are not in the provided list. " + notes = "Adds the list of Customers to the existing list of assignments for the Dashboard. Keeps previous assignments to customers that are not in the provided list. " +
"Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH, "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/dashboard/{dashboardId}/customers/add", method = RequestMethod.POST) @RequestMapping(value = "/dashboard/{dashboardId}/customers/add", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@ -286,8 +278,7 @@ public class DashboardController extends BaseController {
@ApiOperation(value = "Remove the Dashboard Customers (removeDashboardCustomers)", @ApiOperation(value = "Remove the Dashboard Customers (removeDashboardCustomers)",
notes = "Removes the list of Customers from the existing list of assignments for the Dashboard. Keeps other assignments to customers that are not in the provided list. " + notes = "Removes the list of Customers from the existing list of assignments for the Dashboard. Keeps other assignments to customers that are not in the provided list. " +
"Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH, "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/dashboard/{dashboardId}/customers/remove", method = RequestMethod.POST) @RequestMapping(value = "/dashboard/{dashboardId}/customers/remove", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@ -309,8 +300,7 @@ public class DashboardController extends BaseController {
"Be aware that making the dashboard public does not mean that it automatically makes all devices and assets you use in the dashboard to be public." + "Be aware that making the dashboard public does not mean that it automatically makes all devices and assets you use in the dashboard to be public." +
"Use [assign Asset to Public Customer](#!/asset-controller/assignAssetToPublicCustomerUsingPOST) and " + "Use [assign Asset to Public Customer](#!/asset-controller/assignAssetToPublicCustomerUsingPOST) and " +
"[assign Device to Public Customer](#!/device-controller/assignDeviceToPublicCustomerUsingPOST) for this purpose. " + "[assign Device to Public Customer](#!/device-controller/assignDeviceToPublicCustomerUsingPOST) for this purpose. " +
"Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH, "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/customer/public/dashboard/{dashboardId}", method = RequestMethod.POST) @RequestMapping(value = "/customer/public/dashboard/{dashboardId}", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@ -325,8 +315,7 @@ public class DashboardController extends BaseController {
@ApiOperation(value = "Unassign the Dashboard from Public Customer (unassignDashboardFromPublicCustomer)", @ApiOperation(value = "Unassign the Dashboard from Public Customer (unassignDashboardFromPublicCustomer)",
notes = "Unassigns the dashboard from a special, auto-generated 'Public' Customer. Once unassigned, unauthenticated users may no longer browse the dashboard. " + notes = "Unassigns the dashboard from a special, auto-generated 'Public' Customer. Once unassigned, unauthenticated users may no longer browse the dashboard. " +
"Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH, "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/customer/public/dashboard/{dashboardId}", method = RequestMethod.DELETE) @RequestMapping(value = "/customer/public/dashboard/{dashboardId}", method = RequestMethod.DELETE)
@ResponseBody @ResponseBody
@ -341,8 +330,7 @@ public class DashboardController extends BaseController {
@ApiOperation(value = "Get Tenant Dashboards by System Administrator (getTenantDashboards)", @ApiOperation(value = "Get Tenant Dashboards by System Administrator (getTenantDashboards)",
notes = "Returns a page of dashboard info objects owned by tenant. " + DASHBOARD_INFO_DEFINITION + " " + PAGE_DATA_PARAMETERS + notes = "Returns a page of dashboard info objects owned by tenant. " + DASHBOARD_INFO_DEFINITION + " " + PAGE_DATA_PARAMETERS +
SYSTEM_AUTHORITY_PARAGRAPH, SYSTEM_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('SYS_ADMIN')") @PreAuthorize("hasAuthority('SYS_ADMIN')")
@RequestMapping(value = "/tenant/{tenantId}/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET) @RequestMapping(value = "/tenant/{tenantId}/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -367,8 +355,7 @@ public class DashboardController extends BaseController {
@ApiOperation(value = "Get Tenant Dashboards (getTenantDashboards)", @ApiOperation(value = "Get Tenant Dashboards (getTenantDashboards)",
notes = "Returns a page of dashboard info objects owned by the tenant of a current user. " notes = "Returns a page of dashboard info objects owned by the tenant of a current user. "
+ DASHBOARD_INFO_DEFINITION + " " + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, + DASHBOARD_INFO_DEFINITION + " " + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/tenant/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET) @RequestMapping(value = "/tenant/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -396,8 +383,7 @@ public class DashboardController extends BaseController {
@ApiOperation(value = "Get Customer Dashboards (getCustomerDashboards)", @ApiOperation(value = "Get Customer Dashboards (getCustomerDashboards)",
notes = "Returns a page of dashboard info objects owned by the specified customer. " notes = "Returns a page of dashboard info objects owned by the specified customer. "
+ DASHBOARD_INFO_DEFINITION + " " + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, + DASHBOARD_INFO_DEFINITION + " " + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/customer/{customerId}/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET) @RequestMapping(value = "/customer/{customerId}/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -432,8 +418,7 @@ public class DashboardController extends BaseController {
notes = "Returns the home dashboard object that is configured as 'homeDashboardId' parameter in the 'additionalInfo' of the User. " + notes = "Returns the home dashboard object that is configured as 'homeDashboardId' parameter in the 'additionalInfo' of the User. " +
"If 'homeDashboardId' parameter is not set on the User level and the User has authority 'CUSTOMER_USER', check the same parameter for the corresponding Customer. " + "If 'homeDashboardId' parameter is not set on the User level and the User has authority 'CUSTOMER_USER', check the same parameter for the corresponding Customer. " +
"If 'homeDashboardId' parameter is not set on the User and Customer levels then checks the same parameter for the Tenant that owns the user. " "If 'homeDashboardId' parameter is not set on the User and Customer levels then checks the same parameter for the Tenant that owns the user. "
+ DASHBOARD_DEFINITION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, + DASHBOARD_DEFINITION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/dashboard/home", method = RequestMethod.GET) @RequestMapping(value = "/dashboard/home", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -465,8 +450,7 @@ public class DashboardController extends BaseController {
notes = "Returns the home dashboard info object that is configured as 'homeDashboardId' parameter in the 'additionalInfo' of the User. " + notes = "Returns the home dashboard info object that is configured as 'homeDashboardId' parameter in the 'additionalInfo' of the User. " +
"If 'homeDashboardId' parameter is not set on the User level and the User has authority 'CUSTOMER_USER', check the same parameter for the corresponding Customer. " + "If 'homeDashboardId' parameter is not set on the User level and the User has authority 'CUSTOMER_USER', check the same parameter for the corresponding Customer. " +
"If 'homeDashboardId' parameter is not set on the User and Customer levels then checks the same parameter for the Tenant that owns the user. " + "If 'homeDashboardId' parameter is not set on the User and Customer levels then checks the same parameter for the Tenant that owns the user. " +
TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/dashboard/home/info", method = RequestMethod.GET) @RequestMapping(value = "/dashboard/home/info", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -496,8 +480,7 @@ public class DashboardController extends BaseController {
@ApiOperation(value = "Get Tenant Home Dashboard Info (getTenantHomeDashboardInfo)", @ApiOperation(value = "Get Tenant Home Dashboard Info (getTenantHomeDashboardInfo)",
notes = "Returns the home dashboard info object that is configured as 'homeDashboardId' parameter in the 'additionalInfo' of the corresponding tenant. " + notes = "Returns the home dashboard info object that is configured as 'homeDashboardId' parameter in the 'additionalInfo' of the corresponding tenant. " +
TENANT_AUTHORITY_PARAGRAPH, TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/tenant/dashboard/home/info", method = RequestMethod.GET) @RequestMapping(value = "/tenant/dashboard/home/info", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -518,8 +501,7 @@ public class DashboardController extends BaseController {
@ApiOperation(value = "Update Tenant Home Dashboard Info (getTenantHomeDashboardInfo)", @ApiOperation(value = "Update Tenant Home Dashboard Info (getTenantHomeDashboardInfo)",
notes = "Update the home dashboard assignment for the current tenant. " + notes = "Update the home dashboard assignment for the current tenant. " +
TENANT_AUTHORITY_PARAGRAPH, TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/tenant/dashboard/home/info", method = RequestMethod.POST) @RequestMapping(value = "/tenant/dashboard/home/info", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK) @ResponseStatus(value = HttpStatus.OK)
@ -584,8 +566,7 @@ public class DashboardController extends BaseController {
"Second, remote edge service will receive a copy of assignment dashboard " + "Second, remote edge service will receive a copy of assignment dashboard " +
EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION + EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION +
"Third, once dashboard will be delivered to edge service, it's going to be available for usage on remote edge instance." + "Third, once dashboard will be delivered to edge service, it's going to be available for usage on remote edge instance." +
TENANT_AUTHORITY_PARAGRAPH, TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/edge/{edgeId}/dashboard/{dashboardId}", method = RequestMethod.POST) @RequestMapping(value = "/edge/{edgeId}/dashboard/{dashboardId}", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@ -608,8 +589,7 @@ public class DashboardController extends BaseController {
"Second, remote edge service will receive an 'unassign' command to remove dashboard " + "Second, remote edge service will receive an 'unassign' command to remove dashboard " +
EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION + EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION +
"Third, once 'unassign' command will be delivered to edge service, it's going to remove dashboard locally." + "Third, once 'unassign' command will be delivered to edge service, it's going to remove dashboard locally." +
TENANT_AUTHORITY_PARAGRAPH, TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/edge/{edgeId}/dashboard/{dashboardId}", method = RequestMethod.DELETE) @RequestMapping(value = "/edge/{edgeId}/dashboard/{dashboardId}", method = RequestMethod.DELETE)
@ResponseBody @ResponseBody
@ -629,8 +609,7 @@ public class DashboardController extends BaseController {
@ApiOperation(value = "Get Edge Dashboards (getEdgeDashboards)", @ApiOperation(value = "Get Edge Dashboards (getEdgeDashboards)",
notes = "Returns a page of dashboard info objects assigned to the specified edge. " notes = "Returns a page of dashboard info objects assigned to the specified edge. "
+ DASHBOARD_INFO_DEFINITION + " " + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, + DASHBOARD_INFO_DEFINITION + " " + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/edge/{edgeId}/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET) @RequestMapping(value = "/edge/{edgeId}/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody

9
application/src/main/java/org/thingsboard/server/controller/DeviceController.java

@ -534,8 +534,7 @@ public class DeviceController extends BaseController {
} }
@ApiOperation(value = "Get Device Types (getDeviceTypes)", @ApiOperation(value = "Get Device Types (getDeviceTypes)",
notes = "Deprecated. See 'getDeviceProfileNames' API from Device Profile Controller instead." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, notes = "Deprecated. See 'getDeviceProfileNames' API from Device Profile Controller instead." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/device/types", method = RequestMethod.GET) @RequestMapping(value = "/device/types", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -668,8 +667,7 @@ public class DeviceController extends BaseController {
EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION + EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION +
"Second, remote edge service will receive a copy of assignment device " + "Second, remote edge service will receive a copy of assignment device " +
EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION + EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION +
"Third, once device will be delivered to edge service, it's going to be available for usage on remote edge instance." + TENANT_AUTHORITY_PARAGRAPH, "Third, once device will be delivered to edge service, it's going to be available for usage on remote edge instance." + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/edge/{edgeId}/device/{deviceId}", method = RequestMethod.POST) @RequestMapping(value = "/edge/{edgeId}/device/{deviceId}", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@ -693,8 +691,7 @@ public class DeviceController extends BaseController {
EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION + EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION +
"Second, remote edge service will receive an 'unassign' command to remove device " + "Second, remote edge service will receive an 'unassign' command to remove device " +
EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION + EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION +
"Third, once 'unassign' command will be delivered to edge service, it's going to remove device locally." + TENANT_AUTHORITY_PARAGRAPH, "Third, once 'unassign' command will be delivered to edge service, it's going to remove device locally." + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/edge/{edgeId}/device/{deviceId}", method = RequestMethod.DELETE) @RequestMapping(value = "/edge/{edgeId}/device/{deviceId}", method = RequestMethod.DELETE)
@ResponseBody @ResponseBody

27
application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java

@ -86,8 +86,7 @@ public class DeviceProfileController extends BaseController {
@ApiOperation(value = "Get Device Profile (getDeviceProfileById)", @ApiOperation(value = "Get Device Profile (getDeviceProfileById)",
notes = "Fetch the Device Profile object based on the provided Device Profile Id. " + notes = "Fetch the Device Profile object based on the provided Device Profile Id. " +
"The server checks that the device profile is owned by the same tenant. " + TENANT_AUTHORITY_PARAGRAPH, "The server checks that the device profile is owned by the same tenant. " + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/deviceProfile/{deviceProfileId}", method = RequestMethod.GET) @RequestMapping(value = "/deviceProfile/{deviceProfileId}", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -107,8 +106,7 @@ public class DeviceProfileController extends BaseController {
@ApiOperation(value = "Get Device Profile Info (getDeviceProfileInfoById)", @ApiOperation(value = "Get Device Profile Info (getDeviceProfileInfoById)",
notes = "Fetch the Device Profile Info object based on the provided Device Profile Id. " notes = "Fetch the Device Profile Info object based on the provided Device Profile Id. "
+ DEVICE_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, + DEVICE_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/deviceProfileInfo/{deviceProfileId}", method = RequestMethod.GET) @RequestMapping(value = "/deviceProfileInfo/{deviceProfileId}", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -122,8 +120,7 @@ public class DeviceProfileController extends BaseController {
@ApiOperation(value = "Get Default Device Profile (getDefaultDeviceProfileInfo)", @ApiOperation(value = "Get Default Device Profile (getDefaultDeviceProfileInfo)",
notes = "Fetch the Default Device Profile Info object. " + notes = "Fetch the Default Device Profile Info object. " +
DEVICE_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, DEVICE_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/deviceProfileInfo/default", method = RequestMethod.GET) @RequestMapping(value = "/deviceProfileInfo/default", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -136,8 +133,7 @@ public class DeviceProfileController extends BaseController {
"If profile is not set returns a list of unique keys among all profiles. " + "If profile is not set returns a list of unique keys among all profiles. " +
"The call is used for auto-complete in the UI forms. " + "The call is used for auto-complete in the UI forms. " +
"The implementation limits the number of devices that participate in search to 100 as a trade of between accurate results and time-consuming queries. " + "The implementation limits the number of devices that participate in search to 100 as a trade of between accurate results and time-consuming queries. " +
TENANT_AUTHORITY_PARAGRAPH, TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/deviceProfile/devices/keys/timeseries", method = RequestMethod.GET) @RequestMapping(value = "/deviceProfile/devices/keys/timeseries", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -160,8 +156,7 @@ public class DeviceProfileController extends BaseController {
"If profile is not set returns a list of unique keys among all profiles. " + "If profile is not set returns a list of unique keys among all profiles. " +
"The call is used for auto-complete in the UI forms. " + "The call is used for auto-complete in the UI forms. " +
"The implementation limits the number of devices that participate in search to 100 as a trade of between accurate results and time-consuming queries. " + "The implementation limits the number of devices that participate in search to 100 as a trade of between accurate results and time-consuming queries. " +
TENANT_AUTHORITY_PARAGRAPH, TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/deviceProfile/devices/keys/attributes", method = RequestMethod.GET) @RequestMapping(value = "/deviceProfile/devices/keys/attributes", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -186,8 +181,7 @@ public class DeviceProfileController extends BaseController {
"Referencing non-existing device profile Id will cause 'Not Found' error. " + NEW_LINE + "Referencing non-existing device profile Id will cause 'Not Found' error. " + NEW_LINE +
"Device profile name is unique in the scope of tenant. Only one 'default' device profile may exist in scope of tenant." + DEVICE_PROFILE_DATA + "Device profile name is unique in the scope of tenant. Only one 'default' device profile may exist in scope of tenant." + DEVICE_PROFILE_DATA +
"Remove 'id', 'tenantId' from the request body example (below) to create new Device Profile entity. " + "Remove 'id', 'tenantId' from the request body example (below) to create new Device Profile entity. " +
TENANT_AUTHORITY_PARAGRAPH, TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/deviceProfile", method = RequestMethod.POST) @RequestMapping(value = "/deviceProfile", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@ -215,8 +209,7 @@ public class DeviceProfileController extends BaseController {
} }
@ApiOperation(value = "Make Device Profile Default (setDefaultDeviceProfile)", @ApiOperation(value = "Make Device Profile Default (setDefaultDeviceProfile)",
notes = "Marks device profile as default within a tenant scope." + TENANT_AUTHORITY_PARAGRAPH, notes = "Marks device profile as default within a tenant scope." + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/deviceProfile/{deviceProfileId}/default", method = RequestMethod.POST) @RequestMapping(value = "/deviceProfile/{deviceProfileId}/default", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@ -232,8 +225,7 @@ public class DeviceProfileController extends BaseController {
@ApiOperation(value = "Get Device Profiles (getDeviceProfiles)", @ApiOperation(value = "Get Device Profiles (getDeviceProfiles)",
notes = "Returns a page of devices profile objects owned by tenant. " + notes = "Returns a page of devices profile objects owned by tenant. " +
PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/deviceProfiles", params = {"pageSize", "page"}, method = RequestMethod.GET) @RequestMapping(value = "/deviceProfiles", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -254,8 +246,7 @@ public class DeviceProfileController extends BaseController {
@ApiOperation(value = "Get Device Profiles for transport type (getDeviceProfileInfos)", @ApiOperation(value = "Get Device Profiles for transport type (getDeviceProfileInfos)",
notes = "Returns a page of devices profile info objects owned by tenant. " + notes = "Returns a page of devices profile info objects owned by tenant. " +
PAGE_DATA_PARAMETERS + DEVICE_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, PAGE_DATA_PARAMETERS + DEVICE_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/deviceProfileInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) @RequestMapping(value = "/deviceProfileInfos", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody

53
application/src/main/java/org/thingsboard/server/controller/EdgeController.java

@ -120,8 +120,7 @@ public class EdgeController extends BaseController {
} }
@ApiOperation(value = "Get Edge (getEdgeById)", @ApiOperation(value = "Get Edge (getEdgeById)",
notes = "Get the Edge object based on the provided Edge Id. " + EDGE_SECURITY_CHECK + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, notes = "Get the Edge object based on the provided Edge Id. " + EDGE_SECURITY_CHECK + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/edge/{edgeId}", method = RequestMethod.GET) @RequestMapping(value = "/edge/{edgeId}", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -133,8 +132,7 @@ public class EdgeController extends BaseController {
} }
@ApiOperation(value = "Get Edge Info (getEdgeInfoById)", @ApiOperation(value = "Get Edge Info (getEdgeInfoById)",
notes = "Get the Edge Info object based on the provided Edge Id. " + EDGE_SECURITY_CHECK + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, notes = "Get the Edge Info object based on the provided Edge Id. " + EDGE_SECURITY_CHECK + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/edge/info/{edgeId}", method = RequestMethod.GET) @RequestMapping(value = "/edge/info/{edgeId}", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -152,8 +150,7 @@ public class EdgeController extends BaseController {
"Referencing non-existing Edge Id will cause 'Not Found' error." + "Referencing non-existing Edge Id will cause 'Not Found' error." +
"\n\nEdge name is unique in the scope of tenant. Use unique identifiers like MAC or IMEI for the edge names and non-unique 'label' field for user-friendly visualization purposes." + "\n\nEdge name is unique in the scope of tenant. Use unique identifiers like MAC or IMEI for the edge names and non-unique 'label' field for user-friendly visualization purposes." +
"Remove 'id', 'tenantId' and optionally 'customerId' from the request body example (below) to create new Edge entity. " + "Remove 'id', 'tenantId' and optionally 'customerId' from the request body example (below) to create new Edge entity. " +
TENANT_AUTHORITY_PARAGRAPH, TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/edge", method = RequestMethod.POST) @RequestMapping(value = "/edge", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@ -193,7 +190,7 @@ public class EdgeController extends BaseController {
@ApiOperation(value = "Get Tenant Edges (getEdges)", @ApiOperation(value = "Get Tenant Edges (getEdges)",
notes = "Returns a page of edges owned by tenant. " + notes = "Returns a page of edges owned by tenant. " +
PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/edges", params = {"pageSize", "page"}, method = RequestMethod.GET) @RequestMapping(value = "/edges", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -213,8 +210,7 @@ public class EdgeController extends BaseController {
} }
@ApiOperation(value = "Assign edge to customer (assignEdgeToCustomer)", @ApiOperation(value = "Assign edge to customer (assignEdgeToCustomer)",
notes = "Creates assignment of the edge to customer. Customer will be able to query edge afterwards." + TENANT_AUTHORITY_PARAGRAPH, notes = "Creates assignment of the edge to customer. Customer will be able to query edge afterwards." + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/customer/{customerId}/edge/{edgeId}", method = RequestMethod.POST) @RequestMapping(value = "/customer/{customerId}/edge/{edgeId}", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@ -232,8 +228,7 @@ public class EdgeController extends BaseController {
} }
@ApiOperation(value = "Unassign edge from customer (unassignEdgeFromCustomer)", @ApiOperation(value = "Unassign edge from customer (unassignEdgeFromCustomer)",
notes = "Clears assignment of the edge to customer. Customer will not be able to query edge afterwards." + TENANT_AUTHORITY_PARAGRAPH, notes = "Clears assignment of the edge to customer. Customer will not be able to query edge afterwards." + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/customer/edge/{edgeId}", method = RequestMethod.DELETE) @RequestMapping(value = "/customer/edge/{edgeId}", method = RequestMethod.DELETE)
@ResponseBody @ResponseBody
@ -253,8 +248,7 @@ public class EdgeController extends BaseController {
@ApiOperation(value = "Make edge publicly available (assignEdgeToPublicCustomer)", @ApiOperation(value = "Make edge publicly available (assignEdgeToPublicCustomer)",
notes = "Edge will be available for non-authorized (not logged-in) users. " + notes = "Edge will be available for non-authorized (not logged-in) users. " +
"This is useful to create dashboards that you plan to share/embed on a publicly available website. " + "This is useful to create dashboards that you plan to share/embed on a publicly available website. " +
"However, users that are logged-in and belong to different tenant will not be able to access the edge." + TENANT_AUTHORITY_PARAGRAPH, "However, users that are logged-in and belong to different tenant will not be able to access the edge." + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/customer/public/edge/{edgeId}", method = RequestMethod.POST) @RequestMapping(value = "/customer/public/edge/{edgeId}", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@ -268,7 +262,7 @@ public class EdgeController extends BaseController {
@ApiOperation(value = "Get Tenant Edges (getTenantEdges)", @ApiOperation(value = "Get Tenant Edges (getTenantEdges)",
notes = "Returns a page of edges owned by tenant. " + notes = "Returns a page of edges owned by tenant. " +
PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/tenant/edges", params = {"pageSize", "page"}, method = RequestMethod.GET) @RequestMapping(value = "/tenant/edges", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -296,8 +290,7 @@ public class EdgeController extends BaseController {
@ApiOperation(value = "Get Tenant Edge Infos (getTenantEdgeInfos)", @ApiOperation(value = "Get Tenant Edge Infos (getTenantEdgeInfos)",
notes = "Returns a page of edges info objects owned by tenant. " + notes = "Returns a page of edges info objects owned by tenant. " +
PAGE_DATA_PARAMETERS + EDGE_INFO_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH, PAGE_DATA_PARAMETERS + EDGE_INFO_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/tenant/edgeInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) @RequestMapping(value = "/tenant/edgeInfos", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -325,8 +318,7 @@ public class EdgeController extends BaseController {
@ApiOperation(value = "Get Tenant Edge (getTenantEdge)", @ApiOperation(value = "Get Tenant Edge (getTenantEdge)",
notes = "Requested edge must be owned by tenant or customer that the user belongs to. " + notes = "Requested edge must be owned by tenant or customer that the user belongs to. " +
"Edge name is an unique property of edge. So it can be used to identify the edge." + TENANT_AUTHORITY_PARAGRAPH, "Edge name is an unique property of edge. So it can be used to identify the edge." + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/tenant/edges", params = {"edgeName"}, method = RequestMethod.GET) @RequestMapping(value = "/tenant/edges", params = {"edgeName"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -338,8 +330,7 @@ public class EdgeController extends BaseController {
@ApiOperation(value = "Set root rule chain for provided edge (setEdgeRootRuleChain)", @ApiOperation(value = "Set root rule chain for provided edge (setEdgeRootRuleChain)",
notes = "Change root rule chain of the edge to the new provided rule chain. \n" + notes = "Change root rule chain of the edge to the new provided rule chain. \n" +
"This operation will send a notification to update root rule chain on remote edge service." + TENANT_AUTHORITY_PARAGRAPH, "This operation will send a notification to update root rule chain on remote edge service." + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/edge/{edgeId}/{ruleChainId}/root", method = RequestMethod.POST) @RequestMapping(value = "/edge/{edgeId}/{ruleChainId}/root", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@ -359,7 +350,7 @@ public class EdgeController extends BaseController {
@ApiOperation(value = "Get Customer Edges (getCustomerEdges)", @ApiOperation(value = "Get Customer Edges (getCustomerEdges)",
notes = "Returns a page of edges objects assigned to customer. " + notes = "Returns a page of edges objects assigned to customer. " +
PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/customer/{customerId}/edges", params = {"pageSize", "page"}, method = RequestMethod.GET) @RequestMapping(value = "/customer/{customerId}/edges", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -395,7 +386,7 @@ public class EdgeController extends BaseController {
@ApiOperation(value = "Get Customer Edge Infos (getCustomerEdgeInfos)", @ApiOperation(value = "Get Customer Edge Infos (getCustomerEdgeInfos)",
notes = "Returns a page of edges info objects assigned to customer. " + notes = "Returns a page of edges info objects assigned to customer. " +
PAGE_DATA_PARAMETERS + EDGE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) PAGE_DATA_PARAMETERS + EDGE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/customer/{customerId}/edgeInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) @RequestMapping(value = "/customer/{customerId}/edgeInfos", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -430,8 +421,7 @@ public class EdgeController extends BaseController {
} }
@ApiOperation(value = "Get Edges By Ids (getEdgesByIds)", @ApiOperation(value = "Get Edges By Ids (getEdgesByIds)",
notes = "Requested edges must be owned by tenant or assigned to customer which user is performing the request." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, notes = "Requested edges must be owned by tenant or assigned to customer which user is performing the request." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/edges", params = {"edgeIds"}, method = RequestMethod.GET) @RequestMapping(value = "/edges", params = {"edgeIds"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -459,8 +449,7 @@ public class EdgeController extends BaseController {
@ApiOperation(value = "Find related edges (findByQuery)", @ApiOperation(value = "Find related edges (findByQuery)",
notes = "Returns all edges that are related to the specific entity. " + notes = "Returns all edges that are related to the specific entity. " +
"The entity id, relation type, edge types, depth of the search, and other query parameters defined using complex 'EdgeSearchQuery' object. " + "The entity id, relation type, edge types, depth of the search, and other query parameters defined using complex 'EdgeSearchQuery' object. " +
"See 'Model' tab of the Parameters for more info." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, "See 'Model' tab of the Parameters for more info." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/edges", method = RequestMethod.POST) @RequestMapping(value = "/edges", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@ -485,8 +474,7 @@ public class EdgeController extends BaseController {
@ApiOperation(value = "Get Edge Types (getEdgeTypes)", @ApiOperation(value = "Get Edge Types (getEdgeTypes)",
notes = "Returns a set of unique edge types based on edges that are either owned by the tenant or assigned to the customer which user is performing the request." notes = "Returns a set of unique edge types based on edges that are either owned by the tenant or assigned to the customer which user is performing the request."
+ TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/edge/types", method = RequestMethod.GET) @RequestMapping(value = "/edge/types", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -542,8 +530,7 @@ public class EdgeController extends BaseController {
} }
@ApiOperation(value = "Import the bulk of edges (processEdgesBulkImport)", @ApiOperation(value = "Import the bulk of edges (processEdgesBulkImport)",
notes = "There's an ability to import the bulk of edges using the only .csv file." + TENANT_AUTHORITY_PARAGRAPH, notes = "There's an ability to import the bulk of edges using the only .csv file." + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@PostMapping("/edge/bulk_import") @PostMapping("/edge/bulk_import")
public BulkImportResult<Edge> processEdgesBulkImport(@RequestBody BulkImportRequest request) throws Exception { public BulkImportResult<Edge> processEdgesBulkImport(@RequestBody BulkImportRequest request) throws Exception {
@ -557,8 +544,7 @@ public class EdgeController extends BaseController {
} }
@ApiOperation(value = "Get Edge Install Instructions (getEdgeInstallInstructions)", @ApiOperation(value = "Get Edge Install Instructions (getEdgeInstallInstructions)",
notes = "Get an install instructions for provided edge id." + TENANT_AUTHORITY_PARAGRAPH, notes = "Get an install instructions for provided edge id." + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/edge/instructions/install/{edgeId}/{method}", method = RequestMethod.GET) @RequestMapping(value = "/edge/instructions/install/{edgeId}/{method}", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -579,8 +565,7 @@ public class EdgeController extends BaseController {
} }
@ApiOperation(value = "Get Edge Upgrade Instructions (getEdgeUpgradeInstructions)", @ApiOperation(value = "Get Edge Upgrade Instructions (getEdgeUpgradeInstructions)",
notes = "Get an upgrade instructions for provided edge version." + TENANT_AUTHORITY_PARAGRAPH, notes = "Get an upgrade instructions for provided edge version." + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/edge/instructions/upgrade/{edgeVersion}/{method}", method = RequestMethod.GET) @RequestMapping(value = "/edge/instructions/upgrade/{edgeVersion}/{method}", method = RequestMethod.GET)
@ResponseBody @ResponseBody

2
application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java

@ -60,7 +60,7 @@ public class EdgeEventController extends BaseController {
@ApiOperation(value = "Get Edge Events (getEdgeEvents)", @ApiOperation(value = "Get Edge Events (getEdgeEvents)",
notes = "Returns a page of edge events for the requested edge. " + notes = "Returns a page of edge events for the requested edge. " +
PAGE_DATA_PARAMETERS, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) PAGE_DATA_PARAMETERS)
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/edge/{edgeId}/events", method = RequestMethod.GET) @RequestMapping(value = "/edge/{edgeId}/events", method = RequestMethod.GET)
@ResponseBody @ResponseBody

25
application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java

@ -135,8 +135,7 @@ public class EntityRelationController extends BaseController {
} }
@ApiOperation(value = "Get Relation (getRelation)", @ApiOperation(value = "Get Relation (getRelation)",
notes = "Returns relation object between two specified entities if present. Otherwise throws exception. " + SECURITY_CHECKS_ENTITIES_DESCRIPTION, notes = "Returns relation object between two specified entities if present. Otherwise throws exception. " + SECURITY_CHECKS_ENTITIES_DESCRIPTION)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/relation", method = RequestMethod.GET, params = {FROM_ID, FROM_TYPE, RELATION_TYPE, TO_ID, TO_TYPE}) @RequestMapping(value = "/relation", method = RequestMethod.GET, params = {FROM_ID, FROM_TYPE, RELATION_TYPE, TO_ID, TO_TYPE})
@ResponseBody @ResponseBody
@ -161,8 +160,7 @@ public class EntityRelationController extends BaseController {
@ApiOperation(value = "Get List of Relations (findByFrom)", @ApiOperation(value = "Get List of Relations (findByFrom)",
notes = "Returns list of relation objects for the specified entity by the 'from' direction. " + notes = "Returns list of relation objects for the specified entity by the 'from' direction. " +
SECURITY_CHECKS_ENTITY_DESCRIPTION, SECURITY_CHECKS_ENTITY_DESCRIPTION)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/relations", method = RequestMethod.GET, params = {FROM_ID, FROM_TYPE}) @RequestMapping(value = "/relations", method = RequestMethod.GET, params = {FROM_ID, FROM_TYPE})
@ResponseBody @ResponseBody
@ -180,8 +178,7 @@ public class EntityRelationController extends BaseController {
@ApiOperation(value = "Get List of Relation Infos (findInfoByFrom)", @ApiOperation(value = "Get List of Relation Infos (findInfoByFrom)",
notes = "Returns list of relation info objects for the specified entity by the 'from' direction. " + notes = "Returns list of relation info objects for the specified entity by the 'from' direction. " +
SECURITY_CHECKS_ENTITY_DESCRIPTION + " " + RELATION_INFO_DESCRIPTION, SECURITY_CHECKS_ENTITY_DESCRIPTION + " " + RELATION_INFO_DESCRIPTION)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/relations/info", method = RequestMethod.GET, params = {FROM_ID, FROM_TYPE}) @RequestMapping(value = "/relations/info", method = RequestMethod.GET, params = {FROM_ID, FROM_TYPE})
@ResponseBody @ResponseBody
@ -199,8 +196,7 @@ public class EntityRelationController extends BaseController {
@ApiOperation(value = "Get List of Relations (findByFrom)", @ApiOperation(value = "Get List of Relations (findByFrom)",
notes = "Returns list of relation objects for the specified entity by the 'from' direction and relation type. " + notes = "Returns list of relation objects for the specified entity by the 'from' direction and relation type. " +
SECURITY_CHECKS_ENTITY_DESCRIPTION, SECURITY_CHECKS_ENTITY_DESCRIPTION)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/relations", method = RequestMethod.GET, params = {FROM_ID, FROM_TYPE, RELATION_TYPE}) @RequestMapping(value = "/relations", method = RequestMethod.GET, params = {FROM_ID, FROM_TYPE, RELATION_TYPE})
@ResponseBody @ResponseBody
@ -220,8 +216,7 @@ public class EntityRelationController extends BaseController {
@ApiOperation(value = "Get List of Relations (findByTo)", @ApiOperation(value = "Get List of Relations (findByTo)",
notes = "Returns list of relation objects for the specified entity by the 'to' direction. " + notes = "Returns list of relation objects for the specified entity by the 'to' direction. " +
SECURITY_CHECKS_ENTITY_DESCRIPTION, SECURITY_CHECKS_ENTITY_DESCRIPTION)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/relations", method = RequestMethod.GET, params = {TO_ID, TO_TYPE}) @RequestMapping(value = "/relations", method = RequestMethod.GET, params = {TO_ID, TO_TYPE})
@ResponseBody @ResponseBody
@ -239,8 +234,7 @@ public class EntityRelationController extends BaseController {
@ApiOperation(value = "Get List of Relation Infos (findInfoByTo)", @ApiOperation(value = "Get List of Relation Infos (findInfoByTo)",
notes = "Returns list of relation info objects for the specified entity by the 'to' direction. " + notes = "Returns list of relation info objects for the specified entity by the 'to' direction. " +
SECURITY_CHECKS_ENTITY_DESCRIPTION + " " + RELATION_INFO_DESCRIPTION, SECURITY_CHECKS_ENTITY_DESCRIPTION + " " + RELATION_INFO_DESCRIPTION)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/relations/info", method = RequestMethod.GET, params = {TO_ID, TO_TYPE}) @RequestMapping(value = "/relations/info", method = RequestMethod.GET, params = {TO_ID, TO_TYPE})
@ResponseBody @ResponseBody
@ -258,8 +252,7 @@ public class EntityRelationController extends BaseController {
@ApiOperation(value = "Get List of Relations (findByTo)", @ApiOperation(value = "Get List of Relations (findByTo)",
notes = "Returns list of relation objects for the specified entity by the 'to' direction and relation type. " + notes = "Returns list of relation objects for the specified entity by the 'to' direction and relation type. " +
SECURITY_CHECKS_ENTITY_DESCRIPTION, SECURITY_CHECKS_ENTITY_DESCRIPTION)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/relations", method = RequestMethod.GET, params = {TO_ID, TO_TYPE, RELATION_TYPE}) @RequestMapping(value = "/relations", method = RequestMethod.GET, params = {TO_ID, TO_TYPE, RELATION_TYPE})
@ResponseBody @ResponseBody
@ -280,7 +273,7 @@ public class EntityRelationController extends BaseController {
@ApiOperation(value = "Find related entities (findByQuery)", @ApiOperation(value = "Find related entities (findByQuery)",
notes = "Returns all entities that are related to the specific entity. " + notes = "Returns all entities that are related to the specific entity. " +
"The entity id, relation type, entity types, depth of the search, and other query parameters defined using complex 'EntityRelationsQuery' object. " + "The entity id, relation type, entity types, depth of the search, and other query parameters defined using complex 'EntityRelationsQuery' object. " +
"See 'Model' tab of the Parameters for more info.", responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) "See 'Model' tab of the Parameters for more info.")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/relations", method = RequestMethod.POST) @RequestMapping(value = "/relations", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@ -296,7 +289,7 @@ public class EntityRelationController extends BaseController {
@ApiOperation(value = "Find related entity infos (findInfoByQuery)", @ApiOperation(value = "Find related entity infos (findInfoByQuery)",
notes = "Returns all entity infos that are related to the specific entity. " + notes = "Returns all entity infos that are related to the specific entity. " +
"The entity id, relation type, entity types, depth of the search, and other query parameters defined using complex 'EntityRelationsQuery' object. " + "The entity id, relation type, entity types, depth of the search, and other query parameters defined using complex 'EntityRelationsQuery' object. " +
"See 'Model' tab of the Parameters for more info. " + RELATION_INFO_DESCRIPTION, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) "See 'Model' tab of the Parameters for more info. " + RELATION_INFO_DESCRIPTION)
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/relations/info", method = RequestMethod.POST) @RequestMapping(value = "/relations/info", method = RequestMethod.POST)
@ResponseBody @ResponseBody

18
application/src/main/java/org/thingsboard/server/controller/EntityViewController.java

@ -97,8 +97,7 @@ public class EntityViewController extends BaseController {
@ApiOperation(value = "Get entity view (getEntityViewById)", @ApiOperation(value = "Get entity view (getEntityViewById)",
notes = "Fetch the EntityView object based on the provided entity view id. " notes = "Fetch the EntityView object based on the provided entity view id. "
+ ENTITY_VIEW_DESCRIPTION + MODEL_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, + ENTITY_VIEW_DESCRIPTION + MODEL_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/entityView/{entityViewId}", method = RequestMethod.GET) @RequestMapping(value = "/entityView/{entityViewId}", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -111,8 +110,7 @@ public class EntityViewController extends BaseController {
@ApiOperation(value = "Get Entity View info (getEntityViewInfoById)", @ApiOperation(value = "Get Entity View info (getEntityViewInfoById)",
notes = "Fetch the Entity View info object based on the provided Entity View Id. " notes = "Fetch the Entity View info object based on the provided Entity View Id. "
+ ENTITY_VIEW_INFO_DESCRIPTION + MODEL_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, + ENTITY_VIEW_INFO_DESCRIPTION + MODEL_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/entityView/info/{entityViewId}", method = RequestMethod.GET) @RequestMapping(value = "/entityView/info/{entityViewId}", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -127,8 +125,7 @@ public class EntityViewController extends BaseController {
@ApiOperation(value = "Save or update entity view (saveEntityView)", @ApiOperation(value = "Save or update entity view (saveEntityView)",
notes = ENTITY_VIEW_DESCRIPTION + MODEL_DESCRIPTION + notes = ENTITY_VIEW_DESCRIPTION + MODEL_DESCRIPTION +
"Remove 'id', 'tenantId' and optionally 'customerId' from the request body example (below) to create new Entity View entity." + "Remove 'id', 'tenantId' and optionally 'customerId' from the request body example (below) to create new Entity View entity." +
TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/entityView", method = RequestMethod.POST) @RequestMapping(value = "/entityView", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@ -162,8 +159,7 @@ public class EntityViewController extends BaseController {
} }
@ApiOperation(value = "Get Entity View by name (getTenantEntityView)", @ApiOperation(value = "Get Entity View by name (getTenantEntityView)",
notes = "Fetch the Entity View object based on the tenant id and entity view name. " + TENANT_AUTHORITY_PARAGRAPH, notes = "Fetch the Entity View object based on the tenant id and entity view name. " + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/tenant/entityViews", params = {"entityViewName"}, method = RequestMethod.GET) @RequestMapping(value = "/tenant/entityViews", params = {"entityViewName"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -399,8 +395,7 @@ public class EntityViewController extends BaseController {
EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION + EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION +
"Second, remote edge service will receive a copy of assignment entity view " + "Second, remote edge service will receive a copy of assignment entity view " +
EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION + EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION +
"Third, once entity view will be delivered to edge service, it's going to be available for usage on remote edge instance.", "Third, once entity view will be delivered to edge service, it's going to be available for usage on remote edge instance.")
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/edge/{edgeId}/entityView/{entityViewId}", method = RequestMethod.POST) @RequestMapping(value = "/edge/{edgeId}/entityView/{entityViewId}", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@ -424,8 +419,7 @@ public class EntityViewController extends BaseController {
EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION + EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION +
"Second, remote edge service will receive an 'unassign' command to remove entity view " + "Second, remote edge service will receive an 'unassign' command to remove entity view " +
EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION + EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION +
"Third, once 'unassign' command will be delivered to edge service, it's going to remove entity view locally.", "Third, once 'unassign' command will be delivered to edge service, it's going to remove entity view locally.")
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/edge/{edgeId}/entityView/{entityViewId}", method = RequestMethod.DELETE) @RequestMapping(value = "/edge/{edgeId}/entityView/{entityViewId}", method = RequestMethod.DELETE)
@ResponseBody @ResponseBody

7
application/src/main/java/org/thingsboard/server/controller/EventController.java

@ -108,7 +108,7 @@ public class EventController extends BaseController {
@ApiOperation(value = "Get Events by type (getEvents)", @ApiOperation(value = "Get Events by type (getEvents)",
notes = "Returns a page of events for specified entity by specifying event type. " + notes = "Returns a page of events for specified entity by specifying event type. " +
PAGE_DATA_PARAMETERS, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) PAGE_DATA_PARAMETERS)
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/events/{entityType}/{entityId}/{eventType}", method = RequestMethod.GET) @RequestMapping(value = "/events/{entityType}/{entityId}/{eventType}", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -150,7 +150,7 @@ public class EventController extends BaseController {
"The call was deprecated to improve the performance of the system. " + "The call was deprecated to improve the performance of the system. " +
"Current implementation will return 'Lifecycle' events only. " + "Current implementation will return 'Lifecycle' events only. " +
"Use 'Get events by type' or 'Get events by filter' instead. " + "Use 'Get events by type' or 'Get events by filter' instead. " +
PAGE_DATA_PARAMETERS, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) PAGE_DATA_PARAMETERS)
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/events/{entityType}/{entityId}", method = RequestMethod.GET) @RequestMapping(value = "/events/{entityType}/{entityId}", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -190,8 +190,7 @@ public class EventController extends BaseController {
@ApiOperation(value = "Get Events by event filter (getEvents)", @ApiOperation(value = "Get Events by event filter (getEvents)",
notes = "Returns a page of events for the chosen entity by specifying the event filter. " + notes = "Returns a page of events for the chosen entity by specifying the event filter. " +
PAGE_DATA_PARAMETERS + NEW_LINE + PAGE_DATA_PARAMETERS + NEW_LINE +
EVENT_FILTER_DEFINITION, EVENT_FILTER_DEFINITION)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/events/{entityType}/{entityId}", method = RequestMethod.POST) @RequestMapping(value = "/events/{entityType}/{entityId}", method = RequestMethod.POST)
@ResponseBody @ResponseBody

3
application/src/main/java/org/thingsboard/server/controller/Lwm2mController.java

@ -59,8 +59,7 @@ public class Lwm2mController extends BaseController {
@ApiOperation(value = "Get Lwm2m Bootstrap SecurityInfo (getLwm2mBootstrapSecurityInfo)", @ApiOperation(value = "Get Lwm2m Bootstrap SecurityInfo (getLwm2mBootstrapSecurityInfo)",
notes = "Get the Lwm2m Bootstrap SecurityInfo object (of the current server) based on the provided isBootstrapServer parameter. If isBootstrapServer == true, get the parameters of the current Bootstrap Server. If isBootstrapServer == false, get the parameters of the current Lwm2m Server. Used for client settings when starting the client in Bootstrap mode. " + notes = "Get the Lwm2m Bootstrap SecurityInfo object (of the current server) based on the provided isBootstrapServer parameter. If isBootstrapServer == true, get the parameters of the current Bootstrap Server. If isBootstrapServer == false, get the parameters of the current Lwm2m Server. Used for client settings when starting the client in Bootstrap mode. " +
TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/lwm2m/deviceProfile/bootstrap/{isBootstrapServer}", method = RequestMethod.GET) @RequestMapping(value = "/lwm2m/deviceProfile/bootstrap/{isBootstrapServer}", method = RequestMethod.GET)
@ResponseBody @ResponseBody

19
application/src/main/java/org/thingsboard/server/controller/OtaPackageController.java

@ -105,8 +105,7 @@ public class OtaPackageController extends BaseController {
@ApiOperation(value = "Get OTA Package Info (getOtaPackageInfoById)", @ApiOperation(value = "Get OTA Package Info (getOtaPackageInfoById)",
notes = "Fetch the OTA Package Info object based on the provided OTA Package Id. " + notes = "Fetch the OTA Package Info object based on the provided OTA Package Id. " +
OTA_PACKAGE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, OTA_PACKAGE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/otaPackage/info/{otaPackageId}", method = RequestMethod.GET) @RequestMapping(value = "/otaPackage/info/{otaPackageId}", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -119,8 +118,7 @@ public class OtaPackageController extends BaseController {
@ApiOperation(value = "Get OTA Package (getOtaPackageById)", @ApiOperation(value = "Get OTA Package (getOtaPackageById)",
notes = "Fetch the OTA Package object based on the provided OTA Package Id. " + notes = "Fetch the OTA Package object based on the provided OTA Package Id. " +
"The server checks that the OTA Package is owned by the same tenant. " + OTA_PACKAGE_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH, "The server checks that the OTA Package is owned by the same tenant. " + OTA_PACKAGE_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/otaPackage/{otaPackageId}", method = RequestMethod.GET) @RequestMapping(value = "/otaPackage/{otaPackageId}", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -136,8 +134,7 @@ public class OtaPackageController extends BaseController {
"The newly created OTA Package id will be present in the response. " + "The newly created OTA Package id will be present in the response. " +
"Specify existing OTA Package id to update the OTA Package Info. " + "Specify existing OTA Package id to update the OTA Package Info. " +
"Referencing non-existing OTA Package Id will cause 'Not Found' error. " + "Referencing non-existing OTA Package Id will cause 'Not Found' error. " +
"\n\nOTA Package combination of the title with the version is unique in the scope of tenant. " + TENANT_AUTHORITY_PARAGRAPH, "\n\nOTA Package combination of the title with the version is unique in the scope of tenant. " + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/otaPackage", method = RequestMethod.POST) @RequestMapping(value = "/otaPackage", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@ -151,7 +148,6 @@ public class OtaPackageController extends BaseController {
@ApiOperation(value = "Save OTA Package data (saveOtaPackageData)", @ApiOperation(value = "Save OTA Package data (saveOtaPackageData)",
notes = "Update the OTA Package. Adds the date to the existing OTA Package Info" + TENANT_AUTHORITY_PARAGRAPH, notes = "Update the OTA Package. Adds the date to the existing OTA Package Info" + TENANT_AUTHORITY_PARAGRAPH,
responses = @ApiResponse(content = @Content(mediaType = APPLICATION_JSON_VALUE)),
requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(content = @Content(mediaType = MULTIPART_FORM_DATA_VALUE))) requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(content = @Content(mediaType = MULTIPART_FORM_DATA_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/otaPackage/{otaPackageId}", method = RequestMethod.POST, consumes = MULTIPART_FORM_DATA_VALUE) @RequestMapping(value = "/otaPackage/{otaPackageId}", method = RequestMethod.POST, consumes = MULTIPART_FORM_DATA_VALUE)
@ -176,8 +172,7 @@ public class OtaPackageController extends BaseController {
@ApiOperation(value = "Get OTA Package Infos (getOtaPackages)", @ApiOperation(value = "Get OTA Package Infos (getOtaPackages)",
notes = "Returns a page of OTA Package Info objects owned by tenant. " + notes = "Returns a page of OTA Package Info objects owned by tenant. " +
PAGE_DATA_PARAMETERS + OTA_PACKAGE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, PAGE_DATA_PARAMETERS + OTA_PACKAGE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/otaPackages", method = RequestMethod.GET) @RequestMapping(value = "/otaPackages", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -197,8 +192,7 @@ public class OtaPackageController extends BaseController {
@ApiOperation(value = "Get OTA Package Infos (getOtaPackages)", @ApiOperation(value = "Get OTA Package Infos (getOtaPackages)",
notes = "Returns a page of OTA Package Info objects owned by tenant. " + notes = "Returns a page of OTA Package Info objects owned by tenant. " +
PAGE_DATA_PARAMETERS + OTA_PACKAGE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, PAGE_DATA_PARAMETERS + OTA_PACKAGE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/otaPackages/{deviceProfileId}/{type}", method = RequestMethod.GET) @RequestMapping(value = "/otaPackages/{deviceProfileId}/{type}", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -225,8 +219,7 @@ public class OtaPackageController extends BaseController {
@ApiOperation(value = "Delete OTA Package (deleteOtaPackage)", @ApiOperation(value = "Delete OTA Package (deleteOtaPackage)",
notes = "Deletes the OTA Package. Referencing non-existing OTA Package Id will cause an error. " + notes = "Deletes the OTA Package. Referencing non-existing OTA Package Id will cause an error. " +
"Can't delete the OTA Package if it is referenced by existing devices or device profile." + TENANT_AUTHORITY_PARAGRAPH, "Can't delete the OTA Package if it is referenced by existing devices or device profile." + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/otaPackage/{otaPackageId}", method = RequestMethod.DELETE) @RequestMapping(value = "/otaPackage/{otaPackageId}", method = RequestMethod.DELETE)
@ResponseBody @ResponseBody

8
application/src/main/java/org/thingsboard/server/controller/RuleChainController.java

@ -371,7 +371,7 @@ public class RuleChainController extends BaseController {
public JsonNode testScript( public JsonNode testScript(
@Parameter(description = "Script language: JS or TBEL") @Parameter(description = "Script language: JS or TBEL")
@RequestParam(required = false) ScriptLanguage scriptLang, @RequestParam(required = false) ScriptLanguage scriptLang,
@Parameter(description = "Test JS request. See API call description above.") @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "Test JS request. See API call description above.")
@RequestBody JsonNode inputParams) throws ThingsboardException, JsonProcessingException { @RequestBody JsonNode inputParams) throws ThingsboardException, JsonProcessingException {
String script = inputParams.get("script").asText(); String script = inputParams.get("script").asText();
String scriptType = inputParams.get("scriptType").asText(); String scriptType = inputParams.get("scriptType").asText();
@ -499,8 +499,7 @@ public class RuleChainController extends BaseController {
"Second, remote edge service will receive a copy of assignment rule chain " + "Second, remote edge service will receive a copy of assignment rule chain " +
EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION + EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION +
"Third, once rule chain will be delivered to edge service, it's going to start processing messages locally. " + "Third, once rule chain will be delivered to edge service, it's going to start processing messages locally. " +
"\n\nOnly rule chain with type 'EDGE' can be assigned to edge." + TENANT_AUTHORITY_PARAGRAPH, "\n\nOnly rule chain with type 'EDGE' can be assigned to edge." + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/edge/{edgeId}/ruleChain/{ruleChainId}", method = RequestMethod.POST) @RequestMapping(value = "/edge/{edgeId}/ruleChain/{ruleChainId}", method = RequestMethod.POST)
@ResponseBody @ResponseBody
@ -522,8 +521,7 @@ public class RuleChainController extends BaseController {
EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION + EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION +
"Second, remote edge service will receive an 'unassign' command to remove rule chain " + "Second, remote edge service will receive an 'unassign' command to remove rule chain " +
EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION + EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION +
"Third, once 'unassign' command will be delivered to edge service, it's going to remove rule chain locally." + TENANT_AUTHORITY_PARAGRAPH, "Third, once 'unassign' command will be delivered to edge service, it's going to remove rule chain locally." + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/edge/{edgeId}/ruleChain/{ruleChainId}", method = RequestMethod.DELETE) @RequestMapping(value = "/edge/{edgeId}/ruleChain/{ruleChainId}", method = RequestMethod.DELETE)
@ResponseBody @ResponseBody

21
application/src/main/java/org/thingsboard/server/controller/TbResourceController.java

@ -146,8 +146,7 @@ public class TbResourceController extends BaseController {
@ApiOperation(value = "Get Resource Info (getResourceInfoById)", @ApiOperation(value = "Get Resource Info (getResourceInfoById)",
notes = "Fetch the Resource Info object based on the provided Resource Id. " + notes = "Fetch the Resource Info object based on the provided Resource Id. " +
RESOURCE_INFO_DESCRIPTION + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH, RESOURCE_INFO_DESCRIPTION + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
@GetMapping(value = "/resource/info/{resourceId}") @GetMapping(value = "/resource/info/{resourceId}")
public TbResourceInfo getResourceInfoById(@Parameter(description = RESOURCE_ID_PARAM_DESCRIPTION) public TbResourceInfo getResourceInfoById(@Parameter(description = RESOURCE_ID_PARAM_DESCRIPTION)
@ -159,8 +158,7 @@ public class TbResourceController extends BaseController {
@ApiOperation(value = "Get Resource (getResourceById)", @ApiOperation(value = "Get Resource (getResourceById)",
notes = "Fetch the Resource object based on the provided Resource Id. " + notes = "Fetch the Resource object based on the provided Resource Id. " +
RESOURCE_DESCRIPTION + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH, RESOURCE_DESCRIPTION + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH, hidden = true)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)), hidden = true)
@Deprecated // resource's data should be fetched with a download request @Deprecated // resource's data should be fetched with a download request
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
@GetMapping(value = "/resource/{resourceId}") @GetMapping(value = "/resource/{resourceId}")
@ -178,8 +176,7 @@ public class TbResourceController extends BaseController {
"Referencing non-existing Resource Id will cause 'Not Found' error. " + "Referencing non-existing Resource Id will cause 'Not Found' error. " +
"\n\nResource combination of the title with the key is unique in the scope of tenant. " + "\n\nResource combination of the title with the key is unique in the scope of tenant. " +
"Remove 'id', 'tenantId' from the request body example (below) to create new Resource entity." + "Remove 'id', 'tenantId' from the request body example (below) to create new Resource entity." +
SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH, SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
@PostMapping(value = "/resource") @PostMapping(value = "/resource")
public TbResourceInfo saveResource(@Parameter(description = "A JSON value representing the Resource.") public TbResourceInfo saveResource(@Parameter(description = "A JSON value representing the Resource.")
@ -191,8 +188,7 @@ public class TbResourceController extends BaseController {
@ApiOperation(value = "Get Resource Infos (getResources)", @ApiOperation(value = "Get Resource Infos (getResources)",
notes = "Returns a page of Resource Info objects owned by tenant or sysadmin. " + notes = "Returns a page of Resource Info objects owned by tenant or sysadmin. " +
PAGE_DATA_PARAMETERS + RESOURCE_INFO_DESCRIPTION + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH, PAGE_DATA_PARAMETERS + RESOURCE_INFO_DESCRIPTION + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
@GetMapping(value = "/resource") @GetMapping(value = "/resource")
public PageData<TbResourceInfo> getResources(@Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) public PageData<TbResourceInfo> getResources(@Parameter(description = PAGE_SIZE_DESCRIPTION, required = true)
@ -227,8 +223,7 @@ public class TbResourceController extends BaseController {
@ApiOperation(value = "Get All Resource Infos (getAllResources)", @ApiOperation(value = "Get All Resource Infos (getAllResources)",
notes = "Returns a page of Resource Info objects owned by tenant. " + notes = "Returns a page of Resource Info objects owned by tenant. " +
PAGE_DATA_PARAMETERS + RESOURCE_INFO_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH, PAGE_DATA_PARAMETERS + RESOURCE_INFO_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@GetMapping(value = "/resource/tenant") @GetMapping(value = "/resource/tenant")
public PageData<TbResourceInfo> getTenantResources(@Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) public PageData<TbResourceInfo> getTenantResources(@Parameter(description = PAGE_SIZE_DESCRIPTION, required = true)
@ -251,8 +246,7 @@ public class TbResourceController extends BaseController {
@ApiOperation(value = "Get LwM2M Objects (getLwm2mListObjectsPage)", @ApiOperation(value = "Get LwM2M Objects (getLwm2mListObjectsPage)",
notes = "Returns a page of LwM2M objects parsed from Resources with type 'LWM2M_MODEL' owned by tenant or sysadmin. " + notes = "Returns a page of LwM2M objects parsed from Resources with type 'LWM2M_MODEL' owned by tenant or sysadmin. " +
PAGE_DATA_PARAMETERS + LWM2M_OBJECT_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH, PAGE_DATA_PARAMETERS + LWM2M_OBJECT_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@GetMapping(value = "/resource/lwm2m/page") @GetMapping(value = "/resource/lwm2m/page")
public List<LwM2mObject> getLwm2mListObjectsPage(@Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) public List<LwM2mObject> getLwm2mListObjectsPage(@Parameter(description = PAGE_SIZE_DESCRIPTION, required = true)
@ -271,8 +265,7 @@ public class TbResourceController extends BaseController {
@ApiOperation(value = "Get LwM2M Objects (getLwm2mListObjects)", @ApiOperation(value = "Get LwM2M Objects (getLwm2mListObjects)",
notes = "Returns a page of LwM2M objects parsed from Resources with type 'LWM2M_MODEL' owned by tenant or sysadmin. " + notes = "Returns a page of LwM2M objects parsed from Resources with type 'LWM2M_MODEL' owned by tenant or sysadmin. " +
"You can specify parameters to filter the results. " + LWM2M_OBJECT_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH, "You can specify parameters to filter the results. " + LWM2M_OBJECT_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@GetMapping(value = "/resource/lwm2m") @GetMapping(value = "/resource/lwm2m")
public List<LwM2mObject> getLwm2mListObjects(@Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"}, required = true)) public List<LwM2mObject> getLwm2mListObjects(@Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"}, required = true))

51
application/src/main/java/org/thingsboard/server/controller/TelemetryController.java

@ -177,8 +177,7 @@ public class TelemetryController extends BaseController {
"\n\n * SERVER_SCOPE - supported for all entity types;" + "\n\n * SERVER_SCOPE - supported for all entity types;" +
"\n * CLIENT_SCOPE - supported for devices;" + "\n * CLIENT_SCOPE - supported for devices;" +
"\n * SHARED_SCOPE - supported for devices. " "\n * SHARED_SCOPE - supported for devices. "
+ "\n\n" + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, + "\n\n" + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/{entityType}/{entityId}/keys/attributes", method = RequestMethod.GET) @RequestMapping(value = "/{entityType}/{entityId}/keys/attributes", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -193,8 +192,7 @@ public class TelemetryController extends BaseController {
"\n\n * SERVER_SCOPE - supported for all entity types;" + "\n\n * SERVER_SCOPE - supported for all entity types;" +
"\n * CLIENT_SCOPE - supported for devices;" + "\n * CLIENT_SCOPE - supported for devices;" +
"\n * SHARED_SCOPE - supported for devices. " "\n * SHARED_SCOPE - supported for devices. "
+ "\n\n" + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, + "\n\n" + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/{entityType}/{entityId}/keys/attributes/{scope}", method = RequestMethod.GET) @RequestMapping(value = "/{entityType}/{entityId}/keys/attributes/{scope}", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -212,8 +210,7 @@ public class TelemetryController extends BaseController {
+ MARKDOWN_CODE_BLOCK_START + MARKDOWN_CODE_BLOCK_START
+ ATTRIBUTE_DATA_EXAMPLE + ATTRIBUTE_DATA_EXAMPLE
+ MARKDOWN_CODE_BLOCK_END + MARKDOWN_CODE_BLOCK_END
+ "\n\n " + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, + "\n\n " + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/{entityType}/{entityId}/values/attributes", method = RequestMethod.GET) @RequestMapping(value = "/{entityType}/{entityId}/values/attributes", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -235,8 +232,7 @@ public class TelemetryController extends BaseController {
+ MARKDOWN_CODE_BLOCK_START + MARKDOWN_CODE_BLOCK_START
+ ATTRIBUTE_DATA_EXAMPLE + ATTRIBUTE_DATA_EXAMPLE
+ MARKDOWN_CODE_BLOCK_END + MARKDOWN_CODE_BLOCK_END
+ "\n\n " + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, + "\n\n " + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/{entityType}/{entityId}/values/attributes/{scope}", method = RequestMethod.GET) @RequestMapping(value = "/{entityType}/{entityId}/values/attributes/{scope}", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -252,8 +248,7 @@ public class TelemetryController extends BaseController {
@ApiOperation(value = "Get time-series keys (getTimeseriesKeys)", @ApiOperation(value = "Get time-series keys (getTimeseriesKeys)",
notes = "Returns a set of unique time-series key names for the selected entity. " + notes = "Returns a set of unique time-series key names for the selected entity. " +
"\n\n" + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, "\n\n" + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/{entityType}/{entityId}/keys/timeseries", method = RequestMethod.GET) @RequestMapping(value = "/{entityType}/{entityId}/keys/timeseries", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -275,8 +270,7 @@ public class TelemetryController extends BaseController {
+ MARKDOWN_CODE_BLOCK_START + MARKDOWN_CODE_BLOCK_START
+ LATEST_TS_STRICT_DATA_EXAMPLE + LATEST_TS_STRICT_DATA_EXAMPLE
+ MARKDOWN_CODE_BLOCK_END + MARKDOWN_CODE_BLOCK_END
+ "\n\n " + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, + "\n\n " + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/{entityType}/{entityId}/values/timeseries", method = RequestMethod.GET) @RequestMapping(value = "/{entityType}/{entityId}/values/timeseries", method = RequestMethod.GET)
@ResponseBody @ResponseBody
@ -299,8 +293,7 @@ public class TelemetryController extends BaseController {
+ MARKDOWN_CODE_BLOCK_START + MARKDOWN_CODE_BLOCK_START
+ TS_STRICT_DATA_EXAMPLE + TS_STRICT_DATA_EXAMPLE
+ MARKDOWN_CODE_BLOCK_END + MARKDOWN_CODE_BLOCK_END
+ "\n\n" + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, + "\n\n" + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/{entityType}/{entityId}/values/timeseries", method = RequestMethod.GET, params = {"keys", "startTs", "endTs"}) @RequestMapping(value = "/{entityType}/{entityId}/values/timeseries", method = RequestMethod.GET, params = {"keys", "startTs", "endTs"})
@ResponseBody @ResponseBody
@ -348,8 +341,7 @@ public class TelemetryController extends BaseController {
@ApiOperation(value = "Save device attributes (saveDeviceAttributes)", @ApiOperation(value = "Save device attributes (saveDeviceAttributes)",
notes = "Creates or updates the device attributes based on device id and specified attribute scope. " + notes = "Creates or updates the device attributes based on device id and specified attribute scope. " +
SAVE_ATTRIBUTES_REQUEST_PAYLOAD SAVE_ATTRIBUTES_REQUEST_PAYLOAD
+ TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(responseCode = "200", description = SAVE_ATTIRIBUTES_STATUS_OK + @ApiResponse(responseCode = "200", description = SAVE_ATTIRIBUTES_STATUS_OK +
"Platform creates an audit log event about device attributes updates with action type 'ATTRIBUTES_UPDATED', " + "Platform creates an audit log event about device attributes updates with action type 'ATTRIBUTES_UPDATED', " +
@ -365,7 +357,7 @@ public class TelemetryController extends BaseController {
public DeferredResult<ResponseEntity> saveDeviceAttributes( public DeferredResult<ResponseEntity> saveDeviceAttributes(
@Parameter(description = DEVICE_ID_PARAM_DESCRIPTION, required = true) @PathVariable("deviceId") String deviceIdStr, @Parameter(description = DEVICE_ID_PARAM_DESCRIPTION, required = true) @PathVariable("deviceId") String deviceIdStr,
@Parameter(description = ATTRIBUTES_SCOPE_DESCRIPTION, schema = @Schema(allowableValues = {"SERVER_SCOPE", "SHARED_SCOPE"}, required = true)) @PathVariable("scope") AttributeScope scope, @Parameter(description = ATTRIBUTES_SCOPE_DESCRIPTION, schema = @Schema(allowableValues = {"SERVER_SCOPE", "SHARED_SCOPE"}, required = true)) @PathVariable("scope") AttributeScope scope,
@Parameter(description = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true) @RequestBody JsonNode request) throws ThingsboardException { @io.swagger.v3.oas.annotations.parameters.RequestBody(description = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true) @RequestBody JsonNode request) throws ThingsboardException {
EntityId entityId = EntityIdFactory.getByTypeAndUuid(EntityType.DEVICE, deviceIdStr); EntityId entityId = EntityIdFactory.getByTypeAndUuid(EntityType.DEVICE, deviceIdStr);
return saveAttributes(getTenantId(), entityId, scope, request); return saveAttributes(getTenantId(), entityId, scope, request);
} }
@ -374,8 +366,7 @@ public class TelemetryController extends BaseController {
notes = "Creates or updates the entity attributes based on Entity Id and the specified attribute scope. " + notes = "Creates or updates the entity attributes based on Entity Id and the specified attribute scope. " +
ENTITY_SAVE_ATTRIBUTE_SCOPES + ENTITY_SAVE_ATTRIBUTE_SCOPES +
SAVE_ATTRIBUTES_REQUEST_PAYLOAD SAVE_ATTRIBUTES_REQUEST_PAYLOAD
+ INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(responseCode = "200", description = SAVE_ATTIRIBUTES_STATUS_OK + SAVE_ENTITY_ATTRIBUTES_STATUS_OK), @ApiResponse(responseCode = "200", description = SAVE_ATTIRIBUTES_STATUS_OK + SAVE_ENTITY_ATTRIBUTES_STATUS_OK),
@ApiResponse(responseCode = "400", description = SAVE_ATTIRIBUTES_STATUS_BAD_REQUEST), @ApiResponse(responseCode = "400", description = SAVE_ATTIRIBUTES_STATUS_BAD_REQUEST),
@ -389,7 +380,7 @@ public class TelemetryController extends BaseController {
@Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE")) @PathVariable("entityType") String entityType, @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE")) @PathVariable("entityType") String entityType,
@Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr,
@Parameter(description = ATTRIBUTES_SCOPE_DESCRIPTION, schema = @Schema(allowableValues = {"SERVER_SCOPE", "SHARED_SCOPE"})) @PathVariable("scope")AttributeScope scope, @Parameter(description = ATTRIBUTES_SCOPE_DESCRIPTION, schema = @Schema(allowableValues = {"SERVER_SCOPE", "SHARED_SCOPE"})) @PathVariable("scope")AttributeScope scope,
@Parameter(description = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true)@RequestBody JsonNode request) throws ThingsboardException { @io.swagger.v3.oas.annotations.parameters.RequestBody(description = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true) @RequestBody JsonNode request) throws ThingsboardException {
EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr);
return saveAttributes(getTenantId(), entityId, scope, request); return saveAttributes(getTenantId(), entityId, scope, request);
} }
@ -398,8 +389,7 @@ public class TelemetryController extends BaseController {
notes = "Creates or updates the entity attributes based on Entity Id and the specified attribute scope. " + notes = "Creates or updates the entity attributes based on Entity Id and the specified attribute scope. " +
ENTITY_SAVE_ATTRIBUTE_SCOPES + ENTITY_SAVE_ATTRIBUTE_SCOPES +
SAVE_ATTRIBUTES_REQUEST_PAYLOAD SAVE_ATTRIBUTES_REQUEST_PAYLOAD
+ INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(responseCode = "200", description = SAVE_ATTIRIBUTES_STATUS_OK + SAVE_ENTITY_ATTRIBUTES_STATUS_OK), @ApiResponse(responseCode = "200", description = SAVE_ATTIRIBUTES_STATUS_OK + SAVE_ENTITY_ATTRIBUTES_STATUS_OK),
@ApiResponse(responseCode = "400", description = SAVE_ATTIRIBUTES_STATUS_BAD_REQUEST), @ApiResponse(responseCode = "400", description = SAVE_ATTIRIBUTES_STATUS_BAD_REQUEST),
@ -413,7 +403,7 @@ public class TelemetryController extends BaseController {
@Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE")) @PathVariable("entityType") String entityType, @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE")) @PathVariable("entityType") String entityType,
@Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr,
@Parameter(description = ATTRIBUTES_SCOPE_DESCRIPTION, schema = @Schema(allowableValues = {"SERVER_SCOPE", "SHARED_SCOPE"}, required = true)) @PathVariable("scope")AttributeScope scope, @Parameter(description = ATTRIBUTES_SCOPE_DESCRIPTION, schema = @Schema(allowableValues = {"SERVER_SCOPE", "SHARED_SCOPE"}, required = true)) @PathVariable("scope")AttributeScope scope,
@Parameter(description = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true)@RequestBody JsonNode request) throws ThingsboardException { @io.swagger.v3.oas.annotations.parameters.RequestBody(description = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true) @RequestBody JsonNode request) throws ThingsboardException {
EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr);
return saveAttributes(getTenantId(), entityId, scope, request); return saveAttributes(getTenantId(), entityId, scope, request);
} }
@ -423,8 +413,7 @@ public class TelemetryController extends BaseController {
notes = "Creates or updates the entity time-series data based on the Entity Id and request payload." + notes = "Creates or updates the entity time-series data based on the Entity Id and request payload." +
SAVE_TIMESERIES_REQUEST_PAYLOAD + SAVE_TIMESERIES_REQUEST_PAYLOAD +
"\n\n The scope parameter is not used in the API call implementation but should be specified whatever value because it is used as a path variable. " "\n\n The scope parameter is not used in the API call implementation but should be specified whatever value because it is used as a path variable. "
+ INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(responseCode = "200", description = SAVE_ENTITY_TIMESERIES_STATUS_OK), @ApiResponse(responseCode = "200", description = SAVE_ENTITY_TIMESERIES_STATUS_OK),
@ApiResponse(responseCode = "400", description = INVALID_STRUCTURE_OF_THE_REQUEST), @ApiResponse(responseCode = "400", description = INVALID_STRUCTURE_OF_THE_REQUEST),
@ -448,8 +437,7 @@ public class TelemetryController extends BaseController {
SAVE_TIMESERIES_REQUEST_PAYLOAD + SAVE_TIMESERIES_REQUEST_PAYLOAD +
"\n\n The scope parameter is not used in the API call implementation but should be specified whatever value because it is used as a path variable. " "\n\n The scope parameter is not used in the API call implementation but should be specified whatever value because it is used as a path variable. "
+ "\n\nThe ttl parameter takes affect only in case of Cassandra DB." + "\n\nThe ttl parameter takes affect only in case of Cassandra DB."
+ INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(responseCode = "200", description = SAVE_ENTITY_TIMESERIES_STATUS_OK), @ApiResponse(responseCode = "200", description = SAVE_ENTITY_TIMESERIES_STATUS_OK),
@ApiResponse(responseCode = "400", description = INVALID_STRUCTURE_OF_THE_REQUEST), @ApiResponse(responseCode = "400", description = INVALID_STRUCTURE_OF_THE_REQUEST),
@ -476,8 +464,7 @@ public class TelemetryController extends BaseController {
" Use 'deleteLatest' to delete latest value (stored in separate table for performance) if the value's timestamp matches the time-range. " + " Use 'deleteLatest' to delete latest value (stored in separate table for performance) if the value's timestamp matches the time-range. " +
" Use 'rewriteLatestIfDeleted' to rewrite latest value (stored in separate table for performance) if the value's timestamp matches the time-range and 'deleteLatest' param is true." + " Use 'rewriteLatestIfDeleted' to rewrite latest value (stored in separate table for performance) if the value's timestamp matches the time-range and 'deleteLatest' param is true." +
" The replacement value will be fetched from the 'time-series' table, and its timestamp will be the most recent one before the defined time-range. " + " The replacement value will be fetched from the 'time-series' table, and its timestamp will be the most recent one before the defined time-range. " +
TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Timeseries for the selected keys in the request was removed. " + @ApiResponse(responseCode = "200", description = "Timeseries for the selected keys in the request was removed. " +
"Platform creates an audit log event about entity timeseries removal with action type 'TIMESERIES_DELETED'."), "Platform creates an audit log event about entity timeseries removal with action type 'TIMESERIES_DELETED'."),
@ -552,8 +539,7 @@ public class TelemetryController extends BaseController {
@ApiOperation(value = "Delete device attributes (deleteDeviceAttributes)", @ApiOperation(value = "Delete device attributes (deleteDeviceAttributes)",
notes = "Delete device attributes using provided Device Id, scope and a list of keys. " + notes = "Delete device attributes using provided Device Id, scope and a list of keys. " +
"Referencing a non-existing Device Id will cause an error" + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, "Referencing a non-existing Device Id will cause an error" + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Device attributes was removed for the selected keys in the request. " + @ApiResponse(responseCode = "200", description = "Device attributes was removed for the selected keys in the request. " +
"Platform creates an audit log event about device attributes removal with action type 'ATTRIBUTES_DELETED'."), "Platform creates an audit log event about device attributes removal with action type 'ATTRIBUTES_DELETED'."),
@ -575,8 +561,7 @@ public class TelemetryController extends BaseController {
@ApiOperation(value = "Delete entity attributes (deleteEntityAttributes)", @ApiOperation(value = "Delete entity attributes (deleteEntityAttributes)",
notes = "Delete entity attributes using provided Entity Id, scope and a list of keys. " + notes = "Delete entity attributes using provided Entity Id, scope and a list of keys. " +
INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Entity attributes was removed for the selected keys in the request. " + @ApiResponse(responseCode = "200", description = "Entity attributes was removed for the selected keys in the request. " +
"Platform creates an audit log event about entity attributes removal with action type 'ATTRIBUTES_DELETED'."), "Platform creates an audit log event about entity attributes removal with action type 'ATTRIBUTES_DELETED'."),

2
application/src/main/resources/thingsboard.yml

@ -1332,6 +1332,8 @@ springdoc:
swagger: swagger:
# General swagger match pattern of swagger UI links # General swagger match pattern of swagger UI links
api_path: "${SWAGGER_API_PATH:/api/**}" api_path: "${SWAGGER_API_PATH:/api/**}"
# General swagger match pattern path of swagger UI links
security_path_regex: "${SWAGGER_SECURITY_PATH_REGEX:/api/.*}"
# Nonsecurity API path match pattern of swagger UI links # Nonsecurity API path match pattern of swagger UI links
non_security_path_regex: "${SWAGGER_NON_SECURITY_PATH_REGEX:/api/(?:noauth|v1)/.*}" non_security_path_regex: "${SWAGGER_NON_SECURITY_PATH_REGEX:/api/(?:noauth|v1)/.*}"
# The title on the API doc UI page # The title on the API doc UI page

11
common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java

@ -25,6 +25,7 @@ import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.BaseData; import org.thingsboard.server.common.data.BaseData;
import org.thingsboard.server.common.data.HasName; import org.thingsboard.server.common.data.HasName;
import org.thingsboard.server.common.data.id.AlarmCommentId; import org.thingsboard.server.common.data.id.AlarmCommentId;
import org.thingsboard.server.common.data.id.AlarmId;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.validation.Length; import org.thingsboard.server.common.data.validation.Length;
@ -36,21 +37,21 @@ import org.thingsboard.server.common.data.validation.NoXss;
@AllArgsConstructor @AllArgsConstructor
public class AlarmComment extends BaseData<AlarmCommentId> implements HasName { public class AlarmComment extends BaseData<AlarmCommentId> implements HasName {
@Schema(description = "JSON object with Alarm id.", accessMode = Schema.AccessMode.READ_ONLY) @Schema(description = "JSON object with Alarm id.", accessMode = Schema.AccessMode.READ_ONLY)
private EntityId alarmId; private AlarmId alarmId;
@Schema(description = "JSON object with User id.", accessMode = Schema.AccessMode.READ_ONLY) @Schema(description = "JSON object with User id.", accessMode = Schema.AccessMode.READ_ONLY)
private UserId userId; private UserId userId;
@Schema(description = "Defines origination of comment. System type means comment was created by TB. OTHER type means comment was created by user.", example = "SYSTEM/OTHER", accessMode = Schema.AccessMode.READ_ONLY) @Schema(description = "Defines origination of comment. System type means comment was created by TB. OTHER type means comment was created by user.", example = "SYSTEM/OTHER", accessMode = Schema.AccessMode.READ_ONLY)
private AlarmCommentType type; private AlarmCommentType type;
@Schema(description = "JSON object with text of comment.",implementation = com.fasterxml.jackson.databind.JsonNode.class) @Schema(description = "JSON object with text of comment.")
@NoXss @NoXss
@Length(fieldName = "comment", max = 10000) @Length(fieldName = "comment", max = 10000)
@EqualsAndHashCode.Include @EqualsAndHashCode.Include
private transient JsonNode comment; private JsonNode comment;
@Schema(description = "JSON object with the alarm comment Id. " + @Schema(description = "JSON object with the alarm comment Id. " +
"Specify this field to update the alarm comment. " + "Specify this field to update the alarm comment. " +
"Referencing non-existing alarm Id will cause error. " + "Referencing non-existing alarm Id will cause error. " +
"Omit this field to create new alarm." ) "Omit this field to create new alarm.", accessMode = Schema.AccessMode.READ_ONLY)
@Override @Override
public AlarmCommentId getId() { public AlarmCommentId getId() {
return super.getId(); return super.getId();
@ -72,7 +73,7 @@ public class AlarmComment extends BaseData<AlarmCommentId> implements HasName {
@Override @Override
@JsonProperty(access = JsonProperty.Access.READ_ONLY) @JsonProperty(access = JsonProperty.Access.READ_ONLY)
@Schema(required = true, description = "representing comment text", example = "Please take a look") @Schema(accessMode = Schema.AccessMode.READ_ONLY, description = "representing comment text", example = "Please take a look")
public String getName() { public String getName() {
return comment.toString(); return comment.toString();
} }

4
common/data/src/main/java/org/thingsboard/server/common/data/id/EntityId.java

@ -35,10 +35,10 @@ public interface EntityId extends HasUUID, Serializable { //NOSONAR, the constan
UUID NULL_UUID = UUID.fromString("13814000-1dd2-11b2-8080-808080808080"); UUID NULL_UUID = UUID.fromString("13814000-1dd2-11b2-8080-808080808080");
@Schema(required = true, description = "ID of the entity, time-based UUID v1", example = "784f394c-42b6-435a-983c-b7beff2784f9") @Schema(requiredMode = Schema.RequiredMode.REQUIRED, description = "ID of the entity, time-based UUID v1", example = "784f394c-42b6-435a-983c-b7beff2784f9")
UUID getId(); UUID getId();
@Schema(required = true, example = "DEVICE") @Schema(requiredMode = Schema.RequiredMode.REQUIRED, example = "DEVICE")
EntityType getEntityType(); EntityType getEntityType();
@JsonIgnore @JsonIgnore

3
common/data/src/main/java/org/thingsboard/server/common/data/id/UserId.java

@ -22,6 +22,7 @@ import org.thingsboard.server.common.data.EntityType;
import java.util.UUID; import java.util.UUID;
@Schema
public class UserId extends UUIDBased implements EntityId { public class UserId extends UUIDBased implements EntityId {
@JsonCreator @JsonCreator
@ -33,7 +34,7 @@ public class UserId extends UUIDBased implements EntityId {
return new UserId(UUID.fromString(userId)); return new UserId(UUID.fromString(userId));
} }
@Schema(required = true, description = "string", example = "USER", allowableValues = "USER") @Schema(requiredMode = Schema.RequiredMode.REQUIRED, description = "string", example = "USER", allowableValues = "USER")
@Override @Override
public EntityType getEntityType() { public EntityType getEntityType() {
return EntityType.USER; return EntityType.USER;

42
common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java

@ -137,8 +137,7 @@ public class DeviceApiController implements TbTransportService {
+ MARKDOWN_CODE_BLOCK_START + MARKDOWN_CODE_BLOCK_START
+ ATTRIBUTE_PAYLOAD_EXAMPLE + ATTRIBUTE_PAYLOAD_EXAMPLE
+ MARKDOWN_CODE_BLOCK_END + MARKDOWN_CODE_BLOCK_END
+ REQUIRE_ACCESS_TOKEN, + REQUIRE_ACCESS_TOKEN)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@RequestMapping(value = "/{deviceToken}/attributes", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) @RequestMapping(value = "/{deviceToken}/attributes", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public DeferredResult<ResponseEntity> getDeviceAttributes( public DeferredResult<ResponseEntity> getDeviceAttributes(
@Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN"))
@ -174,13 +173,12 @@ public class DeviceApiController implements TbTransportService {
+ MARKDOWN_CODE_BLOCK_START + MARKDOWN_CODE_BLOCK_START
+ ATTRIBUTE_PAYLOAD_EXAMPLE + ATTRIBUTE_PAYLOAD_EXAMPLE
+ MARKDOWN_CODE_BLOCK_END + MARKDOWN_CODE_BLOCK_END
+ REQUIRE_ACCESS_TOKEN, + REQUIRE_ACCESS_TOKEN)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@RequestMapping(value = "/{deviceToken}/attributes", method = RequestMethod.POST) @RequestMapping(value = "/{deviceToken}/attributes", method = RequestMethod.POST)
public DeferredResult<ResponseEntity> postDeviceAttributes( public DeferredResult<ResponseEntity> postDeviceAttributes(
@Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN"))
@PathVariable("deviceToken") String deviceToken, @PathVariable("deviceToken") String deviceToken,
@Parameter(description = "JSON with attribute key-value pairs. See API call description for example.") @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "JSON with attribute key-value pairs. See API call description for example.")
@RequestBody String json) { @RequestBody String json) {
DeferredResult<ResponseEntity> responseWriter = new DeferredResult<>(); DeferredResult<ResponseEntity> responseWriter = new DeferredResult<>();
transportContext.getTransportService().process(DeviceTransportType.DEFAULT, ValidateDeviceTokenRequestMsg.newBuilder().setToken(deviceToken).build(), transportContext.getTransportService().process(DeviceTransportType.DEFAULT, ValidateDeviceTokenRequestMsg.newBuilder().setToken(deviceToken).build(),
@ -196,8 +194,7 @@ public class DeviceApiController implements TbTransportService {
description = "Post time-series data on behalf of device. " description = "Post time-series data on behalf of device. "
+ "\n Example of the request: " + "\n Example of the request: "
+ TS_PAYLOAD + TS_PAYLOAD
+ REQUIRE_ACCESS_TOKEN, + REQUIRE_ACCESS_TOKEN)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@RequestMapping(value = "/{deviceToken}/telemetry", method = RequestMethod.POST) @RequestMapping(value = "/{deviceToken}/telemetry", method = RequestMethod.POST)
public DeferredResult<ResponseEntity> postTelemetry( public DeferredResult<ResponseEntity> postTelemetry(
@Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN"))
@ -222,8 +219,7 @@ public class DeviceApiController implements TbTransportService {
+ MARKDOWN_CODE_BLOCK_END + MARKDOWN_CODE_BLOCK_END
+ "Note: both 'secretKey' and 'durationMs' is optional parameters. " + + "Note: both 'secretKey' and 'durationMs' is optional parameters. " +
"In case the secretKey is not specified, the empty string as a default value is used. In case the durationMs is not specified, the system parameter device.claim.duration is used.\n\n" "In case the secretKey is not specified, the empty string as a default value is used. In case the durationMs is not specified, the system parameter device.claim.duration is used.\n\n"
+ REQUIRE_ACCESS_TOKEN, + REQUIRE_ACCESS_TOKEN)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@RequestMapping(value = "/{deviceToken}/claim", method = RequestMethod.POST) @RequestMapping(value = "/{deviceToken}/claim", method = RequestMethod.POST)
public DeferredResult<ResponseEntity> claimDevice( public DeferredResult<ResponseEntity> claimDevice(
@Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN"))
@ -244,8 +240,7 @@ public class DeviceApiController implements TbTransportService {
description = "Subscribes to RPC commands using http long polling. " + description = "Subscribes to RPC commands using http long polling. " +
"Deprecated, since long polling is resource and network consuming. " + "Deprecated, since long polling is resource and network consuming. " +
"Consider using MQTT or CoAP protocol for light-weight real-time updates. \n\n" + "Consider using MQTT or CoAP protocol for light-weight real-time updates. \n\n" +
REQUIRE_ACCESS_TOKEN, REQUIRE_ACCESS_TOKEN)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@RequestMapping(value = "/{deviceToken}/rpc", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) @RequestMapping(value = "/{deviceToken}/rpc", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public DeferredResult<ResponseEntity> subscribeToCommands( public DeferredResult<ResponseEntity> subscribeToCommands(
@Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN"))
@ -268,15 +263,14 @@ public class DeviceApiController implements TbTransportService {
@Operation(summary = "Reply to RPC commands (replyToCommand)", @Operation(summary = "Reply to RPC commands (replyToCommand)",
description = "Replies to server originated RPC command identified by 'requestId' parameter. The response is arbitrary JSON.\n\n" + description = "Replies to server originated RPC command identified by 'requestId' parameter. The response is arbitrary JSON.\n\n" +
REQUIRE_ACCESS_TOKEN, REQUIRE_ACCESS_TOKEN)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@RequestMapping(value = "/{deviceToken}/rpc/{requestId}", method = RequestMethod.POST) @RequestMapping(value = "/{deviceToken}/rpc/{requestId}", method = RequestMethod.POST)
public DeferredResult<ResponseEntity> replyToCommand( public DeferredResult<ResponseEntity> replyToCommand(
@Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN"))
@PathVariable("deviceToken") String deviceToken, @PathVariable("deviceToken") String deviceToken,
@Parameter(description = "RPC request id from the incoming RPC request", required = true , schema = @Schema(defaultValue = "123")) @Parameter(description = "RPC request id from the incoming RPC request", required = true , schema = @Schema(defaultValue = "123"))
@PathVariable("requestId") Integer requestId, @PathVariable("requestId") Integer requestId,
@Parameter(description = "Reply to the RPC request, JSON. For example: {\"status\":\"success\"}", required = true) @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "Reply to the RPC request, JSON. For example: {\"status\":\"success\"}", required = true)
@RequestBody String json) { @RequestBody String json) {
DeferredResult<ResponseEntity> responseWriter = new DeferredResult<ResponseEntity>(); DeferredResult<ResponseEntity> responseWriter = new DeferredResult<ResponseEntity>();
transportContext.getTransportService().process(DeviceTransportType.DEFAULT, ValidateDeviceTokenRequestMsg.newBuilder().setToken(deviceToken).build(), transportContext.getTransportService().process(DeviceTransportType.DEFAULT, ValidateDeviceTokenRequestMsg.newBuilder().setToken(deviceToken).build(),
@ -296,13 +290,12 @@ public class DeviceApiController implements TbTransportService {
MARKDOWN_CODE_BLOCK_START + MARKDOWN_CODE_BLOCK_START +
"{\"result\": 4}" + "{\"result\": 4}" +
MARKDOWN_CODE_BLOCK_END + MARKDOWN_CODE_BLOCK_END +
REQUIRE_ACCESS_TOKEN, REQUIRE_ACCESS_TOKEN)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@RequestMapping(value = "/{deviceToken}/rpc", method = RequestMethod.POST) @RequestMapping(value = "/{deviceToken}/rpc", method = RequestMethod.POST)
public DeferredResult<ResponseEntity> postRpcRequest( public DeferredResult<ResponseEntity> postRpcRequest(
@Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN"))
@PathVariable("deviceToken") String deviceToken, @PathVariable("deviceToken") String deviceToken,
@Parameter(description = "The RPC request JSON", required = true) @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The RPC request JSON", required = true)
@RequestBody String json) { @RequestBody String json) {
DeferredResult<ResponseEntity> responseWriter = new DeferredResult<ResponseEntity>(); DeferredResult<ResponseEntity> responseWriter = new DeferredResult<ResponseEntity>();
transportContext.getTransportService().process(DeviceTransportType.DEFAULT, ValidateDeviceTokenRequestMsg.newBuilder().setToken(deviceToken).build(), transportContext.getTransportService().process(DeviceTransportType.DEFAULT, ValidateDeviceTokenRequestMsg.newBuilder().setToken(deviceToken).build(),
@ -324,8 +317,7 @@ public class DeviceApiController implements TbTransportService {
description = "Subscribes to client and shared scope attribute updates using http long polling. " + description = "Subscribes to client and shared scope attribute updates using http long polling. " +
"Deprecated, since long polling is resource and network consuming. " + "Deprecated, since long polling is resource and network consuming. " +
"Consider using MQTT or CoAP protocol for light-weight real-time updates. \n\n" + "Consider using MQTT or CoAP protocol for light-weight real-time updates. \n\n" +
REQUIRE_ACCESS_TOKEN, REQUIRE_ACCESS_TOKEN)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@RequestMapping(value = "/{deviceToken}/attributes/updates", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) @RequestMapping(value = "/{deviceToken}/attributes/updates", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public DeferredResult<ResponseEntity> subscribeToAttributes( public DeferredResult<ResponseEntity> subscribeToAttributes(
@Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN"))
@ -356,8 +348,7 @@ public class DeviceApiController implements TbTransportService {
"Optional 'chunk' and 'size' parameters may be used to download the firmware in chunks. " + "Optional 'chunk' and 'size' parameters may be used to download the firmware in chunks. " +
"For example, device may request first 16 KB of firmware using 'chunk'=0 and 'size'=16384. " + "For example, device may request first 16 KB of firmware using 'chunk'=0 and 'size'=16384. " +
"Next 16KB using 'chunk'=1 and 'size'=16384. The last chunk should have less bytes then requested using 'size' parameter. \n\n" + "Next 16KB using 'chunk'=1 and 'size'=16384. The last chunk should have less bytes then requested using 'size' parameter. \n\n" +
REQUIRE_ACCESS_TOKEN, REQUIRE_ACCESS_TOKEN)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@RequestMapping(value = "/{deviceToken}/firmware", method = RequestMethod.GET) @RequestMapping(value = "/{deviceToken}/firmware", method = RequestMethod.GET)
public DeferredResult<ResponseEntity> getFirmware( public DeferredResult<ResponseEntity> getFirmware(
@Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN"))
@ -383,8 +374,7 @@ public class DeviceApiController implements TbTransportService {
"Optional 'chunk' and 'size' parameters may be used to download the software in chunks. " + "Optional 'chunk' and 'size' parameters may be used to download the software in chunks. " +
"For example, device may request first 16 KB of software using 'chunk'=0 and 'size'=16384. " + "For example, device may request first 16 KB of software using 'chunk'=0 and 'size'=16384. " +
"Next 16KB using 'chunk'=1 and 'size'=16384. The last chunk should have less bytes then requested using 'size' parameter. \n\n" + "Next 16KB using 'chunk'=1 and 'size'=16384. The last chunk should have less bytes then requested using 'size' parameter. \n\n" +
REQUIRE_ACCESS_TOKEN, REQUIRE_ACCESS_TOKEN)
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@RequestMapping(value = "/{deviceToken}/software", method = RequestMethod.GET) @RequestMapping(value = "/{deviceToken}/software", method = RequestMethod.GET)
public DeferredResult<ResponseEntity> getSoftware( public DeferredResult<ResponseEntity> getSoftware(
@Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN"))
@ -418,12 +408,10 @@ public class DeviceApiController implements TbTransportService {
" \"credentialsType\":\"ACCESS_TOKEN\",\n" + " \"credentialsType\":\"ACCESS_TOKEN\",\n" +
" \"credentialsValue\":\"DEVICE_ACCESS_TOKEN\",\n" + " \"credentialsValue\":\"DEVICE_ACCESS_TOKEN\",\n" +
" \"status\":\"SUCCESS\"\n" + " \"status\":\"SUCCESS\"\n" +
"}" + MARKDOWN_CODE_BLOCK_END "}" + MARKDOWN_CODE_BLOCK_END)
,
responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)))
@RequestMapping(value = "/provision", method = RequestMethod.POST) @RequestMapping(value = "/provision", method = RequestMethod.POST)
public DeferredResult<ResponseEntity> provisionDevice( public DeferredResult<ResponseEntity> provisionDevice(
@Parameter(description = "JSON with provision request. See API call description for example.") @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "JSON with provision request. See API call description for example.")
@RequestBody String json) { @RequestBody String json) {
DeferredResult<ResponseEntity> responseWriter = new DeferredResult<>(); DeferredResult<ResponseEntity> responseWriter = new DeferredResult<>();
transportContext.getTransportService().process(JsonConverter.convertToProvisionRequestMsg(json), transportContext.getTransportService().process(JsonConverter.convertToProvisionRequestMsg(json),

8
pom.xml

@ -92,8 +92,8 @@
<rabbitmq.version>4.8.0</rabbitmq.version> <rabbitmq.version>4.8.0</rabbitmq.version>
<surefire.version>3.0.0-M9</surefire.version> <surefire.version>3.0.0-M9</surefire.version>
<jar-plugin.version>3.0.2</jar-plugin.version> <jar-plugin.version>3.0.2</jar-plugin.version>
<springdoc-swagger.version>2.1.0</springdoc-swagger.version> <springdoc-swagger.version>2.4.0TB</springdoc-swagger.version>
<swagger-annotations.version>2.2.9</swagger-annotations.version> <swagger-annotations.version>2.2.20</swagger-annotations.version>
<spatial4j.version>0.7</spatial4j.version> <spatial4j.version>0.7</spatial4j.version>
<jts.version>1.18.2</jts.version> <jts.version>1.18.2</jts.version>
<bouncycastle.version>1.69</bouncycastle.version> <bouncycastle.version>1.69</bouncycastle.version>
@ -111,7 +111,7 @@
<kafka.version>3.2.0</kafka.version> <kafka.version>3.2.0</kafka.version>
<bucket4j.version>4.1.1</bucket4j.version> <bucket4j.version>4.1.1</bucket4j.version>
<antlr.version>2.7.7</antlr.version> <antlr.version>2.7.7</antlr.version>
<snakeyaml.version>2.0</snakeyaml.version> <snakeyaml.version>2.2</snakeyaml.version>
<aws.sdk.version>1.11.747</aws.sdk.version> <aws.sdk.version>1.11.747</aws.sdk.version>
<pubsub.client.version>1.105.0</pubsub.client.version> <pubsub.client.version>1.105.0</pubsub.client.version>
<google.common.protos.version>2.1.0</google.common.protos.version> <!-- required by io.grpc:grpc-protobuf:1.38.0--> <google.common.protos.version>2.1.0</google.common.protos.version> <!-- required by io.grpc:grpc-protobuf:1.38.0-->
@ -1775,7 +1775,7 @@
<version>${curator.version}</version> <version>${curator.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springdoc</groupId> <groupId>org.thingsboard</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>${springdoc-swagger.version}</version> <version>${springdoc-swagger.version}</version>
</dependency> </dependency>

Loading…
Cancel
Save