diff --git a/application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java b/application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java index 70a4cd1583..6d10c36203 100644 --- a/application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java +++ b/application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java @@ -240,7 +240,6 @@ public class SwaggerConfiguration { return GroupedOpenApi.builder() .group(groupName) .pathsToMatch(apiPath) - //.addRouterOperationCustomizer(routerOperationCustomizer(localSpringDocParameterNameDiscoverer)) // removed to meet open-api standard .addOperationCustomizer(operationCustomizer()) .addOpenApiCustomizer(customOpenApiCustomizer()) .build(); @@ -553,7 +552,6 @@ public class SwaggerConfiguration { private static ApiResponses loginErrorResponses() { ApiResponses apiResponses = new ApiResponses(); - // Combine all 401 examples into a single map Map unauthorizedExamples = new LinkedHashMap<>(); unauthorizedExamples.put("bad-credentials", errorExample("Bad credentials", @@ -574,14 +572,12 @@ public class SwaggerConfiguration { unauthorizedExamples.put("credentials-expired", errorExample("Expired credentials", ThingsboardCredentialsExpiredResponse.of("User password expired!", StringUtils.randomAlphanumeric(30)))); - // Create a schema that can represent both response types using oneOf Schema unauthorizedSchema = new Schema<>(); unauthorizedSchema.oneOf(List.of( new Schema().$ref("#/components/schemas/ThingsboardErrorResponse"), new Schema().$ref("#/components/schemas/ThingsboardCredentialsExpiredResponse") )); - // Add single 401 response with all examples apiResponses.addApiResponse("401", errorResponse("Unauthorized", unauthorizedExamples, unauthorizedSchema)); return apiResponses; diff --git a/application/src/main/java/org/thingsboard/server/controller/EntitiesVersionControlController.java b/application/src/main/java/org/thingsboard/server/controller/EntitiesVersionControlController.java index e56c2ecf83..89ce5220fd 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EntitiesVersionControlController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EntitiesVersionControlController.java @@ -160,10 +160,8 @@ public class EntitiesVersionControlController extends BaseController { "status of operation via `getVersionCreateRequestStatus`.\n" + TENANT_AUTHORITY_PARAGRAPH) @PostMapping("/version") - public DeferredResult saveEntitiesVersion(@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "A JSON value representing the version create request.", - required = true, content = @Content(mediaType = "application/json", - schema = @Schema(implementation = VersionCreateRequest.class))) - @RequestBody VersionCreateRequest request) throws Exception { + public DeferredResult saveEntitiesVersion(@io.swagger.v3.oas.annotations.parameters.RequestBody(content = @Content(schema = @Schema(implementation = VersionCreateRequest.class))) + @RequestBody VersionCreateRequest request) throws Exception { SecurityUser user = getCurrentUser(); accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.WRITE); return wrapFuture(versionControlService.saveEntitiesVersion(user, request)); @@ -431,10 +429,8 @@ public class EntitiesVersionControlController extends BaseController { "via `getVersionLoadRequestStatus`." + TENANT_AUTHORITY_PARAGRAPH) @PostMapping("/entity") - public UUID loadEntitiesVersion(@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "A JSON value representing the version load request.", - required = true, content = @Content(mediaType = "application/json", - schema = @Schema(implementation = VersionLoadRequest.class))) - @RequestBody VersionLoadRequest request) throws Exception { + public UUID loadEntitiesVersion(@io.swagger.v3.oas.annotations.parameters.RequestBody(content = @Content(schema = @Schema(implementation = VersionLoadRequest.class))) + @RequestBody VersionLoadRequest request) throws Exception { SecurityUser user = getCurrentUser(); accessControlService.checkPermission(user, Resource.VERSION_CONTROL, Operation.WRITE); return versionControlService.loadEntitiesVersion(user, request); diff --git a/application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java b/application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java index 3faeef3ea8..5a66313a08 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java @@ -260,7 +260,7 @@ public class EntityRelationController extends BaseController { SECURITY_CHECKS_ENTITY_DESCRIPTION) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @GetMapping(value = "/relations/from/{fromType}/{fromId}/{relationType}") - public List findByFromV2(@Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @PathVariable(FROM_TYPE) String strFromType, + public List findByFromAndRelationTypeV2(@Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @PathVariable(FROM_TYPE) String strFromType, @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable(FROM_ID) String strFromId, @Parameter(description = RELATION_TYPE_PARAM_DESCRIPTION, required = true) @PathVariable(RELATION_TYPE) String strRelationType, @Parameter(description = RELATION_TYPE_GROUP_PARAM_DESCRIPTION) @@ -344,7 +344,7 @@ public class EntityRelationController extends BaseController { SECURITY_CHECKS_ENTITY_DESCRIPTION) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @GetMapping(value = "/relations/to/{toType}/{toId}/{relationType}") - public List findByToV2(@Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @PathVariable(TO_TYPE) String strToType, + public List findByToAndRelationTypeV2(@Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @PathVariable(TO_TYPE) String strToType, @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable(TO_ID) String strToId, @Parameter(description = RELATION_TYPE_PARAM_DESCRIPTION, required = true) @PathVariable(RELATION_TYPE) String strRelationType, @Parameter(description = RELATION_TYPE_GROUP_PARAM_DESCRIPTION) diff --git a/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java b/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java index cdf030135d..87c6d39679 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java @@ -170,7 +170,7 @@ public class EntityViewController extends BaseController { notes = "Fetch the Entity View object based on the tenant id and entity view name. " + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @GetMapping(value = "/tenant/entityView") - public EntityView getTenantEntityViewV2( + public EntityView getTenantEntityViewByName( @Parameter(description = "Entity View name") @RequestParam String entityViewName) throws ThingsboardException { return getTenantEntityView(entityViewName); diff --git a/application/src/main/java/org/thingsboard/server/controller/EventController.java b/application/src/main/java/org/thingsboard/server/controller/EventController.java index d05c3b94fd..c8e3e25531 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EventController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EventController.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.controller; +import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; @@ -153,6 +154,7 @@ public class EventController extends BaseController { return checkNotNull(eventService.findEvents(tenantId, entityId, resolveEventType(eventType), pageLink)); } + @Hidden @ApiOperation(value = "Get Events (Deprecated)", notes = "Returns a page of events for specified entity. Deprecated and will be removed in next minor release. " + "The call was deprecated to improve the performance of the system. " + @@ -214,7 +216,7 @@ public class EventController extends BaseController { @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, @Parameter(description = "A JSON value representing the event filter.", required = true) - @io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = @Content(schema = @Schema(implementation = EventFilter.class))) + @io.swagger.v3.oas.annotations.parameters.RequestBody(content = @Content(schema = @Schema(implementation = EventFilter.class))) @RequestBody EventFilter eventFilter, @Parameter(description = EVENT_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, @@ -249,9 +251,7 @@ public class EventController extends BaseController { @RequestParam(required = false) Long startTime, @Parameter(description = EVENT_END_TIME_DESCRIPTION) @RequestParam(required = false) Long endTime, - @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "A JSON value representing the event filter.", - required = true, content = @Content(mediaType = "application/json", - schema = @Schema(implementation = EventFilter.class))) + @io.swagger.v3.oas.annotations.parameters.RequestBody(content = @Content(schema = @Schema(implementation = EventFilter.class))) @RequestBody EventFilter eventFilter) throws ThingsboardException { checkParameter("EntityId", strEntityId); checkParameter("EntityType", strEntityType); diff --git a/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java b/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java index 79136c355e..ea6fb5c7e6 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java @@ -173,9 +173,7 @@ public class TelemetryController extends BaseController { "\n * CLIENT_SCOPE - supported for devices;" + "\n * SHARED_SCOPE - supported for devices. " + "\n\n" + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(responseCode = "200", description = "OK", - content = @Content(mediaType = "application/json", - array = @ArraySchema(schema = @Schema(type = "string"))))) + responses = @ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(type = "string"))))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/{entityType}/{entityId}/keys/attributes", method = RequestMethod.GET) @ResponseBody @@ -191,9 +189,7 @@ public class TelemetryController extends BaseController { "\n * CLIENT_SCOPE - supported for devices;" + "\n * SHARED_SCOPE - supported for devices. " + "\n\n" + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(responseCode = "200", description = "OK", - content = @Content(mediaType = "application/json", - array = @ArraySchema(schema = @Schema(type = "string"))))) + responses = @ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(type = "string"))))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/{entityType}/{entityId}/keys/attributes/{scope}", method = RequestMethod.GET) @ResponseBody @@ -212,9 +208,7 @@ public class TelemetryController extends BaseController { + ATTRIBUTE_DATA_EXAMPLE + MARKDOWN_CODE_BLOCK_END + "\n\n " + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(responseCode = "200", description = "OK", - content = @Content(mediaType = "application/json", - array = @ArraySchema(schema = @Schema(implementation = AttributeData.class))))) + responses = @ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = AttributeData.class))))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/{entityType}/{entityId}/values/attributes", method = RequestMethod.GET) @ResponseBody @@ -237,9 +231,7 @@ public class TelemetryController extends BaseController { + ATTRIBUTE_DATA_EXAMPLE + MARKDOWN_CODE_BLOCK_END + "\n\n " + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(responseCode = "200", description = "OK", - content = @Content(mediaType = "application/json", - array = @ArraySchema(schema = @Schema(implementation = AttributeData.class))))) + responses = @ApiResponse(content = @Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = AttributeData.class))))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/{entityType}/{entityId}/values/attributes/{scope}", method = RequestMethod.GET) @ResponseBody @@ -256,9 +248,7 @@ public class TelemetryController extends BaseController { @ApiOperation(value = "Get time series keys (getTimeseriesKeys)", 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, - responses = @ApiResponse(responseCode = "200", description = "OK", - content = @Content(mediaType = "application/json", - array = @ArraySchema(schema = @Schema(type = "string"))))) + responses = @ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(type = "string"))))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/{entityType}/{entityId}/keys/timeseries", method = RequestMethod.GET) @ResponseBody @@ -281,9 +271,7 @@ public class TelemetryController extends BaseController { + LATEST_TS_STRICT_DATA_EXAMPLE + MARKDOWN_CODE_BLOCK_END + "\n\n " + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(responseCode = "200", description = "OK", - content = @Content(mediaType = "application/json", - schema = @Schema(type = "object", additionalPropertiesSchema = TsData[].class)))) + responses = @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(type = "object", additionalPropertiesSchema = TsData[].class)))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @GetMapping(value = "/{entityType}/{entityId}/values/timeseries") public DeferredResult getLatestTimeseries( @@ -331,9 +319,7 @@ public class TelemetryController extends BaseController { + TS_STRICT_DATA_EXAMPLE + MARKDOWN_CODE_BLOCK_END + "\n\n" + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(responseCode = "200", description = "OK", - content = @Content(mediaType = "application/json", - schema = @Schema(type = "object", additionalPropertiesSchema = TsData[].class)))) + responses = @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(type = "object", additionalPropertiesSchema = TsData[].class)))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @GetMapping(value = "/{entityType}/{entityId}/values/timeseries/history") public DeferredResult getTimeseriesHistory( diff --git a/application/src/main/java/org/thingsboard/server/controller/TwoFactorAuthConfigController.java b/application/src/main/java/org/thingsboard/server/controller/TwoFactorAuthConfigController.java index 4a682afcc4..f33f63af0c 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TwoFactorAuthConfigController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TwoFactorAuthConfigController.java @@ -70,11 +70,6 @@ public class TwoFactorAuthConfigController extends BaseController { " \"SMS\": {\n \"providerType\": \"SMS\",\n \"useByDefault\": false,\n \"phoneNumber\": \"+380501253652\"\n }\n" + " }\n}\n```" + ControllerConstants.AVAILABLE_FOR_ANY_AUTHORIZED_USER) - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(mediaType = "application/json", - schema = @Schema(implementation = AccountTwoFaSettings.class))) - }) @GetMapping("/account/settings") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") public AccountTwoFaSettings getAccountTwoFaSettings() throws ThingsboardException { @@ -108,9 +103,7 @@ public class TwoFactorAuthConfigController extends BaseController { "Will throw an error (Bad Request) if the provider is not configured for usage. " + ControllerConstants.AVAILABLE_FOR_ANY_AUTHORIZED_USER) @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(mediaType = "application/json", - schema = @Schema(implementation = TwoFaAccountConfig.class))) + @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TwoFaAccountConfig.class))) }) @PostMapping("/account/config/generate") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @@ -142,9 +135,7 @@ public class TwoFactorAuthConfigController extends BaseController { ControllerConstants.AVAILABLE_FOR_ANY_AUTHORIZED_USER) @PostMapping("/account/config/submit") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") - public void submitTwoFaAccountConfig(@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "2FA account config to submit for verification", - required = true, content = @Content(mediaType = "application/json", - schema = @Schema(implementation = TwoFaAccountConfig.class))) + public void submitTwoFaAccountConfig(@io.swagger.v3.oas.annotations.parameters.RequestBody(content = @Content(schema = @Schema(implementation = TwoFaAccountConfig.class))) @Valid @RequestBody TwoFaAccountConfig accountConfig) throws Exception { SecurityUser user = getCurrentUser(); twoFactorAuthService.prepareVerificationCode(user, accountConfig, false); @@ -155,11 +146,6 @@ public class TwoFactorAuthConfigController extends BaseController { "Returns whole account's 2FA settings object.\n" + "Will throw an error (Bad Request) if the provider is not configured for usage. " + ControllerConstants.AVAILABLE_FOR_ANY_AUTHORIZED_USER) - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(mediaType = "application/json", - schema = @Schema(implementation = AccountTwoFaSettings.class))) - }) @PostMapping("/account/config") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") public AccountTwoFaSettings verifyAndSaveTwoFaAccountConfig(@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "2FA account config to submit for verification", @@ -191,11 +177,6 @@ public class TwoFactorAuthConfigController extends BaseController { "```\n{\n \"useByDefault\": true\n}\n```\n" + "Returns whole account's 2FA settings object.\n" + ControllerConstants.AVAILABLE_FOR_ANY_AUTHORIZED_USER) - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(mediaType = "application/json", - schema = @Schema(implementation = AccountTwoFaSettings.class))) - }) @PutMapping("/account/config") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") public AccountTwoFaSettings updateTwoFaAccountConfig(@RequestParam TwoFaProviderType providerType, @@ -215,11 +196,6 @@ public class TwoFactorAuthConfigController extends BaseController { "Delete 2FA config for a given 2FA provider type. \n" + "Returns whole account's 2FA settings object.\n" + ControllerConstants.AVAILABLE_FOR_ANY_AUTHORIZED_USER) - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(mediaType = "application/json", - schema = @Schema(implementation = AccountTwoFaSettings.class))) - }) @DeleteMapping("/account/config") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") public AccountTwoFaSettings deleteTwoFaAccountConfig(@RequestParam TwoFaProviderType providerType) throws ThingsboardException { @@ -235,9 +211,7 @@ public class TwoFactorAuthConfigController extends BaseController { ControllerConstants.AVAILABLE_FOR_ANY_AUTHORIZED_USER ) @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(mediaType = "application/json", - array = @ArraySchema(schema = @Schema(implementation = TwoFaProviderType.class)))) + @ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = TwoFaProviderType.class)))) }) @GetMapping("/providers") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @@ -253,11 +227,6 @@ public class TwoFactorAuthConfigController extends BaseController { notes = "Get platform settings for 2FA. The settings are described for savePlatformTwoFaSettings API method. " + "If 2FA is not configured, then an empty response will be returned." + ControllerConstants.SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(mediaType = "application/json", - schema = @Schema(implementation = PlatformTwoFaSettings.class))) - }) @GetMapping("/settings") @PreAuthorize("hasAnyAuthority('SYS_ADMIN')") public PlatformTwoFaSettings getPlatformTwoFaSettings() throws ThingsboardException { @@ -305,17 +274,9 @@ public class TwoFactorAuthConfigController extends BaseController { " \"totalAllowedTimeForVerification\": 600\n" + "}\n```" + ControllerConstants.SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "OK", - content = @Content(mediaType = "application/json", - schema = @Schema(implementation = PlatformTwoFaSettings.class))) - }) @PostMapping("/settings") @PreAuthorize("hasAnyAuthority('SYS_ADMIN')") - public PlatformTwoFaSettings savePlatformTwoFaSettings(@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "Platform 2FA settings", - required = true, content = @Content(mediaType = "application/json", - schema = @Schema(implementation = PlatformTwoFaSettings.class))) - @RequestBody PlatformTwoFaSettings twoFaSettings) throws ThingsboardException { + public PlatformTwoFaSettings savePlatformTwoFaSettings(@RequestBody PlatformTwoFaSettings twoFaSettings) throws ThingsboardException { return twoFaConfigManager.savePlatformTwoFaSettings(getTenantId(), twoFaSettings); } diff --git a/application/src/main/java/org/thingsboard/server/controller/UserController.java b/application/src/main/java/org/thingsboard/server/controller/UserController.java index 03228e7c7d..14dcab3b79 100644 --- a/application/src/main/java/org/thingsboard/server/controller/UserController.java +++ b/application/src/main/java/org/thingsboard/server/controller/UserController.java @@ -470,6 +470,16 @@ public class UserController extends BaseController { userSettingsService.updateUserSettings(currentUser.getTenantId(), currentUser.getId(), UserSettingsType.GENERAL, settings); } + @ApiOperation(value = "Update user settings (saveUserSettings)", + notes = "Update user settings for authorized user. Only specified json elements will be updated." + + "Example: you have such settings: {A:5, B:{C:10, D:20}}. Updating it with {B:{C:10, D:30}} will result in" + + "{A:5, B:{C:10, D:30}}. The same could be achieved by putting {B.D:30}") + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") + @PutMapping(value = "/user/settings/general") + public void putGeneralUserSettings(@RequestBody JsonNode settings) throws ThingsboardException { + putUserSettings(settings); + } + @Hidden @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @GetMapping(value = "/user/settings") @@ -480,6 +490,14 @@ public class UserController extends BaseController { return userSettings == null ? JacksonUtil.newObjectNode() : userSettings.getSettings(); } + @ApiOperation(value = "Get user settings (getUserSettings)", + notes = "Fetch the User settings based on authorized user. ") + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") + @GetMapping(value = "/user/settings/general") + public JsonNode getGeneralUserSettings() throws ThingsboardException { + return getUserSettings(); + } + @ApiOperation(value = "Delete user settings (deleteUserSettings)", notes = "Delete user settings by specifying list of json element xpaths. \n " + "Example: to delete B and C element in { \"A\": {\"B\": 5}, \"C\": 15} send A.B,C in jsonPaths request parameter") diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/dto/TbUserMessage.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/dto/TbUserMessage.java index 2d060dbf4a..95fe090bb0 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/dto/TbUserMessage.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/dto/TbUserMessage.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.common.data.ai.dto; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; @@ -24,9 +25,6 @@ import java.util.List; public record TbUserMessage( @NotEmpty @Valid - @Schema( - requiredMode = Schema.RequiredMode.REQUIRED, - description = "A list of content parts that make up the complete user prompt" - ) + @ArraySchema(schema = @Schema(ref = "#/components/schemas/TbContent")) List contents ) {} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmCondition.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmCondition.java index a4da4ceae0..bd5b05da98 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmCondition.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmCondition.java @@ -16,6 +16,7 @@ package org.thingsboard.server.common.data.device.profile; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.Valid; import lombok.Data; @@ -29,7 +30,7 @@ import java.util.List; public class AlarmCondition implements Serializable { @Valid - @Schema(description = "JSON array of alarm condition filters") + @ArraySchema(schema = @Schema(ref = "#/components/schemas/AlarmConditionFilter")) private List condition; @Schema(description = "JSON object representing alarm condition type") private AlarmConditionSpec spec; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/job/DummyJobConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/job/DummyJobConfiguration.java index 28ebcd2095..c36d40dc26 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/job/DummyJobConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/job/DummyJobConfiguration.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.common.data.job; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -24,6 +25,7 @@ import lombok.ToString; import java.util.List; +@Schema(description = "Dummy job configuration", allOf = JobConfiguration.class) @Data @EqualsAndHashCode(callSuper = true) @AllArgsConstructor diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/job/JobConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/job/JobConfiguration.java index 9480ba11c3..6a10dc7ea1 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/job/JobConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/job/JobConfiguration.java @@ -20,6 +20,9 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonSubTypes.Type; import com.fasterxml.jackson.annotation.JsonTypeInfo; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.DiscriminatorMapping; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import lombok.Data; import org.thingsboard.server.common.data.job.task.TaskResult; @@ -27,6 +30,12 @@ import org.thingsboard.server.common.data.job.task.TaskResult; import java.io.Serializable; import java.util.List; +@Schema( + discriminatorProperty = "type", + discriminatorMapping = { + @DiscriminatorMapping(value = "DUMMY", schema = DummyJobConfiguration.class) + } +) @JsonIgnoreProperties(ignoreUnknown = true) @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") @JsonSubTypes({ @@ -37,6 +46,7 @@ public abstract class JobConfiguration implements Serializable { @NotBlank private String tasksKey; // internal + @ArraySchema(schema = @Schema(ref = "#/components/schemas/TaskResult")) private List toReprocess; // internal @JsonIgnore diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/job/JobResult.java b/common/data/src/main/java/org/thingsboard/server/common/data/job/JobResult.java index 714ee236a8..f789e58bcb 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/job/JobResult.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/job/JobResult.java @@ -20,6 +20,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonSubTypes.Type; import com.fasterxml.jackson.annotation.JsonTypeInfo; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.DiscriminatorMapping; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -54,7 +55,7 @@ public abstract class JobResult implements Serializable { private int discardedCount; @Schema(description = "Total number of tasks, set when all tasks are submitted", nullable = true) private Integer totalCount = null; - @Schema(description = "List of task results, preserving only first 100 errors") + @ArraySchema(schema = @Schema(ref = "#/components/schemas/TaskResult")) private List results = new ArrayList<>(); @Schema(description = "General error message if the job failed") private String generalError; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/EscalatedNotificationRuleRecipientsConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/EscalatedNotificationRuleRecipientsConfig.java index 459a15c0fd..2cc27ad7a7 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/EscalatedNotificationRuleRecipientsConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/EscalatedNotificationRuleRecipientsConfig.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.common.data.notification.rule; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotEmpty; import lombok.Data; import lombok.EqualsAndHashCode; @@ -23,6 +24,7 @@ import java.util.List; import java.util.Map; import java.util.UUID; +@Schema(description = "Escalated notification rule recipients configuration", allOf = NotificationRuleRecipientsConfig.class) @Data @EqualsAndHashCode(callSuper = true) public class EscalatedNotificationRuleRecipientsConfig extends NotificationRuleRecipientsConfig { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/NotificationRuleRecipientsConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/NotificationRuleRecipientsConfig.java index fda73b8059..d56312da33 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/NotificationRuleRecipientsConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/NotificationRuleRecipientsConfig.java @@ -20,6 +20,8 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonSubTypes.Type; import com.fasterxml.jackson.annotation.JsonTypeInfo; +import io.swagger.v3.oas.annotations.media.DiscriminatorMapping; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; import org.thingsboard.server.common.data.notification.rule.trigger.config.NotificationRuleTriggerType; @@ -29,6 +31,11 @@ import java.util.List; import java.util.Map; import java.util.UUID; +@Schema( + discriminatorProperty = "triggerType", + discriminatorMapping = { + @DiscriminatorMapping(value = "ALARM", schema = EscalatedNotificationRuleRecipientsConfig.class) + }) @JsonIgnoreProperties @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "triggerType", visible = true, include = JsonTypeInfo.As.EXISTING_PROPERTY, defaultImpl = DefaultNotificationRuleRecipientsConfig.class) @JsonSubTypes({