From a61e9d94c5cb3a56e5783a45a71f75213fe529ea Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Thu, 28 Sep 2023 12:55:36 +0200 Subject: [PATCH] merge improvements --- .../ThingsboardSecurityConfiguration.java | 22 ++++-- .../DeviceConnectivityController.java | 77 ++++++++++++------- .../common/data/widget/WidgetTypeDetails.java | 2 +- .../dao/sql/widget/WidgetTypeRepository.java | 6 +- .../engine/rest/TbRestApiCallNodeTest.java | 1 - 5 files changed, 71 insertions(+), 37 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java b/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java index 49f812944c..d07ef4e2d8 100644 --- a/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java +++ b/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java @@ -31,10 +31,9 @@ import org.springframework.security.config.annotation.authentication.builders.Au import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.config.annotation.web.configurers.RequestCacheConfigurer; import org.springframework.security.config.http.SessionCreationPolicy; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestResolver; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.AuthenticationFailureHandler; @@ -136,8 +135,8 @@ public class ThingsboardSecurityConfiguration { ShallowEtagHeaderFilter etagFilter = new ShallowEtagHeaderFilter(); etagFilter.setWriteWeakETag(true); FilterRegistrationBean filterRegistrationBean - = new FilterRegistrationBean<>( etagFilter); - filterRegistrationBean.addUrlPatterns("*.js","*.css","*.ico","/assets/*","/static/*"); + = new FilterRegistrationBean<>(etagFilter); + filterRegistrationBean.addUrlPatterns("*.js", "*.css", "*.ico", "/assets/*", "/static/*"); filterRegistrationBean.setName("etagFilter"); return filterRegistrationBean; } @@ -200,8 +199,19 @@ public class ThingsboardSecurityConfiguration { private OAuth2AuthorizationRequestResolver oAuth2AuthorizationRequestResolver; @Bean - public WebSecurityCustomizer webSecurityCustomizer() { - return (web) -> web.ignoring().requestMatchers("/*.js", "/*.css", "/*.ico", "/assets/**", "/static/**"); + @Order(0) + SecurityFilterChain resources(HttpSecurity http) throws Exception { + http + .securityMatchers(matchers -> matchers + .requestMatchers("/*.js", "/*.css", "/*.ico", "/assets/**", "/static/**")) + .headers(header -> header + .defaultsDisabled() + .addHeaderWriter(new StaticHeadersWriter(HttpHeaders.CACHE_CONTROL, "max-age=0, public"))) + .authorizeHttpRequests((authorize) -> authorize.anyRequest().permitAll()) + .requestCache(RequestCacheConfigurer::disable) + .securityContext(AbstractHttpConfigurer::disable) + .sessionManagement(AbstractHttpConfigurer::disable); + return http.build(); } @Bean diff --git a/application/src/main/java/org/thingsboard/server/controller/DeviceConnectivityController.java b/application/src/main/java/org/thingsboard/server/controller/DeviceConnectivityController.java index 7346cda9fc..0faa743bf2 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceConnectivityController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceConnectivityController.java @@ -17,6 +17,10 @@ package org.thingsboard.server.controller; import com.fasterxml.jackson.databind.JsonNode; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpHeaders; @@ -36,10 +40,8 @@ import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.dao.device.DeviceConnectivityService; import org.thingsboard.server.queue.util.TbCoreComponent; -import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.system.SystemSecurityService; -import jakarta.servlet.http.HttpServletRequest; import java.io.IOException; import java.net.URISyntaxException; @@ -64,16 +66,30 @@ public class DeviceConnectivityController extends BaseController { notes = "Fetch the list of commands to publish device telemetry based on device profile " + "If the user has the authority of 'Tenant Administrator', the server checks that the device is owned by the same tenant. " + "If the user has the authority of 'Customer User', the server checks that the device is assigned to the same customer. " + - TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) -// @ApiResponses(value = { -// @ApiResponse(code = 200, message = "OK", -// examples = @io.swagger.annotations.Example( -// value = { -// @io.swagger.annotations.ExampleProperty( -// mediaType = "application/json", -// value = "{\"http\":\"curl -v -X POST http://localhost:8080/api/v1/0ySs4FTOn5WU15XLmal8/telemetry --header Content-Type:application/json --data {temperature:25}\"," + -// "\"mqtt\":\"mosquitto_pub -d -q 1 -h localhost -t v1/devices/me/telemetry -i myClient1 -u myUsername1 -P myPassword -m {temperature:25}\"," + -// "\"coap\":\"coap-client -m POST coap://localhost:5683/api/v1/0ySs4FTOn5WU15XLmal8/telemetry -t json -e {temperature:25}\"}")}))}) + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, + responses = { + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content( + mediaType = MediaType.APPLICATION_JSON_VALUE, + examples = { + @ExampleObject( + name = "http", + value = "curl -v -X POST http://localhost:8080/api/v1/0ySs4FTOn5WU15XLmal8/telemetry --header Content-Type:application/json --data {temperature:25}" + ), + @ExampleObject( + name = "mqtt", + value = "mosquitto_pub -d -q 1 -h localhost -t v1/devices/me/telemetry -i myClient1 -u myUsername1 -P myPassword -m {temperature:25}" + ), + @ExampleObject( + name = "coap", + value = "coap-client -m POST coap://localhost:5683/api/v1/0ySs4FTOn5WU15XLmal8/telemetry -t json -e {temperature:25}" + ) + } + ) + ) + }) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/device-connectivity/{deviceId}", method = RequestMethod.GET) @ResponseBody @@ -81,7 +97,7 @@ public class DeviceConnectivityController extends BaseController { @PathVariable(DEVICE_ID) String strDeviceId, HttpServletRequest request) throws ThingsboardException, URISyntaxException { checkParameter(DEVICE_ID, strDeviceId); DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); - Device device = checkDeviceId(deviceId, Operation.READ_CREDENTIALS); + Device device = checkDeviceId(deviceId, org.thingsboard.server.service.security.permission.Operation.READ_CREDENTIALS); String baseUrl = systemSecurityService.getBaseUrl(getTenantId(), getCurrentUser().getCustomerId(), request); return deviceConnectivityService.findDevicePublishTelemetryCommands(baseUrl, device); @@ -89,25 +105,34 @@ public class DeviceConnectivityController extends BaseController { @ApiOperation(value = "Get commands to launch gateway (getGatewayLaunchCommands)", notes = "Fetch the list of commands for different operation systems to launch a gateway using docker." + - TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) -// @ApiResponses(value = { -// @ApiResponse(code = 200, message = "OK", -// examples = @io.swagger.annotations.Example( -// value = { -// @io.swagger.annotations.ExampleProperty( -// mediaType = "application/json", -// value = "{\"mqtt\": {\n" + -// " \"linux\": \"docker run --rm -it -v ~/.tb-gateway/logs:/thingsboard_gateway/logs -v ~/.tb-gateway/extensions:/thingsboard_gateway/extensions -v ~/.tb-gateway/config:/thingsboard_gateway/config --name tbGateway127001 -e host=localhost -e port=1883 -e accessToken=qTe5oDBHPJf0KCSKO8J3 --restart always thingsboard/tb-gateway\",\n" + -// " \"windows\": \"docker run --rm -it -v %HOMEPATH%/tb-gateway/logs:/thingsboard_gateway/logs -v %HOMEPATH%/tb-gateway/extensions:/thingsboard_gateway/extensions -v %HOMEPATH%/tb-gateway/config:/thingsboard_gateway/config --name tbGateway127001 -e host=localhost -e port=1883 -e accessToken=qTe5oDBHPJf0KCSKO8J3 --restart always thingsboard/tb-gateway\"}\n" + -// "}")}))}) + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, + responses = { + @ApiResponse( + responseCode = "200", + description = "OK", + content = @Content( + mediaType = MediaType.APPLICATION_JSON_VALUE, + examples = { + @ExampleObject( + name = "mqtt-linux", + value = "docker run --rm -it -v ~/.tb-gateway/logs:/thingsboard_gateway/logs -v ~/.tb-gateway/extensions:/thingsboard_gateway/extensions -v ~/.tb-gateway/config:/thingsboard_gateway/config --name tbGateway127001 -e host=localhost -e port=1883 -e accessToken=qTe5oDBHPJf0KCSKO8J3 --restart always thingsboard/tb-gateway" + ), + @ExampleObject( + name = "mqtt-windows", + value = "docker run --rm -it -v %HOMEPATH%/tb-gateway/logs:/thingsboard_gateway/logs -v %HOMEPATH%/tb-gateway/extensions:/thingsboard_gateway/extensions -v %HOMEPATH%/tb-gateway/config:/thingsboard_gateway/config --name tbGateway127001 -e host=localhost -e port=1883 -e accessToken=qTe5oDBHPJf0KCSKO8J3 --restart always thingsboard/tb-gateway" + ) + } + ) + ) + }) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/device-connectivity/gateway-launch/{deviceId}", method = RequestMethod.GET) @ResponseBody public JsonNode getGatewayLaunchCommands(@Parameter(description = DEVICE_ID_PARAM_DESCRIPTION) - @PathVariable(DEVICE_ID) String strDeviceId, HttpServletRequest request) throws ThingsboardException, URISyntaxException { + @PathVariable(DEVICE_ID) String strDeviceId, HttpServletRequest request) throws ThingsboardException, URISyntaxException { checkParameter(DEVICE_ID, strDeviceId); DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); - Device device = checkDeviceId(deviceId, Operation.READ_CREDENTIALS); + Device device = checkDeviceId(deviceId, org.thingsboard.server.service.security.permission.Operation.READ_CREDENTIALS); if (!checkIsGateway(device)) { throw new ThingsboardException("The device must be a gateway!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeDetails.java b/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeDetails.java index 88230aec94..2b80a3d0f3 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeDetails.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeDetails.java @@ -35,7 +35,7 @@ public class WidgetTypeDetails extends WidgetType implements HasName, HasTenantI @Schema(description = "Base64 encoded thumbnail") private String image; @NoXss - @Length(fieldName = "description") + @Length(fieldName = "description", max = 1024) @Schema(description = "Description of the widget") private String description; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeRepository.java index 41fa293dd5..f85386b077 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeRepository.java @@ -39,7 +39,7 @@ public interface WidgetTypeRepository extends JpaRepository findSystemWidgetTypes(@Param("systemTenantId") UUID systemTenantId, @Param("searchText") String searchText, @Param("fullSearch") boolean fullSearch, @@ -47,7 +47,7 @@ public interface WidgetTypeRepository extends JpaRepository findAllTenantWidgetTypesByTenantId(@Param("tenantId") UUID tenantId, @Param("nullTenantId") UUID nullTenantId, @Param("searchText") String searchText, @@ -56,7 +56,7 @@ public interface WidgetTypeRepository extends JpaRepository findTenantWidgetTypesByTenantId(@Param("tenantId") UUID tenantId, @Param("searchText") String searchText, @Param("fullSearch") boolean fullSearch, diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java index cb147020f1..de997ef45c 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java @@ -203,7 +203,6 @@ public class TbRestApiCallNodeTest { ArgumentCaptor msgCaptor = ArgumentCaptor.forClass(TbMsg.class); ArgumentCaptor metadataCaptor = ArgumentCaptor.forClass(TbMsgMetaData.class); ArgumentCaptor dataCaptor = ArgumentCaptor.forClass(String.class); - //verify(ctx).transformMsg(msgCaptor.capture(), typeCaptor.capture(), originatorCaptor.capture(), metadataCaptor.capture(), dataCaptor.capture()); verify(ctx).transformMsg(msgCaptor.capture(), metadataCaptor.capture(), dataCaptor.capture()); assertNotSame(metaData, metadataCaptor.getValue());