Browse Source

Merge pull request #5279 from thingsboard/feature/swagger

Swagger Annotations to improve the auto-generated REST API doc.
pull/5442/head
Andrew Shvayka 5 years ago
committed by GitHub
parent
commit
ab356a4bc9
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 45
      application/src/main/java/org/thingsboard/server/controller/AdminController.java
  2. 128
      application/src/main/java/org/thingsboard/server/controller/AssetController.java
  3. 86
      application/src/main/java/org/thingsboard/server/controller/AuthController.java
  4. 42
      application/src/main/java/org/thingsboard/server/controller/BaseController.java
  5. 34
      application/src/main/java/org/thingsboard/server/controller/ComponentDescriptorController.java
  6. 60
      application/src/main/java/org/thingsboard/server/controller/CustomerController.java
  7. 202
      application/src/main/java/org/thingsboard/server/controller/DashboardController.java
  8. 187
      application/src/main/java/org/thingsboard/server/controller/DeviceController.java
  9. 3
      application/src/main/java/org/thingsboard/server/controller/EntityViewController.java
  10. 4
      application/src/main/java/org/thingsboard/server/controller/TenantController.java
  11. 30
      application/src/main/java/org/thingsboard/server/service/security/model/ActivateUserRequest.java
  12. 31
      application/src/main/java/org/thingsboard/server/service/security/model/ChangePasswordRequest.java
  13. 32
      application/src/main/java/org/thingsboard/server/service/security/model/JwtTokenPair.java
  14. 29
      application/src/main/java/org/thingsboard/server/service/security/model/ResetPasswordEmailRequest.java
  15. 30
      application/src/main/java/org/thingsboard/server/service/security/model/ResetPasswordRequest.java
  16. 4
      common/data/pom.xml
  17. 18
      common/data/src/main/java/org/thingsboard/server/common/data/AdminSettings.java
  18. 5
      common/data/src/main/java/org/thingsboard/server/common/data/Dashboard.java
  19. 25
      common/data/src/main/java/org/thingsboard/server/common/data/DashboardInfo.java
  20. 34
      common/data/src/main/java/org/thingsboard/server/common/data/Device.java
  21. 6
      common/data/src/main/java/org/thingsboard/server/common/data/DeviceInfo.java
  22. 6
      common/data/src/main/java/org/thingsboard/server/common/data/HomeDashboard.java
  23. 5
      common/data/src/main/java/org/thingsboard/server/common/data/HomeDashboardInfo.java
  24. 6
      common/data/src/main/java/org/thingsboard/server/common/data/ShortCustomerInfo.java
  25. 5
      common/data/src/main/java/org/thingsboard/server/common/data/UpdateMessage.java
  26. 33
      common/data/src/main/java/org/thingsboard/server/common/data/User.java
  27. 30
      common/data/src/main/java/org/thingsboard/server/common/data/asset/Asset.java
  28. 5
      common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetInfo.java
  29. 4
      common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetSearchQuery.java
  30. 6
      common/data/src/main/java/org/thingsboard/server/common/data/device/DeviceSearchQuery.java
  31. 2
      common/data/src/main/java/org/thingsboard/server/common/data/device/data/DefaultDeviceConfiguration.java
  32. 2
      common/data/src/main/java/org/thingsboard/server/common/data/device/data/DeviceConfiguration.java
  33. 2
      common/data/src/main/java/org/thingsboard/server/common/data/device/data/DeviceData.java
  34. 2
      common/data/src/main/java/org/thingsboard/server/common/data/device/data/DeviceTransportConfiguration.java
  35. 5
      common/data/src/main/java/org/thingsboard/server/common/data/id/AlarmId.java
  36. 5
      common/data/src/main/java/org/thingsboard/server/common/data/id/ApiUsageStateId.java
  37. 5
      common/data/src/main/java/org/thingsboard/server/common/data/id/AssetId.java
  38. 5
      common/data/src/main/java/org/thingsboard/server/common/data/id/CustomerId.java
  39. 5
      common/data/src/main/java/org/thingsboard/server/common/data/id/DashboardId.java
  40. 5
      common/data/src/main/java/org/thingsboard/server/common/data/id/DeviceId.java
  41. 3
      common/data/src/main/java/org/thingsboard/server/common/data/id/DeviceProfileId.java
  42. 3
      common/data/src/main/java/org/thingsboard/server/common/data/id/EdgeId.java
  43. 2
      common/data/src/main/java/org/thingsboard/server/common/data/id/EntityViewId.java
  44. 3
      common/data/src/main/java/org/thingsboard/server/common/data/id/OtaPackageId.java
  45. 3
      common/data/src/main/java/org/thingsboard/server/common/data/id/RpcId.java
  46. 3
      common/data/src/main/java/org/thingsboard/server/common/data/id/RuleChainId.java
  47. 3
      common/data/src/main/java/org/thingsboard/server/common/data/id/RuleNodeId.java
  48. 3
      common/data/src/main/java/org/thingsboard/server/common/data/id/TbResourceId.java
  49. 3
      common/data/src/main/java/org/thingsboard/server/common/data/id/TenantId.java
  50. 3
      common/data/src/main/java/org/thingsboard/server/common/data/id/TenantProfileId.java
  51. 5
      common/data/src/main/java/org/thingsboard/server/common/data/id/UUIDBased.java
  52. 3
      common/data/src/main/java/org/thingsboard/server/common/data/id/UserId.java
  53. 3
      common/data/src/main/java/org/thingsboard/server/common/data/id/WidgetTypeId.java
  54. 3
      common/data/src/main/java/org/thingsboard/server/common/data/id/WidgetsBundleId.java
  55. 7
      common/data/src/main/java/org/thingsboard/server/common/data/page/PageData.java
  56. 26
      common/data/src/main/java/org/thingsboard/server/common/data/plugin/ComponentDescriptor.java
  57. 9
      common/data/src/main/java/org/thingsboard/server/common/data/relation/RelationsSearchParameters.java
  58. 28
      common/data/src/main/java/org/thingsboard/server/common/data/security/DeviceCredentials.java
  59. 7
      common/data/src/main/java/org/thingsboard/server/common/data/security/model/SecuritySettings.java
  60. 10
      common/data/src/main/java/org/thingsboard/server/common/data/security/model/UserPasswordPolicy.java
  61. 6
      common/data/src/main/java/org/thingsboard/server/common/data/sms/config/AwsSnsSmsProviderConfiguration.java
  62. 6
      common/data/src/main/java/org/thingsboard/server/common/data/sms/config/TestSmsRequest.java
  63. 6
      common/data/src/main/java/org/thingsboard/server/common/data/sms/config/TwilioSmsProviderConfiguration.java
  64. 6
      pom.xml

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

@ -16,6 +16,8 @@
package org.thingsboard.server.controller;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
@ -44,6 +46,7 @@ import org.thingsboard.server.service.update.UpdateService;
@RequestMapping("/api/admin")
public class AdminController extends BaseController {
public static final String SYS_ADMIN_AUTHORITY_ONLY = " Available for users with System Administrator ('SYS_ADMIN') authority only.";
@Autowired
private MailService mailService;
@ -59,10 +62,14 @@ public class AdminController extends BaseController {
@Autowired
private UpdateService updateService;
@ApiOperation(value = "Get the Administration Settings object using key (getAdminSettings)",
notes = "Get the Administration Settings object using specified string key. Referencing non-existing key will cause an error." + SYS_ADMIN_AUTHORITY_ONLY)
@PreAuthorize("hasAuthority('SYS_ADMIN')")
@RequestMapping(value = "/settings/{key}", method = RequestMethod.GET)
@ResponseBody
public AdminSettings getAdminSettings(@PathVariable("key") String key) throws ThingsboardException {
public AdminSettings getAdminSettings(
@ApiParam(value = "A string value of the key (e.g. 'general' or 'mail').")
@PathVariable("key") String key) throws ThingsboardException {
try {
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ);
AdminSettings adminSettings = checkNotNull(adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, key));
@ -75,10 +82,17 @@ public class AdminController extends BaseController {
}
}
@ApiOperation(value = "Get the Administration Settings object using key (getAdminSettings)",
notes = "Creates or Updates the Administration Settings. Platform generates random Administration Settings Id during settings creation. " +
"The Administration Settings Id will be present in the response. Specify the Administration Settings Id when you would like to update the Administration Settings. " +
"Referencing non-existing Administration Settings Id will cause an error." + SYS_ADMIN_AUTHORITY_ONLY)
@PreAuthorize("hasAuthority('SYS_ADMIN')")
@RequestMapping(value = "/settings", method = RequestMethod.POST)
@ResponseBody
public AdminSettings saveAdminSettings(@RequestBody AdminSettings adminSettings) throws ThingsboardException {
public AdminSettings saveAdminSettings(
@ApiParam(value = "A JSON value representing the Administration Settings.")
@RequestBody AdminSettings adminSettings) throws ThingsboardException {
try {
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.WRITE);
adminSettings = checkNotNull(adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, adminSettings));
@ -94,6 +108,8 @@ public class AdminController extends BaseController {
}
}
@ApiOperation(value = "Get the Security Settings object",
notes = "Get the Security Settings object that contains password policy, etc." + SYS_ADMIN_AUTHORITY_ONLY)
@PreAuthorize("hasAuthority('SYS_ADMIN')")
@RequestMapping(value = "/securitySettings", method = RequestMethod.GET)
@ResponseBody
@ -106,10 +122,14 @@ public class AdminController extends BaseController {
}
}
@ApiOperation(value = "Update Security Settings (saveSecuritySettings)",
notes = "Updates the Security Settings object that contains password policy, etc." + SYS_ADMIN_AUTHORITY_ONLY)
@PreAuthorize("hasAuthority('SYS_ADMIN')")
@RequestMapping(value = "/securitySettings", method = RequestMethod.POST)
@ResponseBody
public SecuritySettings saveSecuritySettings(@RequestBody SecuritySettings securitySettings) throws ThingsboardException {
public SecuritySettings saveSecuritySettings(
@ApiParam(value = "A JSON value representing the Security Settings.")
@RequestBody SecuritySettings securitySettings) throws ThingsboardException {
try {
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.WRITE);
securitySettings = checkNotNull(systemSecurityService.saveSecuritySettings(TenantId.SYS_TENANT_ID, securitySettings));
@ -119,14 +139,19 @@ public class AdminController extends BaseController {
}
}
@ApiOperation(value = "Send test email (sendTestMail)",
notes = "Attempts to send test email to the System Administrator User using Mail Settings provided as a parameter. " +
"You may change the 'To' email in the user profile of the System Administrator. " + SYS_ADMIN_AUTHORITY_ONLY)
@PreAuthorize("hasAuthority('SYS_ADMIN')")
@RequestMapping(value = "/settings/testMail", method = RequestMethod.POST)
public void sendTestMail(@RequestBody AdminSettings adminSettings) throws ThingsboardException {
public void sendTestMail(
@ApiParam(value = "A JSON value representing the Mail Settings.")
@RequestBody AdminSettings adminSettings) throws ThingsboardException {
try {
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ);
adminSettings = checkNotNull(adminSettings);
if (adminSettings.getKey().equals("mail")) {
if(!adminSettings.getJsonValue().has("password")) {
if (!adminSettings.getJsonValue().has("password")) {
AdminSettings mailSettings = checkNotNull(adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, "mail"));
((ObjectNode) adminSettings.getJsonValue()).put("password", mailSettings.getJsonValue().get("password").asText());
}
@ -138,9 +163,14 @@ public class AdminController extends BaseController {
}
}
@ApiOperation(value = "Send test sms (sendTestMail)",
notes = "Attempts to send test sms to the System Administrator User using SMS Settings and phone number provided as a parameters of the request. "
+ SYS_ADMIN_AUTHORITY_ONLY)
@PreAuthorize("hasAuthority('SYS_ADMIN')")
@RequestMapping(value = "/settings/testSms", method = RequestMethod.POST)
public void sendTestSms(@RequestBody TestSmsRequest testSmsRequest) throws ThingsboardException {
public void sendTestSms(
@ApiParam(value = "A JSON value representing the Test SMS request.")
@RequestBody TestSmsRequest testSmsRequest) throws ThingsboardException {
try {
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ);
smsService.sendTestSms(testSmsRequest);
@ -149,6 +179,9 @@ public class AdminController extends BaseController {
}
}
@ApiOperation(value = "Check for new Platform Releases (checkUpdates)",
notes = "Check notifications about new platform releases. "
+ SYS_ADMIN_AUTHORITY_ONLY)
@PreAuthorize("hasAuthority('SYS_ADMIN')")
@RequestMapping(value = "/updates", method = RequestMethod.GET)
@ResponseBody

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

@ -16,9 +16,12 @@
package org.thingsboard.server.controller;
import com.google.common.util.concurrent.ListenableFuture;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
@ -37,8 +40,8 @@ import org.thingsboard.server.common.data.asset.AssetInfo;
import org.thingsboard.server.common.data.asset.AssetSearchQuery;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.AssetId;
import org.thingsboard.server.common.data.id.CustomerId;
@ -61,9 +64,8 @@ import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import static org.thingsboard.server.dao.asset.BaseAssetService.TB_SERVICE_QUEUE;
import static org.thingsboard.server.controller.EdgeController.EDGE_ID;
import static org.thingsboard.server.dao.asset.BaseAssetService.TB_SERVICE_QUEUE;
@RestController
@TbCoreComponent
@ -75,10 +77,15 @@ public class AssetController extends BaseController {
public static final String ASSET_ID = "assetId";
@ApiOperation(value = "Get Asset (getAssetById)",
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 'Customer User', the server checks that the asset is assigned to the same customer.", produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/asset/{assetId}", method = RequestMethod.GET)
@ResponseBody
public Asset getAssetById(@PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException {
public Asset getAssetById(@ApiParam(value = ASSET_ID_PARAM_DESCRIPTION)
@PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException {
checkParameter(ASSET_ID, strAssetId);
try {
AssetId assetId = new AssetId(toUUID(strAssetId));
@ -88,10 +95,15 @@ public class AssetController extends BaseController {
}
}
@ApiOperation(value = "Get Asset Info (getAssetInfoById)",
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 'Customer User', the server checks that the asset is assigned to the same customer. " + ASSET_INFO_DESCRIPTION, produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/asset/info/{assetId}", method = RequestMethod.GET)
@ResponseBody
public AssetInfo getAssetInfoById(@PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException {
public AssetInfo getAssetInfoById(@ApiParam(value = ASSET_ID_PARAM_DESCRIPTION)
@PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException {
checkParameter(ASSET_ID, strAssetId);
try {
AssetId assetId = new AssetId(toUUID(strAssetId));
@ -101,10 +113,15 @@ public class AssetController extends BaseController {
}
}
@ApiOperation(value = "Create Or Update Asset (saveAsset)",
notes = "Creates or Updates the Asset. When creating asset, platform generates Asset Id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address) " +
"The newly created Asset id will be present in the response. " +
"Specify existing Asset id to update the asset. " +
"Referencing non-existing Asset Id will cause 'Not Found' error.", produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/asset", method = RequestMethod.POST)
@ResponseBody
public Asset saveAsset(@RequestBody Asset asset) throws ThingsboardException {
public Asset saveAsset(@ApiParam(value = "A JSON value representing the asset.") @RequestBody Asset asset) throws ThingsboardException {
try {
if (TB_SERVICE_QUEUE.equals(asset.getType())) {
throw new ThingsboardException("Unable to save asset with type " + TB_SERVICE_QUEUE, ThingsboardErrorCode.BAD_REQUEST_PARAMS);
@ -140,10 +157,12 @@ public class AssetController extends BaseController {
}
}
@ApiOperation(value = "Delete asset (deleteAsset)",
notes = "Deletes the asset and all the relations (from and to the asset). Referencing non-existing asset Id will cause an error.")
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/asset/{assetId}", method = RequestMethod.DELETE)
@ResponseStatus(value = HttpStatus.OK)
public void deleteAsset(@PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException {
public void deleteAsset(@ApiParam(value = ASSET_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException {
checkParameter(ASSET_ID, strAssetId);
try {
AssetId assetId = new AssetId(toUUID(strAssetId));
@ -167,11 +186,13 @@ public class AssetController extends BaseController {
}
}
@ApiOperation(value = "Assign asset to customer (assignAssetToCustomer)",
notes = "Creates assignment of the asset to customer. Customer will be able to query asset afterwards.", produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/customer/{customerId}/asset/{assetId}", method = RequestMethod.POST)
@ResponseBody
public Asset assignAssetToCustomer(@PathVariable("customerId") String strCustomerId,
@PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException {
public Asset assignAssetToCustomer(@ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION) @PathVariable("customerId") String strCustomerId,
@ApiParam(value = ASSET_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException {
checkParameter("customerId", strCustomerId);
checkParameter(ASSET_ID, strAssetId);
try {
@ -201,10 +222,12 @@ public class AssetController extends BaseController {
}
}
@ApiOperation(value = "Unassign asset from customer (unassignAssetFromCustomer)",
notes = "Clears assignment of the asset to customer. Customer will not be able to query asset afterwards.", produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/customer/asset/{assetId}", method = RequestMethod.DELETE)
@ResponseBody
public Asset unassignAssetFromCustomer(@PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException {
public Asset unassignAssetFromCustomer(@ApiParam(value = ASSET_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException {
checkParameter(ASSET_ID, strAssetId);
try {
AssetId assetId = new AssetId(toUUID(strAssetId));
@ -235,10 +258,14 @@ public class AssetController extends BaseController {
}
}
@ApiOperation(value = "Make asset publicly available (assignAssetToPublicCustomer)",
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. " +
"However, users that are logged-in and belong to different tenant will not be able to access the asset.", produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/customer/public/asset/{assetId}", method = RequestMethod.POST)
@ResponseBody
public Asset assignAssetToPublicCustomer(@PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException {
public Asset assignAssetToPublicCustomer(@ApiParam(value = ASSET_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException {
checkParameter(ASSET_ID, strAssetId);
try {
AssetId assetId = new AssetId(toUUID(strAssetId));
@ -261,15 +288,24 @@ public class AssetController extends BaseController {
}
}
@ApiOperation(value = "Get Tenant Assets (getTenantAssets)",
notes = "Returns a page of assets owned by tenant. " +
PAGE_DATA_PARAMETERS, produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/tenant/assets", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody
public PageData<Asset> getTenantAssets(
@ApiParam(value = PAGE_SIZE_DESCRIPTION)
@RequestParam int pageSize,
@ApiParam(value = PAGE_NUMBER_DESCRIPTION)
@RequestParam int page,
@ApiParam(value = ASSET_TYPE_DESCRIPTION)
@RequestParam(required = false) String type,
@ApiParam(value = ASSET_TEXT_SEARCH_DESCRIPTION)
@RequestParam(required = false) String textSearch,
@ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ASSET_SORT_PROPERTY_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException {
try {
TenantId tenantId = getCurrentUser().getTenantId();
@ -284,15 +320,24 @@ public class AssetController extends BaseController {
}
}
@ApiOperation(value = "Get Tenant Asset Infos (getTenantAssetInfos)",
notes = "Returns a page of assets info objects owned by tenant. " +
PAGE_DATA_PARAMETERS + ASSET_INFO_DESCRIPTION, produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/tenant/assetInfos", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody
public PageData<AssetInfo> getTenantAssetInfos(
@ApiParam(value = PAGE_SIZE_DESCRIPTION)
@RequestParam int pageSize,
@ApiParam(value = PAGE_NUMBER_DESCRIPTION)
@RequestParam int page,
@ApiParam(value = ASSET_TYPE_DESCRIPTION)
@RequestParam(required = false) String type,
@ApiParam(value = ASSET_TEXT_SEARCH_DESCRIPTION)
@RequestParam(required = false) String textSearch,
@ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ASSET_SORT_PROPERTY_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException {
try {
TenantId tenantId = getCurrentUser().getTenantId();
@ -307,10 +352,14 @@ public class AssetController extends BaseController {
}
}
@ApiOperation(value = "Get Tenant Asset (getTenantAsset)",
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.", produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/tenant/assets", params = {"assetName"}, method = RequestMethod.GET)
@ResponseBody
public Asset getTenantAsset(
@ApiParam(value = ASSET_NAME_DESCRIPTION)
@RequestParam String assetName) throws ThingsboardException {
try {
TenantId tenantId = getCurrentUser().getTenantId();
@ -320,16 +369,26 @@ public class AssetController extends BaseController {
}
}
@ApiOperation(value = "Get Customer Assets (getCustomerAssets)",
notes = "Returns a page of assets objects assigned to customer. " +
PAGE_DATA_PARAMETERS, produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/customer/{customerId}/assets", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody
public PageData<Asset> getCustomerAssets(
@ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION)
@PathVariable("customerId") String strCustomerId,
@ApiParam(value = PAGE_SIZE_DESCRIPTION)
@RequestParam int pageSize,
@ApiParam(value = PAGE_NUMBER_DESCRIPTION)
@RequestParam int page,
@ApiParam(value = ASSET_TYPE_DESCRIPTION)
@RequestParam(required = false) String type,
@ApiParam(value = ASSET_TEXT_SEARCH_DESCRIPTION)
@RequestParam(required = false) String textSearch,
@ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ASSET_SORT_PROPERTY_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException {
checkParameter("customerId", strCustomerId);
try {
@ -347,16 +406,26 @@ public class AssetController extends BaseController {
}
}
@ApiOperation(value = "Get Customer Asset Infos (getCustomerAssetInfos)",
notes = "Returns a page of assets info objects assigned to customer. " +
PAGE_DATA_PARAMETERS + ASSET_INFO_DESCRIPTION, produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/customer/{customerId}/assetInfos", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody
public PageData<AssetInfo> getCustomerAssetInfos(
@ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION)
@PathVariable("customerId") String strCustomerId,
@ApiParam(value = PAGE_SIZE_DESCRIPTION)
@RequestParam int pageSize,
@ApiParam(value = PAGE_NUMBER_DESCRIPTION)
@RequestParam int page,
@ApiParam(value = ASSET_TYPE_DESCRIPTION)
@RequestParam(required = false) String type,
@ApiParam(value = ASSET_TEXT_SEARCH_DESCRIPTION)
@RequestParam(required = false) String textSearch,
@ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ASSET_SORT_PROPERTY_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException {
checkParameter("customerId", strCustomerId);
try {
@ -374,10 +443,13 @@ public class AssetController extends BaseController {
}
}
@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. ", produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/assets", params = {"assetIds"}, method = RequestMethod.GET)
@ResponseBody
public List<Asset> getAssetsByIds(
@ApiParam(value = "A list of assets ids, separated by comma ','")
@RequestParam("assetIds") String[] strAssetIds) throws ThingsboardException {
checkArrayParameter("assetIds", strAssetIds);
try {
@ -400,6 +472,10 @@ public class AssetController extends BaseController {
}
}
@ApiOperation(value = "Find related assets (findByQuery)",
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. " +
"See 'Model' tab of the Parameters for more info.", produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/assets", method = RequestMethod.POST)
@ResponseBody
@ -424,6 +500,8 @@ public class AssetController extends BaseController {
}
}
@ApiOperation(value = "Get Asset Types (getAssetTypes)",
notes = "Returns a set of unique asset types based on assets that are either owned by the tenant or assigned to the customer which user is performing the request.", produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/asset/types", method = RequestMethod.GET)
@ResponseBody
@ -438,11 +516,15 @@ public class AssetController extends BaseController {
}
}
@ApiOperation(value = "Assign asset to edge (assignAssetToEdge)",
notes = "Creates assignment of an existing asset to an instance of The Edge. " +
"The Edge is a software product for edge computing. " +
"It allows bringing data analysis and management to the edge, while seamlessly synchronizing with the platform server (cloud). ", produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/edge/{edgeId}/asset/{assetId}", method = RequestMethod.POST)
@ResponseBody
public Asset assignAssetToEdge(@PathVariable(EDGE_ID) String strEdgeId,
@PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException {
public Asset assignAssetToEdge(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION) @PathVariable(EDGE_ID) String strEdgeId,
@ApiParam(value = ASSET_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException {
checkParameter(EDGE_ID, strEdgeId);
checkParameter(ASSET_ID, strAssetId);
try {
@ -471,11 +553,13 @@ public class AssetController extends BaseController {
}
}
@ApiOperation(value = "Unassign asset from edge (unassignAssetFromEdge)",
notes = "Clears assignment of the asset to the edge", produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/edge/{edgeId}/asset/{assetId}", method = RequestMethod.DELETE)
@ResponseBody
public Asset unassignAssetFromEdge(@PathVariable(EDGE_ID) String strEdgeId,
@PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException {
public Asset unassignAssetFromEdge(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION) @PathVariable(EDGE_ID) String strEdgeId,
@ApiParam(value = ASSET_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException {
checkParameter(EDGE_ID, strEdgeId);
checkParameter(ASSET_ID, strAssetId);
try {
@ -504,18 +588,30 @@ public class AssetController extends BaseController {
}
}
@ApiOperation(value = "Get assets assigned to edge (getEdgeAssets)",
notes = "Returns a page of assets assigned to edge. " +
PAGE_DATA_PARAMETERS, produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/edge/{edgeId}/assets", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody
public PageData<Asset> getEdgeAssets(
@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION)
@PathVariable(EDGE_ID) String strEdgeId,
@ApiParam(value = PAGE_SIZE_DESCRIPTION)
@RequestParam int pageSize,
@ApiParam(value = PAGE_NUMBER_DESCRIPTION)
@RequestParam int page,
@ApiParam(value = ASSET_TYPE_DESCRIPTION)
@RequestParam(required = false) String type,
@ApiParam(value = ASSET_TEXT_SEARCH_DESCRIPTION)
@RequestParam(required = false) String textSearch,
@ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ASSET_SORT_PROPERTY_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder,
@ApiParam(value = "Timestamp. Assets with creation time before it won't be queried")
@RequestParam(required = false) Long startTime,
@ApiParam(value = "Timestamp. Assets with creation time after it won't be queried")
@RequestParam(required = false) Long endTime) throws ThingsboardException {
checkParameter(EDGE_ID, strEdgeId);
try {
@ -547,6 +643,8 @@ public class AssetController extends BaseController {
}
}
@ApiOperation(value = "Import the bulk of assets (processAssetsBulkImport)",
notes = "There's an ability to import the bulk of assets using the only .csv file.", produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@PostMapping("/asset/bulk_import")
public BulkImportResult<Asset> processAssetsBulkImport(@RequestBody BulkImportRequest request) throws Exception {

86
application/src/main/java/org/thingsboard/server/controller/AuthController.java

@ -18,6 +18,8 @@ package org.thingsboard.server.controller;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
@ -48,8 +50,13 @@ import org.thingsboard.server.common.data.security.model.SecuritySettings;
import org.thingsboard.server.common.data.security.model.UserPasswordPolicy;
import org.thingsboard.server.dao.audit.AuditLogService;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.security.model.ActivateUserRequest;
import org.thingsboard.server.service.security.model.ChangePasswordRequest;
import org.thingsboard.server.service.security.model.ResetPasswordEmailRequest;
import org.thingsboard.server.service.security.model.ResetPasswordRequest;
import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository;
import org.thingsboard.server.service.security.auth.rest.RestAuthenticationDetails;
import org.thingsboard.server.service.security.model.JwtTokenPair;
import org.thingsboard.server.service.security.model.SecurityUser;
import org.thingsboard.server.service.security.model.UserPrincipal;
import org.thingsboard.server.service.security.model.token.JwtTokenFactory;
@ -74,9 +81,13 @@ public class AuthController extends BaseController {
private final AuditLogService auditLogService;
private final ApplicationEventPublisher eventPublisher;
@ApiOperation(value = "Get current User (getUser)",
notes = "Get the information about the User which credentials are used to perform this REST API call.")
@PreAuthorize("isAuthenticated()")
@RequestMapping(value = "/auth/user", method = RequestMethod.GET)
public @ResponseBody User getUser() throws ThingsboardException {
public @ResponseBody
User getUser() throws ThingsboardException {
try {
SecurityUser securityUser = getCurrentUser();
return userService.findUserById(securityUser.getTenantId(), securityUser.getId());
@ -85,6 +96,8 @@ public class AuthController extends BaseController {
}
}
@ApiOperation(value = "Logout (logout)",
notes = "Special API call to record the 'logout' of the user to the Audit Logs. Since platform uses [JWT](https://jwt.io/), the actual logout is the procedure of clearing the [JWT](https://jwt.io/) token on the client side. ")
@PreAuthorize("isAuthenticated()")
@RequestMapping(value = "/auth/logout", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK)
@ -92,13 +105,17 @@ public class AuthController extends BaseController {
logLogoutAction(request);
}
@ApiOperation(value = "Change password for current User (changePassword)",
notes = "Change the password for the User which credentials are used to perform this REST API call. Be aware that previously generated [JWT](https://jwt.io/) tokens will be still valid until they expire.")
@PreAuthorize("isAuthenticated()")
@RequestMapping(value = "/auth/changePassword", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK)
public ObjectNode changePassword(@RequestBody JsonNode changePasswordRequest) throws ThingsboardException {
public ObjectNode changePassword(
@ApiParam(value = "Change Password Request")
@RequestBody ChangePasswordRequest changePasswordRequest) throws ThingsboardException {
try {
String currentPassword = changePasswordRequest.get("currentPassword").asText();
String newPassword = changePasswordRequest.get("newPassword").asText();
String currentPassword = changePasswordRequest.getCurrentPassword();
String newPassword = changePasswordRequest.getNewPassword();
SecurityUser securityUser = getCurrentUser();
UserCredentials userCredentials = userService.findUserCredentialsByUserId(TenantId.SYS_TENANT_ID, securityUser.getId());
if (!passwordEncoder.matches(currentPassword, userCredentials.getPassword())) {
@ -123,6 +140,8 @@ public class AuthController extends BaseController {
}
}
@ApiOperation(value = "Get the current User password policy (getUserPasswordPolicy)",
notes = "API call to get the password policy for the password validation form(s).")
@RequestMapping(value = "/noauth/userPasswordPolicy", method = RequestMethod.GET)
@ResponseBody
public UserPasswordPolicy getUserPasswordPolicy() throws ThingsboardException {
@ -135,8 +154,13 @@ public class AuthController extends BaseController {
}
}
@ApiOperation(value = "Check Activate User Token (checkActivateToken)",
notes = "Checks the activation token and forwards user to 'Create Password' page. " +
"If token is valid, returns '303 See Other' (redirect) response code with the correct address of 'Create Password' page and same 'activateToken' specified in the URL parameters. " +
"If token is not valid, returns '409 Conflict'.")
@RequestMapping(value = "/noauth/activate", params = {"activateToken"}, method = RequestMethod.GET)
public ResponseEntity<String> checkActivateToken(
@ApiParam(value = "The activate token string.")
@RequestParam(value = "activateToken") String activateToken) {
HttpHeaders headers = new HttpHeaders();
HttpStatus responseStatus;
@ -157,13 +181,17 @@ public class AuthController extends BaseController {
return new ResponseEntity<>(headers, responseStatus);
}
@ApiOperation(value = "Request reset password email (requestResetPasswordByEmail)",
notes = "Request to send the reset password email if the user with specified email address is present in the database. " +
"Always return '200 OK' status for security purposes.")
@RequestMapping(value = "/noauth/resetPasswordByEmail", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK)
public void requestResetPasswordByEmail(
@RequestBody JsonNode resetPasswordByEmailRequest,
@ApiParam(value = "The JSON object representing the reset password email request.")
@RequestBody ResetPasswordEmailRequest resetPasswordByEmailRequest,
HttpServletRequest request) throws ThingsboardException {
try {
String email = resetPasswordByEmailRequest.get("email").asText();
String email = resetPasswordByEmailRequest.getEmail();
UserCredentials userCredentials = userService.requestPasswordReset(TenantId.SYS_TENANT_ID, email);
User user = userService.findUserById(TenantId.SYS_TENANT_ID, userCredentials.getUserId());
String baseUrl = systemSecurityService.getBaseUrl(user.getTenantId(), user.getCustomerId(), request);
@ -176,8 +204,13 @@ public class AuthController extends BaseController {
}
}
@ApiOperation(value = "Check password reset token (checkResetToken)",
notes = "Checks the password reset token and forwards user to 'Reset Password' page. " +
"If token is valid, returns '303 See Other' (redirect) response code with the correct address of 'Reset Password' page and same 'resetToken' specified in the URL parameters. " +
"If token is not valid, returns '409 Conflict'.")
@RequestMapping(value = "/noauth/resetPassword", params = {"resetToken"}, method = RequestMethod.GET)
public ResponseEntity<String> checkResetToken(
@ApiParam(value = "The reset token string.")
@RequestParam(value = "resetToken") String resetToken) {
HttpHeaders headers = new HttpHeaders();
HttpStatus responseStatus;
@ -198,16 +231,24 @@ public class AuthController extends BaseController {
return new ResponseEntity<>(headers, responseStatus);
}
@ApiOperation(value = "Activate User",
notes = "Checks the activation token and updates corresponding user password in the database. " +
"Now the user may start using his password to login. " +
"The response already contains the [JWT](https://jwt.io) activation and refresh tokens, " +
"to simplify the user activation flow and avoid asking user to input password again after activation. " +
"If token is valid, returns the object that contains [JWT](https://jwt.io/) access and refresh tokens. " +
"If token is not valid, returns '404 Bad Request'.")
@RequestMapping(value = "/noauth/activate", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK)
@ResponseBody
public JsonNode activateUser(
@RequestBody JsonNode activateRequest,
public JwtTokenPair activateUser(
@ApiParam(value = "Activate user request.")
@RequestBody ActivateUserRequest activateRequest,
@RequestParam(required = false, defaultValue = "true") boolean sendActivationMail,
HttpServletRequest request) throws ThingsboardException {
try {
String activateToken = activateRequest.get("activateToken").asText();
String password = activateRequest.get("password").asText();
String activateToken = activateRequest.getActivateToken();
String password = activateRequest.getPassword();
systemSecurityService.validatePassword(TenantId.SYS_TENANT_ID, password, null);
String encodedPassword = passwordEncoder.encode(password);
UserCredentials credentials = userService.activateUserCredentials(TenantId.SYS_TENANT_ID, activateToken, encodedPassword);
@ -232,25 +273,26 @@ public class AuthController extends BaseController {
JwtToken accessToken = tokenFactory.createAccessJwtToken(securityUser);
JwtToken refreshToken = refreshTokenRepository.requestRefreshToken(securityUser);
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode tokenObject = objectMapper.createObjectNode();
tokenObject.put("token", accessToken.getToken());
tokenObject.put("refreshToken", refreshToken.getToken());
return tokenObject;
return new JwtTokenPair(accessToken.getToken(), refreshToken.getToken());
} catch (Exception e) {
throw handleException(e);
}
}
@ApiOperation(value = "Reset password (resetPassword)",
notes = "Checks the password reset token and updates the password. " +
"If token is valid, returns the object that contains [JWT](https://jwt.io/) access and refresh tokens. " +
"If token is not valid, returns '404 Bad Request'.")
@RequestMapping(value = "/noauth/resetPassword", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK)
@ResponseBody
public JsonNode resetPassword(
@RequestBody JsonNode resetPasswordRequest,
public JwtTokenPair resetPassword(
@ApiParam(value = "Reset password request.")
@RequestBody ResetPasswordRequest resetPasswordRequest,
HttpServletRequest request) throws ThingsboardException {
try {
String resetToken = resetPasswordRequest.get("resetToken").asText();
String password = resetPasswordRequest.get("password").asText();
String resetToken = resetPasswordRequest.getResetToken();
String password = resetPasswordRequest.getPassword();
UserCredentials userCredentials = userService.findUserCredentialsByResetToken(TenantId.SYS_TENANT_ID, resetToken);
if (userCredentials != null) {
systemSecurityService.validatePassword(TenantId.SYS_TENANT_ID, password, userCredentials);
@ -273,11 +315,7 @@ public class AuthController extends BaseController {
JwtToken accessToken = tokenFactory.createAccessJwtToken(securityUser);
JwtToken refreshToken = refreshTokenRepository.requestRefreshToken(securityUser);
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode tokenObject = objectMapper.createObjectNode();
tokenObject.put("token", accessToken.getToken());
tokenObject.put("refreshToken", refreshToken.getToken());
return tokenObject;
return new JwtTokenPair(accessToken.getToken(), refreshToken.getToken());
} else {
throw new ThingsboardException("Invalid reset token!", ThingsboardErrorCode.BAD_REQUEST_PARAMS);
}

42
application/src/main/java/org/thingsboard/server/controller/BaseController.java

@ -153,6 +153,46 @@ import static org.thingsboard.server.dao.service.Validator.validateId;
@TbCoreComponent
public abstract class BaseController {
/*Swagger UI description*/
public static final String CUSTOMER_ID = "customerId";
public static final String TENANT_ID = "tenantId";
public static final String PAGE_DATA_PARAMETERS = "You can specify parameters to filter the results. " +
"The result is wrapped with PageData object that allows you to iterate over result set using pagination. " +
"See the 'Model' tab of the Response Class for more details. ";
public static final String DASHBOARD_ID_PARAM_DESCRIPTION = "A string value representing the device id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
public static final String DEVICE_ID_PARAM_DESCRIPTION = "A string value representing the device id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
public static final String DEVICE_PROFILE_ID_DESCRIPTION = "A string value representing the device profile id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
public static final String TENANT_ID_PARAM_DESCRIPTION = "A string value representing the tenant id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
public static final String EDGE_ID_PARAM_DESCRIPTION = "A string value representing the edge id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
public static final String CUSTOMER_ID_PARAM_DESCRIPTION = "A string value representing the customer id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
public static final String ASSET_ID_PARAM_DESCRIPTION = "A string value representing the asset id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
protected final String PAGE_SIZE_DESCRIPTION = "Maximum amount of entities in a one page";
protected final String PAGE_NUMBER_DESCRIPTION = "Sequence number of page starting from 0";
protected final String DEVICE_TYPE_DESCRIPTION = "Device type as the name of the device profile";
protected final String ASSET_TYPE_DESCRIPTION = "Asset type";
protected final String ASSET_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the asset name.";
protected final String DASHBOARD_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the dashboard title.";
protected final String DEVICE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the device name.";
protected final String CUSTOMER_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the customer title.";
protected final String SORT_PROPERTY_DESCRIPTION = "Property of entity to sort by";
protected final String DASHBOARD_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, title";
protected final String CUSTOMER_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, title, email, country, city";
protected final String DEVICE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, deviceProfileName, label, customerTitle";
protected final String ASSET_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, type, label, customerTitle";
protected final String SORT_ORDER_DESCRIPTION = "Sort order. ASC (ASCENDING) or DESC (DESCENDING)";
protected final String SORT_ORDER_ALLOWABLE_VALUES = "ASC, DESC";
protected final String DEVICE_INFO_DESCRIPTION = "Device Info is an extension of the default Device object that contains information about the assigned customer name and device profile name. ";
protected final String ASSET_INFO_DESCRIPTION = "Asset Info is an extension of the default Asset object that contains information about the assigned customer name. ";
protected final String DEVICE_NAME_DESCRIPTION = "A string value representing the Device name.";
protected final String ASSET_NAME_DESCRIPTION = "A string value representing the Asset name.";
public static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
protected static final String DEFAULT_DASHBOARD = "defaultDashboardId";
protected static final String HOME_DASHBOARD = "homeDashboardId";
@ -897,7 +937,7 @@ public abstract class BaseController {
PageDataIterableByTenantIdEntityId<EdgeId> relatedEdgeIdsIterator =
new PageDataIterableByTenantIdEntityId<>(edgeService::findRelatedEdgeIdsByEntityId, tenantId, entityId, DEFAULT_PAGE_SIZE);
List<EdgeId> result = new ArrayList<>();
for(EdgeId edgeId : relatedEdgeIdsIterator) {
for (EdgeId edgeId : relatedEdgeIdsIterator) {
result.add(edgeId);
}
return result;

34
application/src/main/java/org/thingsboard/server/controller/ComponentDescriptorController.java

@ -15,6 +15,8 @@
*/
package org.thingsboard.server.controller;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
@ -38,10 +40,20 @@ import java.util.Set;
@RequestMapping("/api")
public class ComponentDescriptorController extends BaseController {
private static final String COMPONENT_DESCRIPTOR_DEFINITION = "Each Component Descriptor represents configuration of specific rule node (e.g. 'Save Timeseries' or 'Send Email'.). " +
"The Component Descriptors are used by the rule chain Web UI to build the configuration forms for the rule nodes. " +
"The Component Descriptors are discovered at runtime by scanning the class path and searching for @RuleNode annotation. " +
"Once discovered, the up to date list of descriptors is persisted to the database.";
@ApiOperation(value = "Get Component Descriptor (getComponentDescriptorByClazz)",
notes = "Gets the Component Descriptor object using class name from the path parameters. " +
COMPONENT_DESCRIPTOR_DEFINITION)
@PreAuthorize("hasAnyAuthority('SYS_ADMIN','TENANT_ADMIN')")
@RequestMapping(value = "/component/{componentDescriptorClazz:.+}", method = RequestMethod.GET)
@ResponseBody
public ComponentDescriptor getComponentDescriptorByClazz(@PathVariable("componentDescriptorClazz") String strComponentDescriptorClazz) throws ThingsboardException {
public ComponentDescriptor getComponentDescriptorByClazz(
@ApiParam(value = "Component Descriptor class name", required = true)
@PathVariable("componentDescriptorClazz") String strComponentDescriptorClazz) throws ThingsboardException {
checkParameter("strComponentDescriptorClazz", strComponentDescriptorClazz);
try {
return checkComponentDescriptorByClazz(strComponentDescriptorClazz);
@ -50,11 +62,17 @@ public class ComponentDescriptorController extends BaseController {
}
}
@ApiOperation(value = "Get Component Descriptors (getComponentDescriptorsByType)",
notes = "Gets the Component Descriptors using rule node type and optional rule chain type request parameters. " +
COMPONENT_DESCRIPTOR_DEFINITION)
@PreAuthorize("hasAnyAuthority('SYS_ADMIN','TENANT_ADMIN')")
@RequestMapping(value = "/components/{componentType}", method = RequestMethod.GET)
@ResponseBody
public List<ComponentDescriptor> getComponentDescriptorsByType(@PathVariable("componentType") String strComponentType,
@RequestParam(value = "ruleChainType", required = false) String strRuleChainType) throws ThingsboardException {
public List<ComponentDescriptor> getComponentDescriptorsByType(
@ApiParam(value = "Type of the Rule Node", allowableValues = "ENRICHMENT,FILTER,TRANSFORMATION,ACTION,EXTERNAL", required = true)
@PathVariable("componentType") String strComponentType,
@ApiParam(value = "Type of the Rule Chain", allowableValues = "CORE,EDGE")
@RequestParam(value = "ruleChainType", required = false) String strRuleChainType) throws ThingsboardException {
checkParameter("componentType", strComponentType);
try {
return checkComponentDescriptorsByType(ComponentType.valueOf(strComponentType), getRuleChainType(strRuleChainType));
@ -63,11 +81,17 @@ public class ComponentDescriptorController extends BaseController {
}
}
@ApiOperation(value = "Get Component Descriptors (getComponentDescriptorsByTypes)",
notes = "Gets the Component Descriptors using coma separated list of rule node types and optional rule chain type request parameters. " +
COMPONENT_DESCRIPTOR_DEFINITION)
@PreAuthorize("hasAnyAuthority('SYS_ADMIN','TENANT_ADMIN')")
@RequestMapping(value = "/components", params = {"componentTypes"}, method = RequestMethod.GET)
@ResponseBody
public List<ComponentDescriptor> getComponentDescriptorsByTypes(@RequestParam("componentTypes") String[] strComponentTypes,
@RequestParam(value = "ruleChainType", required = false) String strRuleChainType) throws ThingsboardException {
public List<ComponentDescriptor> getComponentDescriptorsByTypes(
@ApiParam(value = "List of types of the Rule Nodes, (ENRICHMENT, FILTER, TRANSFORMATION, ACTION or EXTERNAL)", required = true)
@RequestParam("componentTypes") String[] strComponentTypes,
@ApiParam(value = "Type of the Rule Chain", allowableValues = "CORE,EDGE")
@RequestParam(value = "ruleChainType", required = false) String strRuleChainType) throws ThingsboardException {
checkArrayParameter("componentTypes", strComponentTypes);
try {
Set<ComponentType> componentTypes = new HashSet<>();

60
application/src/main/java/org/thingsboard/server/controller/CustomerController.java

@ -18,6 +18,8 @@ package org.thingsboard.server.controller;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
@ -50,18 +52,23 @@ import java.util.List;
@RequestMapping("/api")
public class CustomerController extends BaseController {
public static final String CUSTOMER_ID = "customerId";
public static final String IS_PUBLIC = "isPublic";
public static final String CUSTOMER_SECURITY_CHECK = "If the user has the authority of 'Tenant Administrator', the server checks that the customer is owned by the same tenant. " +
"If the user has the authority of 'Customer User', the server checks that the user belongs to the customer.";
@ApiOperation(value = "Get Customer (getCustomerById)",
notes = "Get the Customer object based on the provided Customer Id. " + CUSTOMER_SECURITY_CHECK)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/customer/{customerId}", method = RequestMethod.GET)
@ResponseBody
public Customer getCustomerById(@PathVariable(CUSTOMER_ID) String strCustomerId) throws ThingsboardException {
public Customer getCustomerById(
@ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION)
@PathVariable(CUSTOMER_ID) String strCustomerId) throws ThingsboardException {
checkParameter(CUSTOMER_ID, strCustomerId);
try {
CustomerId customerId = new CustomerId(toUUID(strCustomerId));
Customer customer = checkCustomerId(customerId, Operation.READ);
if(!customer.getAdditionalInfo().isNull()) {
if (!customer.getAdditionalInfo().isNull()) {
processDashboardIdFromAdditionalInfo((ObjectNode) customer.getAdditionalInfo(), HOME_DASHBOARD);
}
return customer;
@ -70,10 +77,15 @@ public class CustomerController extends BaseController {
}
}
@ApiOperation(value = "Get short Customer info (getShortCustomerInfoById)",
notes = "Get the short customer object that contains only the title and 'isPublic' flag. " + CUSTOMER_SECURITY_CHECK)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/customer/{customerId}/shortInfo", method = RequestMethod.GET)
@ResponseBody
public JsonNode getShortCustomerInfoById(@PathVariable(CUSTOMER_ID) String strCustomerId) throws ThingsboardException {
public JsonNode getShortCustomerInfoById(
@ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION)
@PathVariable(CUSTOMER_ID) String strCustomerId) throws ThingsboardException {
checkParameter(CUSTOMER_ID, strCustomerId);
try {
CustomerId customerId = new CustomerId(toUUID(strCustomerId));
@ -88,10 +100,14 @@ public class CustomerController extends BaseController {
}
}
@ApiOperation(value = "Get Customer Title (getCustomerTitleById)",
notes = "Get the title of the customer. " + CUSTOMER_SECURITY_CHECK)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/customer/{customerId}/title", method = RequestMethod.GET, produces = "application/text")
@ResponseBody
public String getCustomerTitleById(@PathVariable(CUSTOMER_ID) String strCustomerId) throws ThingsboardException {
public String getCustomerTitleById(
@ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION)
@PathVariable(CUSTOMER_ID) String strCustomerId) throws ThingsboardException {
checkParameter(CUSTOMER_ID, strCustomerId);
try {
CustomerId customerId = new CustomerId(toUUID(strCustomerId));
@ -102,10 +118,15 @@ public class CustomerController extends BaseController {
}
}
@ApiOperation(value = "Create or update Customer (saveCustomer)",
notes = "Creates or Updates the Customer. When creating customer, platform generates Customer Id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address) " +
"The newly created Customer Id will be present in the response. " +
"Specify existing Customer Id to update the Customer. " +
"Referencing non-existing Customer Id will cause 'Not Found' error.")
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/customer", method = RequestMethod.POST)
@ResponseBody
public Customer saveCustomer(@RequestBody Customer customer) throws ThingsboardException {
public Customer saveCustomer(@ApiParam(value = "A JSON value representing the customer.") @RequestBody Customer customer) throws ThingsboardException {
try {
customer.setTenantId(getCurrentUser().getTenantId());
@ -131,10 +152,13 @@ public class CustomerController extends BaseController {
}
}
@ApiOperation(value = "Delete Customer (deleteCustomer)",
notes = "Deletes the Customer and all customer Users. All assigned Dashboards, Assets, Devices, etc. will be unassigned but not deleted. Referencing non-existing Customer Id will cause an error.")
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/customer/{customerId}", method = RequestMethod.DELETE)
@ResponseStatus(value = HttpStatus.OK)
public void deleteCustomer(@PathVariable(CUSTOMER_ID) String strCustomerId) throws ThingsboardException {
public void deleteCustomer(@ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION)
@PathVariable(CUSTOMER_ID) String strCustomerId) throws ThingsboardException {
checkParameter(CUSTOMER_ID, strCustomerId);
try {
CustomerId customerId = new CustomerId(toUUID(strCustomerId));
@ -161,14 +185,23 @@ public class CustomerController extends BaseController {
}
}
@ApiOperation(value = "Get Tenant Customers (getCustomers)",
notes = "Returns a page of customers owned by tenant. " +
PAGE_DATA_PARAMETERS)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/customers", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody
public PageData<Customer> getCustomers(@RequestParam int pageSize,
@RequestParam int page,
@RequestParam(required = false) String textSearch,
@RequestParam(required = false) String sortProperty,
@RequestParam(required = false) String sortOrder) throws ThingsboardException {
public PageData<Customer> getCustomers(
@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
@RequestParam int pageSize,
@ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
@RequestParam int page,
@ApiParam(value = CUSTOMER_TEXT_SEARCH_DESCRIPTION)
@RequestParam(required = false) String textSearch,
@ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = CUSTOMER_SORT_PROPERTY_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException {
try {
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
TenantId tenantId = getCurrentUser().getTenantId();
@ -178,10 +211,13 @@ public class CustomerController extends BaseController {
}
}
@ApiOperation(value = "Get Tenant Customer by Customer title (getTenantCustomer)",
notes = "Get the Customer using Customer Title. Available for users with 'Tenant Administrator' authority only.")
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/tenant/customers", params = {"customerTitle"}, method = RequestMethod.GET)
@ResponseBody
public Customer getTenantCustomer(
@ApiParam(value = "A string value representing the Customer title.")
@RequestParam String customerTitle) throws ThingsboardException {
try {
TenantId tenantId = getCurrentUser().getTenantId();

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

@ -17,8 +17,11 @@ package org.thingsboard.server.controller;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
@ -68,11 +71,16 @@ public class DashboardController extends BaseController {
private static final String HOME_DASHBOARD_ID = "homeDashboardId";
private static final String HOME_DASHBOARD_HIDE_TOOLBAR = "homeDashboardHideToolbar";
public static final String DASHBOARD_INFO_DEFINITION = "The Dashboard Info object contains lightweight information about the dashboard (e.g. title, image, assigned customers) but does not contain the heavyweight configuration JSON.";
public static final String DASHBOARD_DEFINITION = "The Dashboard object is a heavyweight object that contains information about the dashboard (e.g. title, image, assigned customers) and also configuration JSON (e.g. layouts, widgets, entity aliases).";
public static final String HIDDEN_FOR_MOBILE = "Exclude dashboards that are hidden for mobile";
@Value("${dashboard.max_datapoints_limit}")
private long maxDatapointsLimit;
@ApiOperation(value = "Get server time (getServerTime)",
notes = "Get the server time (milliseconds since January 1, 1970 UTC). " +
"Used to adjust view of the dashboards according to the difference between browser and server time.")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/dashboard/serverTime", method = RequestMethod.GET)
@ResponseBody
@ -80,6 +88,11 @@ public class DashboardController extends BaseController {
return System.currentTimeMillis();
}
@ApiOperation(value = "Get max data points limit (getMaxDatapointsLimit)",
notes = "Get the maximum number of data points that dashboard may request from the server per in a single subscription command. " +
"This value impacts the time window behavior. It impacts 'Max values' parameter in case user selects 'None' as 'Data aggregation function'. " +
"It also impacts the 'Grouping interval' in case of any other 'Data aggregation function' is selected. " +
"The actual value of the limit is configurable in the system configuration file.")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/dashboard/maxDatapointsLimit", method = RequestMethod.GET)
@ResponseBody
@ -87,10 +100,16 @@ public class DashboardController extends BaseController {
return maxDatapointsLimit;
}
@ApiOperation(value = "Get Dashboard Info (getDashboardInfoById)",
notes = "Get the information about the dashboard based on 'dashboardId' parameter. " + DASHBOARD_INFO_DEFINITION,
produces = MediaType.APPLICATION_JSON_VALUE
)
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/dashboard/info/{dashboardId}", method = RequestMethod.GET)
@ResponseBody
public DashboardInfo getDashboardInfoById(@PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException {
public DashboardInfo getDashboardInfoById(
@ApiParam(value = DASHBOARD_ID_PARAM_DESCRIPTION)
@PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException {
checkParameter(DASHBOARD_ID, strDashboardId);
try {
DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
@ -100,10 +119,16 @@ public class DashboardController extends BaseController {
}
}
@ApiOperation(value = "Get Dashboard (getDashboardById)",
notes = "Get the dashboard based on 'dashboardId' parameter. " + DASHBOARD_DEFINITION,
produces = MediaType.APPLICATION_JSON_VALUE
)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/dashboard/{dashboardId}", method = RequestMethod.GET)
@ResponseBody
public Dashboard getDashboardById(@PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException {
public Dashboard getDashboardById(
@ApiParam(value = DASHBOARD_ID_PARAM_DESCRIPTION)
@PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException {
checkParameter(DASHBOARD_ID, strDashboardId);
try {
DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
@ -113,10 +138,20 @@ public class DashboardController extends BaseController {
}
}
@ApiOperation(value = "Create Or Update Dashboard (saveDashboard)",
notes = "Create or update the Dashboard. When creating dashboard, platform generates Dashboard Id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address)." +
"The newly created Dashboard id will be present in the response. " +
"Specify existing Dashboard id to update the dashboard. " +
"Referencing non-existing dashboard Id will cause 'Not Found' error. " +
"Only users with 'TENANT_ADMIN') authority may create the dashboards.",
produces = MediaType.APPLICATION_JSON_VALUE,
consumes = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/dashboard", method = RequestMethod.POST)
@ResponseBody
public Dashboard saveDashboard(@RequestBody Dashboard dashboard) throws ThingsboardException {
public Dashboard saveDashboard(
@ApiParam(value = "A JSON value representing the dashboard.")
@RequestBody Dashboard dashboard) throws ThingsboardException {
try {
dashboard.setTenantId(getCurrentUser().getTenantId());
@ -141,10 +176,14 @@ public class DashboardController extends BaseController {
}
}
@ApiOperation(value = "Delete the Dashboard (deleteDashboard)",
notes = "Delete the Dashboard. Only users with 'TENANT_ADMIN') authority may delete the dashboards.")
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/dashboard/{dashboardId}", method = RequestMethod.DELETE)
@ResponseStatus(value = HttpStatus.OK)
public void deleteDashboard(@PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException {
public void deleteDashboard(
@ApiParam(value = DASHBOARD_ID_PARAM_DESCRIPTION)
@PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException {
checkParameter(DASHBOARD_ID, strDashboardId);
try {
DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
@ -170,12 +209,19 @@ public class DashboardController extends BaseController {
}
}
@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. " +
"Returns the Dashboard object. Only users with 'TENANT_ADMIN') authority may assign the dashboards to customers.",
produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/customer/{customerId}/dashboard/{dashboardId}", method = RequestMethod.POST)
@ResponseBody
public Dashboard assignDashboardToCustomer(@PathVariable("customerId") String strCustomerId,
@PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException {
checkParameter("customerId", strCustomerId);
public Dashboard assignDashboardToCustomer(
@ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION)
@PathVariable(CUSTOMER_ID) String strCustomerId,
@ApiParam(value = DASHBOARD_ID_PARAM_DESCRIPTION)
@PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException {
checkParameter(CUSTOMER_ID, strCustomerId);
checkParameter(DASHBOARD_ID, strDashboardId);
try {
CustomerId customerId = new CustomerId(toUUID(strCustomerId));
@ -203,11 +249,18 @@ public class DashboardController extends BaseController {
}
}
@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. " +
"Returns the Dashboard object. Only users with 'TENANT_ADMIN') authority may unassign the dashboards from customers.",
produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/customer/{customerId}/dashboard/{dashboardId}", method = RequestMethod.DELETE)
@ResponseBody
public Dashboard unassignDashboardFromCustomer(@PathVariable("customerId") String strCustomerId,
@PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException {
public Dashboard unassignDashboardFromCustomer(
@ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION)
@PathVariable(CUSTOMER_ID) String strCustomerId,
@ApiParam(value = DASHBOARD_ID_PARAM_DESCRIPTION)
@PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException {
checkParameter("customerId", strCustomerId);
checkParameter(DASHBOARD_ID, strDashboardId);
try {
@ -235,11 +288,20 @@ public class DashboardController extends BaseController {
}
}
@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. " +
"Returns the Dashboard object. Only users with 'TENANT_ADMIN') authority may assign the dashboards to customers.",
produces = MediaType.APPLICATION_JSON_VALUE,
consumes = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/dashboard/{dashboardId}/customers", method = RequestMethod.POST)
@ResponseBody
public Dashboard updateDashboardCustomers(@PathVariable(DASHBOARD_ID) String strDashboardId,
@RequestBody(required = false) String[] strCustomerIds) throws ThingsboardException {
public Dashboard updateDashboardCustomers(
@ApiParam(value = DASHBOARD_ID_PARAM_DESCRIPTION)
@PathVariable(DASHBOARD_ID) String strDashboardId,
@ApiParam(value = "JSON array with the list of customer ids, or empty to remove all customers")
@RequestBody(required = false) String[] strCustomerIds) throws ThingsboardException {
checkParameter(DASHBOARD_ID, strDashboardId);
try {
DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
@ -301,11 +363,19 @@ public class DashboardController extends BaseController {
}
}
@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. " +
"Returns the Dashboard object. Only users with 'TENANT_ADMIN') authority may assign the dashboards to customers.",
produces = MediaType.APPLICATION_JSON_VALUE,
consumes = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/dashboard/{dashboardId}/customers/add", method = RequestMethod.POST)
@ResponseBody
public Dashboard addDashboardCustomers(@PathVariable(DASHBOARD_ID) String strDashboardId,
@RequestBody String[] strCustomerIds) throws ThingsboardException {
public Dashboard addDashboardCustomers(
@ApiParam(value = DASHBOARD_ID_PARAM_DESCRIPTION)
@PathVariable(DASHBOARD_ID) String strDashboardId,
@ApiParam(value = "JSON array with the list of customer ids")
@RequestBody String[] strCustomerIds) throws ThingsboardException {
checkParameter(DASHBOARD_ID, strDashboardId);
try {
DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
@ -345,11 +415,19 @@ public class DashboardController extends BaseController {
}
}
@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. " +
"Returns the Dashboard object. Only users with 'TENANT_ADMIN') authority may assign the dashboards to customers.",
produces = MediaType.APPLICATION_JSON_VALUE,
consumes = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/dashboard/{dashboardId}/customers/remove", method = RequestMethod.POST)
@ResponseBody
public Dashboard removeDashboardCustomers(@PathVariable(DASHBOARD_ID) String strDashboardId,
@RequestBody String[] strCustomerIds) throws ThingsboardException {
public Dashboard removeDashboardCustomers(
@ApiParam(value = DASHBOARD_ID_PARAM_DESCRIPTION)
@PathVariable(DASHBOARD_ID) String strDashboardId,
@ApiParam(value = "JSON array with the list of customer ids")
@RequestBody String[] strCustomerIds) throws ThingsboardException {
checkParameter(DASHBOARD_ID, strDashboardId);
try {
DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
@ -389,10 +467,20 @@ public class DashboardController extends BaseController {
}
}
@ApiOperation(value = "Assign the Dashboard to Public Customer (assignDashboardToPublicCustomer)",
notes = "Assigns the dashboard to a special, auto-generated 'Public' Customer. Once assigned, unauthenticated users may browse the dashboard. " +
"This method is useful if you like to embed the dashboard on public web pages to be available for users that are not logged in. " +
"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 " +
"[assign Device to Public Customer](#!/device-controller/assignDeviceToPublicCustomerUsingPOST) for this purpose. " +
"Returns the Dashboard object. Only users with 'TENANT_ADMIN') authority may assign the dashboards to customers.",
produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/customer/public/dashboard/{dashboardId}", method = RequestMethod.POST)
@ResponseBody
public Dashboard assignDashboardToPublicCustomer(@PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException {
public Dashboard assignDashboardToPublicCustomer(
@ApiParam(value = DASHBOARD_ID_PARAM_DESCRIPTION)
@PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException {
checkParameter(DASHBOARD_ID, strDashboardId);
try {
DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
@ -415,10 +503,16 @@ public class DashboardController extends BaseController {
}
}
@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. " +
"Returns the Dashboard object. Only users with 'TENANT_ADMIN') authority may assign the dashboards to customers.",
produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/customer/public/dashboard/{dashboardId}", method = RequestMethod.DELETE)
@ResponseBody
public Dashboard unassignDashboardFromPublicCustomer(@PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException {
public Dashboard unassignDashboardFromPublicCustomer(
@ApiParam(value = DASHBOARD_ID_PARAM_DESCRIPTION)
@PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException {
checkParameter(DASHBOARD_ID, strDashboardId);
try {
DashboardId dashboardId = new DashboardId(toUUID(strDashboardId));
@ -442,15 +536,25 @@ public class DashboardController extends BaseController {
}
}
@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 +
"Only users with 'SYS_ADMIN' authority may use this method.",
produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAuthority('SYS_ADMIN')")
@RequestMapping(value = "/tenant/{tenantId}/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody
public PageData<DashboardInfo> getTenantDashboards(
@PathVariable("tenantId") String strTenantId,
@ApiParam(value = TENANT_ID_PARAM_DESCRIPTION, required = true)
@PathVariable(TENANT_ID) String strTenantId,
@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
@RequestParam int pageSize,
@ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
@RequestParam int page,
@ApiParam(value = DASHBOARD_TEXT_SEARCH_DESCRIPTION)
@RequestParam(required = false) String textSearch,
@ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = DASHBOARD_SORT_PROPERTY_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException {
try {
TenantId tenantId = new TenantId(toUUID(strTenantId));
@ -462,20 +566,30 @@ public class DashboardController extends BaseController {
}
}
@ApiOperation(value = "Get Tenant Dashboards (getTenantDashboards)",
notes = "Returns a page of dashboard info objects owned by the tenant of a current user. " + DASHBOARD_INFO_DEFINITION + " " + PAGE_DATA_PARAMETERS +
"Only users with 'TENANT_ADMIN' authority may use this method.",
produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/tenant/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody
public PageData<DashboardInfo> getTenantDashboards(
@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
@RequestParam int pageSize,
@ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
@RequestParam int page,
@ApiParam(value = HIDDEN_FOR_MOBILE)
@RequestParam(required = false) Boolean mobile,
@ApiParam(value = DASHBOARD_TEXT_SEARCH_DESCRIPTION)
@RequestParam(required = false) String textSearch,
@ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = DASHBOARD_SORT_PROPERTY_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException {
try {
TenantId tenantId = getCurrentUser().getTenantId();
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
if (mobile != null && mobile.booleanValue()) {
if (mobile != null && mobile) {
return checkNotNull(dashboardService.findMobileDashboardsByTenantId(tenantId, pageLink));
} else {
return checkNotNull(dashboardService.findDashboardsByTenantId(tenantId, pageLink));
@ -485,24 +599,35 @@ public class DashboardController extends BaseController {
}
}
@ApiOperation(value = "Get Customer Dashboards (getCustomerDashboards)",
notes = "Returns a page of dashboard info objects owned by the specified customer. " + DASHBOARD_INFO_DEFINITION + " " + PAGE_DATA_PARAMETERS +
"Only users with 'TENANT_ADMIN' or 'CUSTOMER_USER' authority may use this method.",
produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/customer/{customerId}/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody
public PageData<DashboardInfo> getCustomerDashboards(
@PathVariable("customerId") String strCustomerId,
@ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION, required = true)
@PathVariable(CUSTOMER_ID) String strCustomerId,
@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
@RequestParam int pageSize,
@ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
@RequestParam int page,
@ApiParam(value = HIDDEN_FOR_MOBILE)
@RequestParam(required = false) Boolean mobile,
@ApiParam(value = DASHBOARD_TEXT_SEARCH_DESCRIPTION)
@RequestParam(required = false) String textSearch,
@ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = DASHBOARD_SORT_PROPERTY_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException {
checkParameter("customerId", strCustomerId);
checkParameter(CUSTOMER_ID, strCustomerId);
try {
TenantId tenantId = getCurrentUser().getTenantId();
CustomerId customerId = new CustomerId(toUUID(strCustomerId));
checkCustomerId(customerId, Operation.READ);
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
if (mobile != null && mobile.booleanValue()) {
if (mobile != null && mobile) {
return checkNotNull(dashboardService.findMobileDashboardsByTenantIdAndCustomerId(tenantId, customerId, pageLink));
} else {
return checkNotNull(dashboardService.findDashboardsByTenantIdAndCustomerId(tenantId, customerId, pageLink));
@ -512,6 +637,13 @@ public class DashboardController extends BaseController {
}
}
@ApiOperation(value = "Get Home Dashboard (getHomeDashboard)",
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 and Customer levels then checks the same parameter for the Tenant that owns the user. "
+ DASHBOARD_DEFINITION + " " +
"Only users with 'TENANT_ADMIN' or 'CUSTOMER_USER' authority should use this method.",
produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("isAuthenticated()")
@RequestMapping(value = "/dashboard/home", method = RequestMethod.GET)
@ResponseBody
@ -543,6 +675,12 @@ public class DashboardController extends BaseController {
}
}
@ApiOperation(value = "Get Home Dashboard Info (getHomeDashboardInfo)",
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 and Customer levels then checks the same parameter for the Tenant that owns the user. " +
"Only users with 'TENANT_ADMIN' or 'CUSTOMER_USER' authority should use this method.",
produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("isAuthenticated()")
@RequestMapping(value = "/dashboard/home/info", method = RequestMethod.GET)
@ResponseBody
@ -574,6 +712,10 @@ public class DashboardController extends BaseController {
}
}
@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. " +
"Only users with 'TENANT_ADMIN' authority may use this method.",
produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/tenant/dashboard/home/info", method = RequestMethod.GET)
@ResponseBody
@ -596,10 +738,16 @@ public class DashboardController extends BaseController {
}
}
@ApiOperation(value = "Update Tenant Home Dashboard Info (getTenantHomeDashboardInfo)",
notes = "Update the home dashboard assignment for the current tenant. " +
"Only users with 'TENANT_ADMIN' authority may use this method.",
produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/tenant/dashboard/home/info", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK)
public void setTenantHomeDashboardInfo(@RequestBody HomeDashboardInfo homeDashboardInfo) throws ThingsboardException {
public void setTenantHomeDashboardInfo(
@ApiParam(value = "A JSON object that represents home dashboard id and other parameters", required = true)
@RequestBody HomeDashboardInfo homeDashboardInfo) throws ThingsboardException {
try {
if (homeDashboardInfo.getDashboardId() != null) {
checkDashboardId(homeDashboardInfo.getDashboardId(), Operation.READ);
@ -635,7 +783,8 @@ public class DashboardController extends BaseController {
}
return new HomeDashboardInfo(dashboardId, hideDashboardToolbar);
}
} catch (Exception e) {}
} catch (Exception e) {
}
return null;
}
@ -651,7 +800,8 @@ public class DashboardController extends BaseController {
}
return new HomeDashboard(dashboard, hideDashboardToolbar);
}
} catch (Exception e) {}
} catch (Exception e) {
}
return null;
}

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

@ -19,6 +19,8 @@ import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
@ -91,16 +93,22 @@ import static org.thingsboard.server.controller.EdgeController.EDGE_ID;
@RequiredArgsConstructor
@Slf4j
public class DeviceController extends BaseController {
private final DeviceBulkImportService deviceBulkImportService;
private static final String DEVICE_ID = "deviceId";
private static final String DEVICE_NAME = "deviceName";
private static final String TENANT_ID = "tenantId";
protected static final String DEVICE_ID = "deviceId";
protected static final String DEVICE_NAME = "deviceName";
protected static final String TENANT_ID = "tenantId";
private final DeviceBulkImportService deviceBulkImportService;
@ApiOperation(value = "Get Device (getDeviceById)",
notes = "Fetch the Device object based on the provided Device Id. " +
"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.")
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/device/{deviceId}", method = RequestMethod.GET)
@ResponseBody
public Device getDeviceById(@PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException {
public Device getDeviceById(@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION)
@PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException {
checkParameter(DEVICE_ID, strDeviceId);
try {
DeviceId deviceId = new DeviceId(toUUID(strDeviceId));
@ -110,10 +118,15 @@ public class DeviceController extends BaseController {
}
}
@ApiOperation(value = "Get Device Info (getDeviceInfoById)",
notes = "Fetch the Device Info object based on the provided Device Id. " +
"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. " + DEVICE_INFO_DESCRIPTION)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/device/info/{deviceId}", method = RequestMethod.GET)
@ResponseBody
public DeviceInfo getDeviceInfoById(@PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException {
public DeviceInfo getDeviceInfoById(@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION)
@PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException {
checkParameter(DEVICE_ID, strDeviceId);
try {
DeviceId deviceId = new DeviceId(toUUID(strDeviceId));
@ -123,11 +136,18 @@ public class DeviceController extends BaseController {
}
}
@ApiOperation(value = "Create Or Update Device (saveDevice)",
notes = "Create or update the Device. When creating device, platform generates Device Id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address). " +
"Device credentials are also generated if not provided in the 'accessToken' request parameter. " +
"The newly created device id will be present in the response. " +
"Specify existing Device id to update the device. " +
"Referencing non-existing device Id will cause 'Not Found' error.")
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/device", method = RequestMethod.POST)
@ResponseBody
public Device saveDevice(@RequestBody Device device,
@RequestParam(name = "accessToken", required = false) String accessToken) throws ThingsboardException {
public Device saveDevice(@ApiParam(value = "A JSON value representing the device.") @RequestBody Device device,
@ApiParam(value = "Optional value of the device credentials to be used during device creation. " +
"If omitted, access token will be auto-generated.") @RequestParam(name = "accessToken", required = false) String accessToken) throws ThingsboardException {
boolean created = device.getId() == null;
try {
device.setTenantId(getCurrentUser().getTenantId());
@ -164,10 +184,13 @@ public class DeviceController extends BaseController {
}
}
@ApiOperation(value = "Delete device (deleteDevice)",
notes = "Deletes the device, it's credentials and all the relations (from and to the device). Referencing non-existing device Id will cause an error.")
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/device/{deviceId}", method = RequestMethod.DELETE)
@ResponseStatus(value = HttpStatus.OK)
public void deleteDevice(@PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException {
public void deleteDevice(@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION)
@PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException {
checkParameter(DEVICE_ID, strDeviceId);
try {
DeviceId deviceId = new DeviceId(toUUID(strDeviceId));
@ -193,10 +216,14 @@ public class DeviceController extends BaseController {
}
}
@ApiOperation(value = "Assign device to customer (assignDeviceToCustomer)",
notes = "Creates assignment of the device to customer. Customer will be able to query device afterwards.")
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/customer/{customerId}/device/{deviceId}", method = RequestMethod.POST)
@ResponseBody
public Device assignDeviceToCustomer(@PathVariable("customerId") String strCustomerId,
public Device assignDeviceToCustomer(@ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION)
@PathVariable("customerId") String strCustomerId,
@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION)
@PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException {
checkParameter("customerId", strCustomerId);
checkParameter(DEVICE_ID, strDeviceId);
@ -225,10 +252,13 @@ public class DeviceController extends BaseController {
}
}
@ApiOperation(value = "Unassign device from customer (unassignDeviceFromCustomer)",
notes = "Clears assignment of the device to customer. Customer will not be able to query device afterwards.")
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/customer/device/{deviceId}", method = RequestMethod.DELETE)
@ResponseBody
public Device unassignDeviceFromCustomer(@PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException {
public Device unassignDeviceFromCustomer(@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION)
@PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException {
checkParameter(DEVICE_ID, strDeviceId);
try {
DeviceId deviceId = new DeviceId(toUUID(strDeviceId));
@ -256,10 +286,15 @@ public class DeviceController extends BaseController {
}
}
@ApiOperation(value = "Make device publicly available (assignDeviceToPublicCustomer)",
notes = "Device 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. " +
"However, users that are logged-in and belong to different tenant will not be able to access the device.")
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/customer/public/device/{deviceId}", method = RequestMethod.POST)
@ResponseBody
public Device assignDeviceToPublicCustomer(@PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException {
public Device assignDeviceToPublicCustomer(@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION)
@PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException {
checkParameter(DEVICE_ID, strDeviceId);
try {
DeviceId deviceId = new DeviceId(toUUID(strDeviceId));
@ -280,10 +315,13 @@ public class DeviceController extends BaseController {
}
}
@ApiOperation(value = "Get Device Credentials (getDeviceCredentialsByDeviceId)",
notes = "If during device creation there wasn't specified any credentials, platform generates random 'ACCESS_TOKEN' credentials.")
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/device/{deviceId}/credentials", method = RequestMethod.GET)
@ResponseBody
public DeviceCredentials getDeviceCredentialsByDeviceId(@PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException {
public DeviceCredentials getDeviceCredentialsByDeviceId(@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION)
@PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException {
checkParameter(DEVICE_ID, strDeviceId);
try {
DeviceId deviceId = new DeviceId(toUUID(strDeviceId));
@ -301,10 +339,16 @@ public class DeviceController extends BaseController {
}
}
@ApiOperation(value = "Update device credentials (updateDeviceCredentials)", notes = "During device creation, platform generates random 'ACCESS_TOKEN' credentials. " +
"Use this method to update the device credentials. First use 'getDeviceCredentialsByDeviceId' to get the credentials id and value. " +
"Then use current method to update the credentials type and value. It is not possible to create multiple device credentials for the same device. " +
"The structure of device credentials id and value is simple for the 'ACCESS_TOKEN' but is much more complex for the 'MQTT_BASIC' or 'LWM2M_CREDENTIALS'.")
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/device/credentials", method = RequestMethod.POST)
@ResponseBody
public DeviceCredentials saveDeviceCredentials(@RequestBody DeviceCredentials deviceCredentials) throws ThingsboardException {
public DeviceCredentials updateDeviceCredentials(
@ApiParam(value = "A JSON value representing the device credentials.")
@RequestBody DeviceCredentials deviceCredentials) throws ThingsboardException {
checkNotNull(deviceCredentials);
try {
Device device = checkDeviceId(deviceCredentials.getDeviceId(), Operation.WRITE_CREDENTIALS);
@ -325,15 +369,24 @@ public class DeviceController extends BaseController {
}
}
@ApiOperation(value = "Get Tenant Devices (getTenantDevices)",
notes = "Returns a page of devices owned by tenant. " +
PAGE_DATA_PARAMETERS)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/tenant/devices", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody
public PageData<Device> getTenantDevices(
@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
@RequestParam int pageSize,
@ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
@RequestParam int page,
@ApiParam(value = DEVICE_TYPE_DESCRIPTION)
@RequestParam(required = false) String type,
@ApiParam(value = DEVICE_TEXT_SEARCH_DESCRIPTION)
@RequestParam(required = false) String textSearch,
@ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = DEVICE_SORT_PROPERTY_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException {
try {
TenantId tenantId = getCurrentUser().getTenantId();
@ -348,17 +401,28 @@ public class DeviceController extends BaseController {
}
}
@ApiOperation(value = "Get Tenant Device Infos (getTenantDeviceInfos)",
notes = "Returns a page of devices info objects owned by tenant. " +
PAGE_DATA_PARAMETERS + DEVICE_INFO_DESCRIPTION)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/tenant/deviceInfos", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody
public PageData<DeviceInfo> getTenantDeviceInfos(
@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
@RequestParam int pageSize,
@ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
@RequestParam int page,
@ApiParam(value = DEVICE_TYPE_DESCRIPTION)
@RequestParam(required = false) String type,
@ApiParam(value = DEVICE_PROFILE_ID_DESCRIPTION)
@RequestParam(required = false) String deviceProfileId,
@ApiParam(value = DEVICE_TEXT_SEARCH_DESCRIPTION)
@RequestParam(required = false) String textSearch,
@ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = DEVICE_SORT_PROPERTY_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortProperty,
@RequestParam(required = false) String sortOrder) throws ThingsboardException {
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder
) throws ThingsboardException {
try {
TenantId tenantId = getCurrentUser().getTenantId();
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
@ -375,10 +439,14 @@ public class DeviceController extends BaseController {
}
}
@ApiOperation(value = "Get Tenant Device (getTenantDevice)",
notes = "Requested device must be owned by tenant that the user belongs to. " +
"Device name is an unique property of device. So it can be used to identify the device.")
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/tenant/devices", params = {"deviceName"}, method = RequestMethod.GET)
@ResponseBody
public Device getTenantDevice(
@ApiParam(value = DEVICE_NAME_DESCRIPTION)
@RequestParam String deviceName) throws ThingsboardException {
try {
TenantId tenantId = getCurrentUser().getTenantId();
@ -388,16 +456,26 @@ public class DeviceController extends BaseController {
}
}
@ApiOperation(value = "Get Customer Devices (getCustomerDevices)",
notes = "Returns a page of devices objects assigned to customer. " +
PAGE_DATA_PARAMETERS)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/customer/{customerId}/devices", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody
public PageData<Device> getCustomerDevices(
@ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION, required = true)
@PathVariable("customerId") String strCustomerId,
@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
@RequestParam int pageSize,
@ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
@RequestParam int page,
@ApiParam(value = DEVICE_TYPE_DESCRIPTION)
@RequestParam(required = false) String type,
@ApiParam(value = DEVICE_TEXT_SEARCH_DESCRIPTION)
@RequestParam(required = false) String textSearch,
@ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = DEVICE_SORT_PROPERTY_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException {
checkParameter("customerId", strCustomerId);
try {
@ -415,17 +493,28 @@ public class DeviceController extends BaseController {
}
}
@ApiOperation(value = "Get Customer Device Infos (getCustomerDeviceInfos)",
notes = "Returns a page of devices info objects assigned to customer. " +
PAGE_DATA_PARAMETERS + DEVICE_INFO_DESCRIPTION)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/customer/{customerId}/deviceInfos", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody
public PageData<DeviceInfo> getCustomerDeviceInfos(
@ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION, required = true)
@PathVariable("customerId") String strCustomerId,
@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
@RequestParam int pageSize,
@ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
@RequestParam int page,
@ApiParam(value = DEVICE_TYPE_DESCRIPTION)
@RequestParam(required = false) String type,
@ApiParam(value = DEVICE_PROFILE_ID_DESCRIPTION)
@RequestParam(required = false) String deviceProfileId,
@ApiParam(value = DEVICE_TEXT_SEARCH_DESCRIPTION)
@RequestParam(required = false) String textSearch,
@ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = DEVICE_SORT_PROPERTY_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException {
checkParameter("customerId", strCustomerId);
try {
@ -446,10 +535,13 @@ public class DeviceController extends BaseController {
}
}
@ApiOperation(value = "Get Devices By Ids (getDevicesByIds)",
notes = "Requested devices must be owned by tenant or assigned to customer which user is performing the request. ")
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/devices", params = {"deviceIds"}, method = RequestMethod.GET)
@ResponseBody
public List<Device> getDevicesByIds(
@ApiParam(value = "A list of devices ids, separated by comma ','")
@RequestParam("deviceIds") String[] strDeviceIds) throws ThingsboardException {
checkArrayParameter("deviceIds", strDeviceIds);
try {
@ -472,6 +564,10 @@ public class DeviceController extends BaseController {
}
}
@ApiOperation(value = "Find related devices (findByQuery)",
notes = "Returns all devices that are related to the specific entity. " +
"The entity id, relation type, device types, depth of the search, and other query parameters defined using complex 'DeviceSearchQuery' object. " +
"See 'Model' tab of the Parameters for more info.")
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/devices", method = RequestMethod.POST)
@ResponseBody
@ -496,6 +592,8 @@ public class DeviceController extends BaseController {
}
}
@ApiOperation(value = "Get Device Types (getDeviceTypes)",
notes = "Returns a set of unique device profile names based on devices that are either owned by the tenant or assigned to the customer which user is performing the request.")
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/device/types", method = RequestMethod.GET)
@ResponseBody
@ -510,10 +608,19 @@ public class DeviceController extends BaseController {
}
}
@ApiOperation(value = "Claim device (claimDevice)",
notes = "Claiming makes it possible to assign a device to the specific customer using device/server side claiming data (in the form of secret key)." +
"To make this happen you have to provide unique device name and optional claiming data (it is needed only for device-side claiming)." +
"Once device is claimed, the customer becomes its owner and customer users may access device data as well as control the device. \n" +
"In order to enable claiming devices feature a system parameter security.claim.allowClaimingByDefault should be set to true, " +
"otherwise a server-side claimingAllowed attribute with the value true is obligatory for provisioned devices. \n" +
"See official documentation for more details regarding claiming.")
@PreAuthorize("hasAuthority('CUSTOMER_USER')")
@RequestMapping(value = "/customer/device/{deviceName}/claim", method = RequestMethod.POST)
@ResponseBody
public DeferredResult<ResponseEntity> claimDevice(@PathVariable(DEVICE_NAME) String deviceName,
public DeferredResult<ResponseEntity> claimDevice(@ApiParam(value = "Unique name of the device which is going to be claimed")
@PathVariable(DEVICE_NAME) String deviceName,
@ApiParam(value = "Claiming request which can optionally contain secret key")
@RequestBody(required = false) ClaimRequest claimRequest) throws ThingsboardException {
checkParameter(DEVICE_NAME, deviceName);
try {
@ -564,10 +671,13 @@ public class DeviceController extends BaseController {
}
}
@ApiOperation(value = "Reclaim device (reClaimDevice)",
notes = "Reclaiming means the device will be unassigned from the customer and the device will be available for claiming again.")
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/customer/device/{deviceName}/claim", method = RequestMethod.DELETE)
@ResponseStatus(value = HttpStatus.OK)
public DeferredResult<ResponseEntity> reClaimDevice(@PathVariable(DEVICE_NAME) String deviceName) throws ThingsboardException {
public DeferredResult<ResponseEntity> reClaimDevice(@ApiParam(value = "Unique name of the device which is going to be reclaimed")
@PathVariable(DEVICE_NAME) String deviceName) throws ThingsboardException {
checkParameter(DEVICE_NAME, deviceName);
try {
final DeferredResult<ResponseEntity> deferredResult = new DeferredResult<>();
@ -615,10 +725,14 @@ public class DeviceController extends BaseController {
return DataConstants.DEFAULT_SECRET_KEY;
}
@ApiOperation(value = "Assign device to tenant (assignDeviceToTenant)",
notes = "Creates assignment of the device to tenant. Thereafter tenant will be able to reassign the device to a customer.")
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/tenant/{tenantId}/device/{deviceId}", method = RequestMethod.POST)
@ResponseBody
public Device assignDeviceToTenant(@PathVariable(TENANT_ID) String strTenantId,
public Device assignDeviceToTenant(@ApiParam(value = TENANT_ID_PARAM_DESCRIPTION)
@PathVariable(TENANT_ID) String strTenantId,
@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION)
@PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException {
checkParameter(TENANT_ID, strTenantId);
checkParameter(DEVICE_ID, strDeviceId);
@ -665,10 +779,16 @@ public class DeviceController extends BaseController {
return metaData;
}
@ApiOperation(value = "Assign device to edge (assignDeviceToEdge)",
notes = "Creates assignment of an existing device to an instance of The Edge. " +
"The Edge is a software product for edge computing. " +
"It allows bringing data analysis and management to the edge, while seamlessly synchronizing with the platform server (cloud). ")
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/edge/{edgeId}/device/{deviceId}", method = RequestMethod.POST)
@ResponseBody
public Device assignDeviceToEdge(@PathVariable(EDGE_ID) String strEdgeId,
public Device assignDeviceToEdge(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION)
@PathVariable(EDGE_ID) String strEdgeId,
@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION)
@PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException {
checkParameter(EDGE_ID, strEdgeId);
checkParameter(DEVICE_ID, strDeviceId);
@ -699,10 +819,14 @@ public class DeviceController extends BaseController {
}
}
@ApiOperation(value = "Unassign device from edge (unassignDeviceFromEdge)",
notes = "Clears assignment of the device to the edge")
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/edge/{edgeId}/device/{deviceId}", method = RequestMethod.DELETE)
@ResponseBody
public Device unassignDeviceFromEdge(@PathVariable(EDGE_ID) String strEdgeId,
public Device unassignDeviceFromEdge(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION)
@PathVariable(EDGE_ID) String strEdgeId,
@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION)
@PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException {
checkParameter(EDGE_ID, strEdgeId);
checkParameter(DEVICE_ID, strDeviceId);
@ -733,18 +857,30 @@ public class DeviceController extends BaseController {
}
}
@ApiOperation(value = "Get devices assigned to edge (getEdgeDevices)",
notes = "Returns a page of devices assigned to edge. " +
PAGE_DATA_PARAMETERS)
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/edge/{edgeId}/devices", params = {"pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody
public PageData<Device> getEdgeDevices(
@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true)
@PathVariable(EDGE_ID) String strEdgeId,
@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
@RequestParam int pageSize,
@ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
@RequestParam int page,
@ApiParam(value = DEVICE_TYPE_DESCRIPTION)
@RequestParam(required = false) String type,
@ApiParam(value = DEVICE_TEXT_SEARCH_DESCRIPTION)
@RequestParam(required = false) String textSearch,
@ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = DEVICE_SORT_PROPERTY_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder,
@ApiParam(value = "Timestamp. Devices with creation time before it won't be queried")
@RequestParam(required = false) Long startTime,
@ApiParam(value = "Timestamp. Devices with creation time after it won't be queried")
@RequestParam(required = false) Long endTime) throws ThingsboardException {
checkParameter(EDGE_ID, strEdgeId);
try {
@ -776,10 +912,17 @@ public class DeviceController extends BaseController {
}
}
@ApiOperation(value = "Count devices by device profile (countByDeviceProfileAndEmptyOtaPackage)",
notes = "The platform gives an ability to load OTA (over-the-air) packages to devices. " +
"It can be done in two different ways: device scope or device profile scope." +
"In the response you will find the number of devices with specified device profile, but without previously defined device scope OTA package. " +
"It can be useful when you want to define number of devices that will be affected with future OTA package")
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/devices/count/{otaPackageType}/{deviceProfileId}", method = RequestMethod.GET)
@ResponseBody
public Long countByDeviceProfileAndEmptyOtaPackage(@PathVariable("otaPackageType") String otaPackageType,
public Long countByDeviceProfileAndEmptyOtaPackage(@ApiParam(value = "OTA package type", allowableValues = "FIRMWARE, SOFTWARE")
@PathVariable("otaPackageType") String otaPackageType,
@ApiParam(value = "Device Profile Id. I.g. '784f394c-42b6-435a-983c-b7beff2784f9'")
@PathVariable("deviceProfileId") String deviceProfileId) throws ThingsboardException {
checkParameter("OtaPackageType", otaPackageType);
checkParameter("DeviceProfileId", deviceProfileId);
@ -793,6 +936,8 @@ public class DeviceController extends BaseController {
}
}
@ApiOperation(value = "Import the bulk of devices (processDevicesBulkImport)",
notes = "There's an ability to import the bulk of devices using the only .csv file.")
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@PostMapping("/device/bulk_import")
public BulkImportResult<Device> processDevicesBulkImport(@RequestBody BulkImportRequest request) throws Exception {

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

@ -38,7 +38,6 @@ import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.EntityView;
import org.thingsboard.server.common.data.EntityViewInfo;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
@ -49,7 +48,6 @@ import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.EntityViewId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UUIDBased;
import org.thingsboard.server.common.data.kv.AttributeKvEntry;
import org.thingsboard.server.common.data.kv.BaseReadTsKvQuery;
import org.thingsboard.server.common.data.kv.ReadTsKvQuery;
@ -74,7 +72,6 @@ import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.thingsboard.server.controller.CustomerController.CUSTOMER_ID;
import static org.thingsboard.server.controller.EdgeController.EDGE_ID;
/**

4
application/src/main/java/org/thingsboard/server/controller/TenantController.java

@ -57,7 +57,7 @@ public class TenantController extends BaseController {
@RequestMapping(value = "/tenant/{tenantId}", method = RequestMethod.GET)
@ResponseBody
public Tenant getTenantById(@PathVariable("tenantId") String strTenantId) throws ThingsboardException {
checkParameter("tenantId", strTenantId);
checkParameter(TENANT_ID, strTenantId);
try {
TenantId tenantId = new TenantId(toUUID(strTenantId));
Tenant tenant = checkTenantId(tenantId, Operation.READ);
@ -74,7 +74,7 @@ public class TenantController extends BaseController {
@RequestMapping(value = "/tenant/info/{tenantId}", method = RequestMethod.GET)
@ResponseBody
public TenantInfo getTenantInfoById(@PathVariable("tenantId") String strTenantId) throws ThingsboardException {
checkParameter("tenantId", strTenantId);
checkParameter(TENANT_ID, strTenantId);
try {
TenantId tenantId = new TenantId(toUUID(strTenantId));
return checkTenantInfoId(tenantId, Operation.READ);

30
application/src/main/java/org/thingsboard/server/service/security/model/ActivateUserRequest.java

@ -0,0 +1,30 @@
/**
* Copyright © 2016-2021 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.service.security.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel
@Data
public class ActivateUserRequest {
@ApiModelProperty(position = 1, value = "The activate token to verify", example = "AAB254FF67D..")
private String activateToken;
@ApiModelProperty(position = 2, value = "The new password to set", example = "secret")
private String password;
}

31
application/src/main/java/org/thingsboard/server/service/security/model/ChangePasswordRequest.java

@ -0,0 +1,31 @@
/**
* Copyright © 2016-2021 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.service.security.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel
@Data
public class ChangePasswordRequest {
@ApiModelProperty(position = 1, value = "The old password", example = "OldPassword")
private String currentPassword;
@ApiModelProperty(position = 1, value = "The new password", example = "NewPassword")
private String newPassword;
}

32
application/src/main/java/org/thingsboard/server/service/security/model/JwtTokenPair.java

@ -0,0 +1,32 @@
/**
* Copyright © 2016-2021 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.service.security.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
@ApiModel(value = "JWT Token Pair")
@Data
@AllArgsConstructor
public class JwtTokenPair {
@ApiModelProperty(position = 1, value = "The JWT Access Token. Used to perform API calls.", example = "AAB254FF67D..")
private String token;
@ApiModelProperty(position = 1, value = "The JWT Refresh Token. Used to get new JWT Access Token if old one has expired.", example = "AAB254FF67D..")
private String refreshToken;
}

29
application/src/main/java/org/thingsboard/server/service/security/model/ResetPasswordEmailRequest.java

@ -0,0 +1,29 @@
/**
* Copyright © 2016-2021 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.service.security.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel
@Data
public class ResetPasswordEmailRequest {
@ApiModelProperty(position = 1, value = "The email of the user", example = "user@example.com")
private String email;
}

30
application/src/main/java/org/thingsboard/server/service/security/model/ResetPasswordRequest.java

@ -0,0 +1,30 @@
/**
* Copyright © 2016-2021 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.service.security.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel
@Data
public class ResetPasswordRequest {
@ApiModelProperty(position = 1, value = "The reset token to verify", example = "AAB254FF67D..")
private String resetToken;
@ApiModelProperty(position = 2, value = "The new password to set", example = "secret")
private String password;
}

4
common/data/pom.xml

@ -96,6 +96,10 @@
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
</dependency>
</dependencies>
<build>

18
common/data/src/main/java/org/thingsboard/server/common/data/AdminSettings.java

@ -15,11 +15,15 @@
*/
package org.thingsboard.server.common.data;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.thingsboard.server.common.data.id.AdminSettingsId;
import com.fasterxml.jackson.databind.JsonNode;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.validation.NoXss;
@ApiModel
public class AdminSettings extends BaseData<AdminSettingsId> {
private static final long serialVersionUID = -7670322981725511892L;
@ -42,6 +46,19 @@ public class AdminSettings extends BaseData<AdminSettingsId> {
this.jsonValue = adminSettings.getJsonValue();
}
@ApiModelProperty(position = 1, value = "The Id of the Administration Settings, auto-generated, UUID")
@Override
public AdminSettingsId getId() {
return super.getId();
}
@ApiModelProperty(position = 2, value = "Timestamp of the settings creation, in milliseconds", example = "1609459200000", readOnly = true)
@Override
public long getCreatedTime() {
return super.getCreatedTime();
}
@ApiModelProperty(position = 3, value = "The Administration Settings key, (e.g. 'general' or 'mail')")
public String getKey() {
return key;
}
@ -50,6 +67,7 @@ public class AdminSettings extends BaseData<AdminSettingsId> {
this.key = key;
}
@ApiModelProperty(position = 4, value = "JSON representation of the Administration Settings value")
public JsonNode getJsonValue() {
return jsonValue;
}

5
common/data/src/main/java/org/thingsboard/server/common/data/Dashboard.java

@ -16,6 +16,7 @@
package org.thingsboard.server.common.data;
import com.fasterxml.jackson.databind.JsonNode;
import io.swagger.annotations.ApiModelProperty;
import org.thingsboard.server.common.data.id.DashboardId;
public class Dashboard extends DashboardInfo {
@ -41,6 +42,10 @@ public class Dashboard extends DashboardInfo {
this.configuration = dashboard.getConfiguration();
}
@ApiModelProperty(position = 9, value = "JSON object with main configuration of the dashboard: layouts, widgets, aliases, etc. " +
"The JSON structure of the dashboard configuration is quite complex. " +
"The easiest way to learn it is to export existing dashboard to JSON."
, dataType = "com.fasterxml.jackson.databind.JsonNode")
public JsonNode getConfiguration() {
return configuration;
}

25
common/data/src/main/java/org/thingsboard/server/common/data/DashboardInfo.java

@ -16,6 +16,8 @@
package org.thingsboard.server.common.data;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DashboardId;
import org.thingsboard.server.common.data.id.TenantId;
@ -25,6 +27,7 @@ import javax.validation.Valid;
import java.util.HashSet;
import java.util.Set;
@ApiModel
public class DashboardInfo extends SearchTextBased<DashboardId> implements HasName, HasTenantId {
private TenantId tenantId;
@ -54,6 +57,22 @@ public class DashboardInfo extends SearchTextBased<DashboardId> implements HasNa
this.mobileOrder = dashboardInfo.getMobileOrder();
}
@ApiModelProperty(position = 1, value = "JSON object with the dashboard Id. " +
"Specify existing dashboard Id to update the dashboard. " +
"Referencing non-existing dashboard id will cause error. " +
"Omit this field to create new dashboard." )
@Override
public DashboardId getId() {
return super.getId();
}
@ApiModelProperty(position = 2, value = "Timestamp of the dashboard creation, in milliseconds", example = "1609459200000", readOnly = true)
@Override
public long getCreatedTime() {
return super.getCreatedTime();
}
@ApiModelProperty(position = 3, value = "JSON object with Tenant Id. Tenant Id of the dashboard can't be changed.", readOnly = true)
public TenantId getTenantId() {
return tenantId;
}
@ -62,6 +81,7 @@ public class DashboardInfo extends SearchTextBased<DashboardId> implements HasNa
this.tenantId = tenantId;
}
@ApiModelProperty(position = 4, value = "Title of the dashboard.")
public String getTitle() {
return title;
}
@ -70,6 +90,7 @@ public class DashboardInfo extends SearchTextBased<DashboardId> implements HasNa
this.title = title;
}
@ApiModelProperty(position = 8, value = "Thumbnail picture for rendering of the dashboards in a grid view on mobile devices.", readOnly = true)
public String getImage() {
return image;
}
@ -78,6 +99,7 @@ public class DashboardInfo extends SearchTextBased<DashboardId> implements HasNa
this.image = image;
}
@ApiModelProperty(position = 5, value = "List of assigned customers with their info.", readOnly = true)
public Set<ShortCustomerInfo> getAssignedCustomers() {
return assignedCustomers;
}
@ -86,6 +108,7 @@ public class DashboardInfo extends SearchTextBased<DashboardId> implements HasNa
this.assignedCustomers = assignedCustomers;
}
@ApiModelProperty(position = 6, value = "Hide dashboard from mobile devices. Useful if the dashboard is not designed for small screens.", readOnly = true)
public boolean isMobileHide() {
return mobileHide;
}
@ -94,6 +117,7 @@ public class DashboardInfo extends SearchTextBased<DashboardId> implements HasNa
this.mobileHide = mobileHide;
}
@ApiModelProperty(position = 7, value = "Order on mobile devices. Useful to adjust sorting of the dashboards for mobile applications", readOnly = true)
public Integer getMobileOrder() {
return mobileOrder;
}
@ -152,6 +176,7 @@ public class DashboardInfo extends SearchTextBased<DashboardId> implements HasNa
}
}
@ApiModelProperty(position = 4, value = "Same as title of the dashboard. Read-only field. Update the 'title' to change the 'name' of the dashboard.", readOnly = true)
@Override
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
public String getName() {

34
common/data/src/main/java/org/thingsboard/server/common/data/Device.java

@ -17,6 +17,9 @@ package org.thingsboard.server.common.data;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.thingsboard.server.common.data.device.data.DeviceData;
@ -31,6 +34,7 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Optional;
@ApiModel
@EqualsAndHashCode(callSuper = true)
@Slf4j
public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implements HasName, HasTenantId, HasCustomerId, HasOtaPackage {
@ -88,6 +92,22 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen
return this;
}
@ApiModelProperty(position = 1, value = "JSON object with the device Id. " +
"Specify this field to update the device. " +
"Referencing non-existing device Id will cause error. " +
"Omit this field to create new device." )
@Override
public DeviceId getId() {
return super.getId();
}
@ApiModelProperty(position = 2, value = "Timestamp of the device creation, in milliseconds", example = "1609459200000", readOnly = true)
@Override
public long getCreatedTime() {
return super.getCreatedTime();
}
@ApiModelProperty(position = 3, value = "JSON object with Tenant Id. Use 'assignDeviceToTenant' to change the Tenant Id.", readOnly = true)
public TenantId getTenantId() {
return tenantId;
}
@ -96,6 +116,7 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen
this.tenantId = tenantId;
}
@ApiModelProperty(position = 4, value = "JSON object with Customer Id. Use 'assignDeviceToCustomer' to change the Customer Id.", readOnly = true)
public CustomerId getCustomerId() {
return customerId;
}
@ -104,6 +125,7 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen
this.customerId = customerId;
}
@ApiModelProperty(position = 5, required = true, value = "Unique Device Name in scope of Tenant", example = "A4B72CCDFF33")
@Override
public String getName() {
return name;
@ -113,6 +135,7 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen
this.name = name;
}
@ApiModelProperty(position = 6, required = true, value = "Device Profile Name", example = "Temperature Sensor")
public String getType() {
return type;
}
@ -121,6 +144,7 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen
this.type = type;
}
@ApiModelProperty(position = 7, required = true, value = "Label that may be used in widgets", example = "Room 234 Sensor")
public String getLabel() {
return label;
}
@ -129,6 +153,7 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen
this.label = label;
}
@ApiModelProperty(position = 8, required = true, value = "JSON object with Device Profile Id.")
public DeviceProfileId getDeviceProfileId() {
return deviceProfileId;
}
@ -137,6 +162,7 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen
this.deviceProfileId = deviceProfileId;
}
@ApiModelProperty(position = 9, value = "JSON object with content specific to type of transport in the device profile.")
public DeviceData getDeviceData() {
if (deviceData != null) {
return deviceData;
@ -169,6 +195,7 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen
return getName();
}
@ApiModelProperty(position = 10, value = "JSON object with Ota Package Id.")
public OtaPackageId getFirmwareId() {
return firmwareId;
}
@ -177,6 +204,7 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen
this.firmwareId = firmwareId;
}
@ApiModelProperty(position = 11, value = "JSON object with Ota Package Id.")
public OtaPackageId getSoftwareId() {
return softwareId;
}
@ -185,6 +213,12 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen
this.softwareId = softwareId;
}
@ApiModelProperty(position = 12, value = "Additional parameters of the device", dataType = "com.fasterxml.jackson.databind.JsonNode")
@Override
public JsonNode getAdditionalInfo() {
return super.getAdditionalInfo();
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();

6
common/data/src/main/java/org/thingsboard/server/common/data/DeviceInfo.java

@ -15,14 +15,20 @@
*/
package org.thingsboard.server.common.data;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.thingsboard.server.common.data.id.DeviceId;
@ApiModel
@Data
public class DeviceInfo extends Device {
@ApiModelProperty(position = 13, value = "Title of the Customer that owns the device.", readOnly = true)
private String customerTitle;
@ApiModelProperty(position = 14, value = "Indicates special 'Public' Customer that is auto-generated to use the devices on public dashboards.", readOnly = true)
private boolean customerIsPublic;
@ApiModelProperty(position = 15, value = "Name of the corresponding Device Profile.", readOnly = true)
private String deviceProfileName;
public DeviceInfo() {

6
common/data/src/main/java/org/thingsboard/server/common/data/HomeDashboard.java

@ -15,11 +15,17 @@
*/
package org.thingsboard.server.common.data;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel
@Data
public class HomeDashboard extends Dashboard {
public static final String HIDE_DASHBOARD_TOOLBAR_DESCRIPTION = "Hide dashboard toolbar flag. Useful for rendering dashboards on mobile.";
@ApiModelProperty(position = 10, value = HIDE_DASHBOARD_TOOLBAR_DESCRIPTION)
private boolean hideDashboardToolbar;
public HomeDashboard(Dashboard dashboard, boolean hideDashboardToolbar) {

5
common/data/src/main/java/org/thingsboard/server/common/data/HomeDashboardInfo.java

@ -15,13 +15,18 @@
*/
package org.thingsboard.server.common.data;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.thingsboard.server.common.data.id.DashboardId;
@ApiModel
@Data
@AllArgsConstructor
public class HomeDashboardInfo {
@ApiModelProperty(position = 1, value = "JSON object with the dashboard Id.")
private DashboardId dashboardId;
@ApiModelProperty(position = 1, value = HomeDashboard.HIDE_DASHBOARD_TOOLBAR_DESCRIPTION)
private boolean hideDashboardToolbar;
}

6
common/data/src/main/java/org/thingsboard/server/common/data/ShortCustomerInfo.java

@ -15,6 +15,8 @@
*/
package org.thingsboard.server.common.data;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
@ -25,16 +27,20 @@ import org.thingsboard.server.common.data.validation.NoXss;
* Created by igor on 2/27/18.
*/
@ApiModel
@AllArgsConstructor
public class ShortCustomerInfo {
@ApiModelProperty(position = 1, value = "JSON object with the customer Id.")
@Getter @Setter
private CustomerId customerId;
@ApiModelProperty(position = 2, value = "Title of the customer.")
@Getter @Setter
@NoXss
private String title;
@ApiModelProperty(position = 3, value = "Indicates special 'Public' customer used to embed dashboards on public websites.")
@Getter @Setter
private boolean isPublic;

5
common/data/src/main/java/org/thingsboard/server/common/data/UpdateMessage.java

@ -15,12 +15,17 @@
*/
package org.thingsboard.server.common.data;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel
@Data
public class UpdateMessage {
@ApiModelProperty(position = 1, value = "The message about new platform update available.")
private final String message;
@ApiModelProperty(position = 1, value = "'True' if new platform update is available.")
private final boolean isUpdateAvailable;
}

33
common/data/src/main/java/org/thingsboard/server/common/data/User.java

@ -17,6 +17,9 @@ package org.thingsboard.server.common.data;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.EntityId;
@ -26,6 +29,7 @@ import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.common.data.validation.NoXss;
@ApiModel
@EqualsAndHashCode(callSuper = true)
public class User extends SearchTextBasedWithAdditionalInfo<UserId> implements HasName, HasTenantId, HasCustomerId {
@ -58,6 +62,23 @@ public class User extends SearchTextBasedWithAdditionalInfo<UserId> implements H
this.lastName = user.getLastName();
}
@ApiModelProperty(position = 1, value = "JSON object with the User Id. " +
"Specify this field to update the device. " +
"Referencing non-existing User Id will cause error. " +
"Omit this field to create new customer." )
@Override
public UserId getId() {
return super.getId();
}
@ApiModelProperty(position = 2, value = "Timestamp of the user creation, in milliseconds", example = "1609459200000", readOnly = true)
@Override
public long getCreatedTime() {
return super.getCreatedTime();
}
@ApiModelProperty(position = 3, value = "JSON object with the Tenant Id.", readOnly = true)
public TenantId getTenantId() {
return tenantId;
}
@ -66,6 +87,7 @@ public class User extends SearchTextBasedWithAdditionalInfo<UserId> implements H
this.tenantId = tenantId;
}
@ApiModelProperty(position = 4, value = "JSON object with the Customer Id.", readOnly = true)
public CustomerId getCustomerId() {
return customerId;
}
@ -74,6 +96,7 @@ public class User extends SearchTextBasedWithAdditionalInfo<UserId> implements H
this.customerId = customerId;
}
@ApiModelProperty(position = 5, required = true, value = "Email of the user", example = "user@example.com")
public String getEmail() {
return email;
}
@ -82,12 +105,14 @@ public class User extends SearchTextBasedWithAdditionalInfo<UserId> implements H
this.email = email;
}
@ApiModelProperty(position = 6, readOnly = true, value = "Duplicates the email of the user, readonly", example = "user@example.com")
@Override
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
public String getName() {
return email;
}
@ApiModelProperty(position = 7, required = true, value = "Authority", example = "SYS_ADMIN, TENANT_ADMIN or CUSTOMER_USER")
public Authority getAuthority() {
return authority;
}
@ -96,6 +121,7 @@ public class User extends SearchTextBasedWithAdditionalInfo<UserId> implements H
this.authority = authority;
}
@ApiModelProperty(position = 8, required = true, value = "First name of the user", example = "John")
public String getFirstName() {
return firstName;
}
@ -104,6 +130,7 @@ public class User extends SearchTextBasedWithAdditionalInfo<UserId> implements H
this.firstName = firstName;
}
@ApiModelProperty(position = 9, required = true, value = "Last name of the user", example = "Doe")
public String getLastName() {
return lastName;
}
@ -112,6 +139,12 @@ public class User extends SearchTextBasedWithAdditionalInfo<UserId> implements H
this.lastName = lastName;
}
@ApiModelProperty(position = 10, value = "Additional parameters of the user", dataType = "com.fasterxml.jackson.databind.JsonNode")
@Override
public JsonNode getAdditionalInfo() {
return super.getAdditionalInfo();
}
@Override
public String getSearchText() {
return getEmail();

30
common/data/src/main/java/org/thingsboard/server/common/data/asset/Asset.java

@ -15,6 +15,9 @@
*/
package org.thingsboard.server.common.data.asset;
import com.fasterxml.jackson.databind.JsonNode;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.HasCustomerId;
import org.thingsboard.server.common.data.HasName;
@ -27,6 +30,7 @@ import org.thingsboard.server.common.data.validation.NoXss;
import java.util.Optional;
@ApiModel
@EqualsAndHashCode(callSuper = true)
public class Asset extends SearchTextBasedWithAdditionalInfo<AssetId> implements HasName, HasTenantId, HasCustomerId {
@ -67,6 +71,22 @@ public class Asset extends SearchTextBasedWithAdditionalInfo<AssetId> implements
Optional.ofNullable(asset.getAdditionalInfo()).ifPresent(this::setAdditionalInfo);
}
@ApiModelProperty(position = 1, value = "JSON object with the asset Id. " +
"Specify this field to update the asset. " +
"Referencing non-existing asset Id will cause error. " +
"Omit this field to create new asset.")
@Override
public AssetId getId() {
return super.getId();
}
@ApiModelProperty(position = 2, value = "Timestamp of the asset creation, in milliseconds", example = "1609459200000", readOnly = true)
@Override
public long getCreatedTime() {
return super.getCreatedTime();
}
@ApiModelProperty(position = 3, value = "JSON object with Tenant Id.", readOnly = true)
public TenantId getTenantId() {
return tenantId;
}
@ -75,6 +95,7 @@ public class Asset extends SearchTextBasedWithAdditionalInfo<AssetId> implements
this.tenantId = tenantId;
}
@ApiModelProperty(position = 4, value = "JSON object with Customer Id. Use 'assignAssetToCustomer' to change the Customer Id.", readOnly = true)
public CustomerId getCustomerId() {
return customerId;
}
@ -83,6 +104,7 @@ public class Asset extends SearchTextBasedWithAdditionalInfo<AssetId> implements
this.customerId = customerId;
}
@ApiModelProperty(position = 5, required = true, value = "Unique Asset Name in scope of Tenant", example = "Empire State Building")
@Override
public String getName() {
return name;
@ -92,6 +114,7 @@ public class Asset extends SearchTextBasedWithAdditionalInfo<AssetId> implements
this.name = name;
}
@ApiModelProperty(position = 6, required = true, value = "Asset type", example = "Building")
public String getType() {
return type;
}
@ -100,6 +123,7 @@ public class Asset extends SearchTextBasedWithAdditionalInfo<AssetId> implements
this.type = type;
}
@ApiModelProperty(position = 7, required = true, value = "Label that may be used in widgets", example = "NY Building")
public String getLabel() {
return label;
}
@ -113,6 +137,12 @@ public class Asset extends SearchTextBasedWithAdditionalInfo<AssetId> implements
return getName();
}
@ApiModelProperty(position = 8, value = "Additional parameters of the asset", dataType = "com.fasterxml.jackson.databind.JsonNode")
@Override
public JsonNode getAdditionalInfo() {
return super.getAdditionalInfo();
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();

5
common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetInfo.java

@ -15,13 +15,18 @@
*/
package org.thingsboard.server.common.data.asset;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.thingsboard.server.common.data.id.AssetId;
@ApiModel
@Data
public class AssetInfo extends Asset {
@ApiModelProperty(position = 9, value = "Title of the Customer that owns the asset.", readOnly = true)
private String customerTitle;
@ApiModelProperty(position = 10, value = "Indicates special 'Public' Customer that is auto-generated to use the assets on public dashboards.", readOnly = true)
private boolean customerIsPublic;
public AssetInfo() {

4
common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetSearchQuery.java

@ -15,6 +15,7 @@
*/
package org.thingsboard.server.common.data.asset;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.relation.EntityRelation;
@ -31,8 +32,11 @@ import java.util.List;
@Data
public class AssetSearchQuery {
@ApiModelProperty(position = 3, value = "Main search parameters.")
private RelationsSearchParameters parameters;
@ApiModelProperty(position = 1, value = "Type of the relation between root entity and asset (e.g. 'Contains' or 'Manages').")
private String relationType;
@ApiModelProperty(position = 2, value = "Array of asset types to filter the related entities (e.g. 'Building', 'Vehicle').")
private List<String> assetTypes;
public EntityRelationsQuery toEntitySearchQuery() {

6
common/data/src/main/java/org/thingsboard/server/common/data/device/DeviceSearchQuery.java

@ -15,6 +15,8 @@
*/
package org.thingsboard.server.common.data.device;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.relation.EntityRelation;
@ -25,11 +27,15 @@ import org.thingsboard.server.common.data.relation.RelationsSearchParameters;
import java.util.Collections;
import java.util.List;
@ApiModel
@Data
public class DeviceSearchQuery {
@ApiModelProperty(position = 3, value = "Main search parameters.")
private RelationsSearchParameters parameters;
@ApiModelProperty(position = 1, value = "Type of the relation between root entity and device (e.g. 'Contains' or 'Manages').")
private String relationType;
@ApiModelProperty(position = 2, value = "Array of device types to filter the related entities (e.g. 'Temperature Sensor', 'Smoke Sensor').")
private List<String> deviceTypes;
public EntityRelationsQuery toEntitySearchQuery() {

2
common/data/src/main/java/org/thingsboard/server/common/data/device/data/DefaultDeviceConfiguration.java

@ -15,9 +15,11 @@
*/
package org.thingsboard.server.common.data.device.data;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import org.thingsboard.server.common.data.DeviceProfileType;
@ApiModel
@Data
public class DefaultDeviceConfiguration implements DeviceConfiguration {

2
common/data/src/main/java/org/thingsboard/server/common/data/device/data/DeviceConfiguration.java

@ -19,8 +19,10 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import io.swagger.annotations.ApiModel;
import org.thingsboard.server.common.data.DeviceProfileType;
@ApiModel
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,

2
common/data/src/main/java/org/thingsboard/server/common/data/device/data/DeviceData.java

@ -15,8 +15,10 @@
*/
package org.thingsboard.server.common.data.device.data;
import io.swagger.annotations.ApiModel;
import lombok.Data;
@ApiModel
@Data
public class DeviceData {

2
common/data/src/main/java/org/thingsboard/server/common/data/device/data/DeviceTransportConfiguration.java

@ -19,10 +19,12 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import io.swagger.annotations.ApiModel;
import org.thingsboard.server.common.data.DeviceTransportType;
import java.io.Serializable;
@ApiModel
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,

5
common/data/src/main/java/org/thingsboard/server/common/data/id/AlarmId.java

@ -18,10 +18,13 @@ package org.thingsboard.server.common.data.id;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.thingsboard.server.common.data.EntityType;
import java.util.UUID;
@ApiModel
public class AlarmId extends UUIDBased implements EntityId {
private static final long serialVersionUID = 1L;
@ -35,7 +38,7 @@ public class AlarmId extends UUIDBased implements EntityId {
return new AlarmId(UUID.fromString(alarmId));
}
@JsonIgnore
@ApiModelProperty(position = 2, required = true, value = "string", example = "ALARM", allowableValues = "ALARM")
@Override
public EntityType getEntityType() {
return EntityType.ALARM;

5
common/data/src/main/java/org/thingsboard/server/common/data/id/ApiUsageStateId.java

@ -18,10 +18,13 @@ package org.thingsboard.server.common.data.id;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.thingsboard.server.common.data.EntityType;
import java.util.UUID;
@ApiModel
public class ApiUsageStateId extends UUIDBased implements EntityId {
@JsonCreator
@ -33,7 +36,7 @@ public class ApiUsageStateId extends UUIDBased implements EntityId {
return new ApiUsageStateId(UUID.fromString(userId));
}
@JsonIgnore
@ApiModelProperty(position = 2, required = true, value = "string", example = "API_USAGE_STATE", allowableValues = "API_USAGE_STATE")
@Override
public EntityType getEntityType() {
return EntityType.API_USAGE_STATE;

5
common/data/src/main/java/org/thingsboard/server/common/data/id/AssetId.java

@ -18,10 +18,13 @@ package org.thingsboard.server.common.data.id;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.thingsboard.server.common.data.EntityType;
import java.util.UUID;
@ApiModel
public class AssetId extends UUIDBased implements EntityId {
private static final long serialVersionUID = 1L;
@ -35,7 +38,7 @@ public class AssetId extends UUIDBased implements EntityId {
return new AssetId(UUID.fromString(assetId));
}
@JsonIgnore
@ApiModelProperty(position = 2, required = true, value = "string", example = "ASSET", allowableValues = "ASSET")
@Override
public EntityType getEntityType() {
return EntityType.ASSET;

5
common/data/src/main/java/org/thingsboard/server/common/data/id/CustomerId.java

@ -20,8 +20,11 @@ import java.util.UUID;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.thingsboard.server.common.data.EntityType;
@ApiModel
public final class CustomerId extends UUIDBased implements EntityId {
private static final long serialVersionUID = 1L;
@ -31,7 +34,7 @@ public final class CustomerId extends UUIDBased implements EntityId {
super(id);
}
@JsonIgnore
@ApiModelProperty(position = 2, required = true, value = "string", example = "CUSTOMER", allowableValues = "CUSTOMER")
@Override
public EntityType getEntityType() {
return EntityType.CUSTOMER;

5
common/data/src/main/java/org/thingsboard/server/common/data/id/DashboardId.java

@ -20,8 +20,11 @@ import java.util.UUID;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.thingsboard.server.common.data.EntityType;
@ApiModel
public class DashboardId extends UUIDBased implements EntityId {
@JsonCreator
@ -33,7 +36,7 @@ public class DashboardId extends UUIDBased implements EntityId {
return new DashboardId(UUID.fromString(dashboardId));
}
@JsonIgnore
@ApiModelProperty(position = 2, required = true, value = "string", example = "DASHBOARD", allowableValues = "DASHBOARD")
@Override
public EntityType getEntityType() {
return EntityType.DASHBOARD;

5
common/data/src/main/java/org/thingsboard/server/common/data/id/DeviceId.java

@ -20,8 +20,11 @@ import java.util.UUID;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.thingsboard.server.common.data.EntityType;
@ApiModel
public class DeviceId extends UUIDBased implements EntityId {
private static final long serialVersionUID = 1L;
@ -35,8 +38,8 @@ public class DeviceId extends UUIDBased implements EntityId {
return new DeviceId(UUID.fromString(deviceId));
}
@JsonIgnore
@Override
@ApiModelProperty(position = 2, required = true, value = "string", example = "DEVICE", allowableValues = "DEVICE")
public EntityType getEntityType() {
return EntityType.DEVICE;
}

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

@ -20,6 +20,7 @@ import java.util.UUID;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import org.thingsboard.server.common.data.EntityType;
public class DeviceProfileId extends UUIDBased implements EntityId {
@ -35,7 +36,7 @@ public class DeviceProfileId extends UUIDBased implements EntityId {
return new DeviceProfileId(UUID.fromString(deviceProfileId));
}
@JsonIgnore
@ApiModelProperty(position = 2, required = true, value = "string", example = "DEVICE_PROFILE", allowableValues = "DEVICE_PROFILE")
@Override
public EntityType getEntityType() {
return EntityType.DEVICE_PROFILE;

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

@ -18,6 +18,7 @@ package org.thingsboard.server.common.data.id;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import org.thingsboard.server.common.data.EntityType;
import java.util.UUID;
@ -35,7 +36,7 @@ public class EdgeId extends UUIDBased implements EntityId {
return new EdgeId(UUID.fromString(integrationId));
}
@JsonIgnore
@ApiModelProperty(position = 2, required = true, value = "string", example = "EDGE", allowableValues = "EDGE")
@Override
public EntityType getEntityType() {
return EntityType.EDGE;

2
common/data/src/main/java/org/thingsboard/server/common/data/id/EntityViewId.java

@ -17,6 +17,7 @@ package org.thingsboard.server.common.data.id;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import org.thingsboard.server.common.data.EntityType;
import java.util.UUID;
@ -37,6 +38,7 @@ public class EntityViewId extends UUIDBased implements EntityId {
return new EntityViewId(UUID.fromString(entityViewID));
}
@ApiModelProperty(position = 2, required = true, value = "string", example = "ENTITY_VIEW", allowableValues = "ENTITY_VIEW")
@Override
public EntityType getEntityType() {
return EntityType.ENTITY_VIEW;

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

@ -18,6 +18,7 @@ package org.thingsboard.server.common.data.id;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import org.thingsboard.server.common.data.EntityType;
import java.util.UUID;
@ -35,7 +36,7 @@ public class OtaPackageId extends UUIDBased implements EntityId {
return new OtaPackageId(UUID.fromString(firmwareId));
}
@JsonIgnore
@ApiModelProperty(position = 2, required = true, value = "string", example = "OTA_PACKAGE", allowableValues = "OTA_PACKAGE")
@Override
public EntityType getEntityType() {
return EntityType.OTA_PACKAGE;

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

@ -18,6 +18,7 @@ package org.thingsboard.server.common.data.id;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import org.thingsboard.server.common.data.EntityType;
import java.util.UUID;
@ -31,7 +32,7 @@ public final class RpcId extends UUIDBased implements EntityId {
super(id);
}
@JsonIgnore
@ApiModelProperty(position = 2, required = true, value = "string", example = "RPC", allowableValues = "RPC")
@Override
public EntityType getEntityType() {
return EntityType.RPC;

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

@ -18,6 +18,7 @@ package org.thingsboard.server.common.data.id;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import org.thingsboard.server.common.data.EntityType;
import java.util.UUID;
@ -29,7 +30,7 @@ public class RuleChainId extends UUIDBased implements EntityId {
super(id);
}
@JsonIgnore
@ApiModelProperty(position = 2, required = true, value = "string", example = "RULE_CHAIN", allowableValues = "RULE_CHAIN")
@Override
public EntityType getEntityType() {
return EntityType.RULE_CHAIN;

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

@ -18,6 +18,7 @@ package org.thingsboard.server.common.data.id;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import org.thingsboard.server.common.data.EntityType;
import java.util.UUID;
@ -29,7 +30,7 @@ public class RuleNodeId extends UUIDBased implements EntityId {
super(id);
}
@JsonIgnore
@ApiModelProperty(position = 2, required = true, value = "string", example = "RULE_NODE", allowableValues = "RULE_NODE")
@Override
public EntityType getEntityType() {
return EntityType.RULE_NODE;

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

@ -18,6 +18,7 @@ package org.thingsboard.server.common.data.id;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import org.thingsboard.server.common.data.EntityType;
import java.util.UUID;
@ -31,7 +32,7 @@ public class TbResourceId extends UUIDBased implements EntityId {
super(id);
}
@JsonIgnore
@ApiModelProperty(position = 2, required = true, value = "string", example = "TB_RESOURCE", allowableValues = "TB_RESOURCE")
@Override
public EntityType getEntityType() {
return EntityType.TB_RESOURCE;

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

@ -20,6 +20,7 @@ import java.util.UUID;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import org.thingsboard.server.common.data.EntityType;
public final class TenantId extends UUIDBased implements EntityId {
@ -34,7 +35,7 @@ public final class TenantId extends UUIDBased implements EntityId {
super(id);
}
@JsonIgnore
@ApiModelProperty(position = 2, required = true, value = "string", example = "TENANT", allowableValues = "TENANT")
@Override
public EntityType getEntityType() {
return EntityType.TENANT;

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

@ -20,6 +20,7 @@ import java.util.UUID;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import org.thingsboard.server.common.data.EntityType;
public class TenantProfileId extends UUIDBased implements EntityId {
@ -35,7 +36,7 @@ public class TenantProfileId extends UUIDBased implements EntityId {
return new TenantProfileId(UUID.fromString(tenantProfileId));
}
@JsonIgnore
@ApiModelProperty(position = 2, required = true, value = "string", example = "TENANT_PROFILE", allowableValues = "TENANT_PROFILE")
@Override
public EntityType getEntityType() {
return EntityType.TENANT_PROFILE;

5
common/data/src/main/java/org/thingsboard/server/common/data/id/UUIDBased.java

@ -15,9 +15,13 @@
*/
package org.thingsboard.server.common.data.id;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import java.util.UUID;
@ApiModel
public abstract class UUIDBased implements HasUUID, Serializable {
private static final long serialVersionUID = 1L;
@ -33,6 +37,7 @@ public abstract class UUIDBased implements HasUUID, Serializable {
this.id = id;
}
@ApiModelProperty(position = 1, required = true, value = "string", example = "784f394c-42b6-435a-983c-b7beff2784f9")
public UUID getId() {
return id;
}

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

@ -20,6 +20,7 @@ import java.util.UUID;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import org.thingsboard.server.common.data.EntityType;
public class UserId extends UUIDBased implements EntityId {
@ -33,7 +34,7 @@ public class UserId extends UUIDBased implements EntityId {
return new UserId(UUID.fromString(userId));
}
@JsonIgnore
@ApiModelProperty(position = 2, required = true, value = "string", example = "USER", allowableValues = "USER")
@Override
public EntityType getEntityType() {
return EntityType.USER;

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

@ -20,6 +20,7 @@ import java.util.UUID;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import org.thingsboard.server.common.data.EntityType;
public final class WidgetTypeId extends UUIDBased implements EntityId {
@ -31,7 +32,7 @@ public final class WidgetTypeId extends UUIDBased implements EntityId {
super(id);
}
@JsonIgnore
@ApiModelProperty(position = 2, required = true, value = "string", example = "WIDGET_TYPE", allowableValues = "WIDGET_TYPE")
@Override
public EntityType getEntityType() {
return EntityType.WIDGET_TYPE;

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

@ -20,6 +20,7 @@ import java.util.UUID;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import org.thingsboard.server.common.data.EntityType;
public final class WidgetsBundleId extends UUIDBased implements EntityId {
@ -31,7 +32,7 @@ public final class WidgetsBundleId extends UUIDBased implements EntityId {
super(id);
}
@JsonIgnore
@ApiModelProperty(position = 2, required = true, value = "string", example = "WIDGETS_BUNDLE", allowableValues = "WIDGETS_BUNDLE")
@Override
public EntityType getEntityType() {
return EntityType.WIDGETS_BUNDLE;

7
common/data/src/main/java/org/thingsboard/server/common/data/page/PageData.java

@ -17,12 +17,15 @@ package org.thingsboard.server.common.data.page;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
@ApiModel
public class PageData<T> {
private final List<T> data;
@ -45,18 +48,22 @@ public class PageData<T> {
this.hasNext = hasNext;
}
@ApiModelProperty(position = 1, value = "Array of the entities", readOnly = true)
public List<T> getData() {
return data;
}
@ApiModelProperty(position = 2, value = "Total number of available pages. Calculated based on the 'pageSize' request parameter and total number of entities that match search criteria", readOnly = true)
public int getTotalPages() {
return totalPages;
}
@ApiModelProperty(position = 3, value = "Total number of elements in all available pages", readOnly = true)
public long getTotalElements() {
return totalElements;
}
@ApiModelProperty(position = 4, value = "'false' value indicates the end of the result set", readOnly = true)
@JsonProperty("hasNext")
public boolean hasNext() {
return hasNext;

26
common/data/src/main/java/org/thingsboard/server/common/data/plugin/ComponentDescriptor.java

@ -16,6 +16,8 @@
package org.thingsboard.server.common.data.plugin;
import com.fasterxml.jackson.databind.JsonNode;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import org.thingsboard.server.common.data.SearchTextBased;
import org.thingsboard.server.common.data.id.ComponentDescriptorId;
@ -23,16 +25,23 @@ import org.thingsboard.server.common.data.id.ComponentDescriptorId;
/**
* @author Andrew Shvayka
*/
@ApiModel
@ToString
public class ComponentDescriptor extends SearchTextBased<ComponentDescriptorId> {
private static final long serialVersionUID = 1L;
@ApiModelProperty(position = 3, value = "Type of the Rule Node", readOnly = true)
@Getter @Setter private ComponentType type;
@ApiModelProperty(position = 4, value = "Scope of the Rule Node. Always set to 'TENANT', since no rule chains on the 'SYSTEM' level yet.", readOnly = true, allowableValues = "TENANT", example = "TENANT")
@Getter @Setter private ComponentScope scope;
@ApiModelProperty(position = 5, value = "Name of the Rule Node. Taken from the @RuleNode annotation.", readOnly = true, example = "Custom Rule Node")
@Getter @Setter private String name;
@ApiModelProperty(position = 6, value = "Full name of the Java class that implements the Rule Engine Node interface.", readOnly = true, example = "com.mycompany.CustomRuleNode")
@Getter @Setter private String clazz;
@ApiModelProperty(position = 7, value = "Complex JSON object that represents the Rule Node configuration.", readOnly = true)
@Getter @Setter private transient JsonNode configurationDescriptor;
@ApiModelProperty(position = 8, value = "Rule Node Actions. Deprecated. Always null.", readOnly = true)
@Getter @Setter private String actions;
public ComponentDescriptor() {
@ -53,12 +62,26 @@ public class ComponentDescriptor extends SearchTextBased<ComponentDescriptorId>
this.actions = plugin.getActions();
}
@ApiModelProperty(position = 1, value = "JSON object with the descriptor Id. " +
"Specify existing descriptor id to update the descriptor. " +
"Referencing non-existing descriptor Id will cause error. " +
"Omit this field to create new descriptor." )
@Override
public ComponentDescriptorId getId() {
return super.getId();
}
@ApiModelProperty(position = 2, value = "Timestamp of the descriptor creation, in milliseconds", example = "1609459200000", readOnly = true)
@Override
public long getCreatedTime() {
return super.getCreatedTime();
}
@Override
public String getSearchText() {
return name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@ -84,4 +107,5 @@ public class ComponentDescriptor extends SearchTextBased<ComponentDescriptorId>
result = 31 * result + (actions != null ? actions.hashCode() : 0);
return result;
}
}

9
common/data/src/main/java/org/thingsboard/server/common/data/relation/RelationsSearchParameters.java

@ -15,6 +15,8 @@
*/
package org.thingsboard.server.common.data.relation;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.thingsboard.server.common.data.EntityType;
@ -26,15 +28,22 @@ import java.util.UUID;
/**
* Created by ashvayka on 03.05.17.
*/
@ApiModel
@Data
@AllArgsConstructor
public class RelationsSearchParameters {
@ApiModelProperty(position = 1, value = "Root entity id to start search from.")
private UUID rootId;
@ApiModelProperty(position = 2, value = "Type of the root entity.")
private EntityType rootType;
@ApiModelProperty(position = 3, value = "Type of the root entity.")
private EntitySearchDirection direction;
@ApiModelProperty(position = 4, value = "Type of the relation.")
private RelationTypeGroup relationTypeGroup;
@ApiModelProperty(position = 5, value = "Maximum level of the search depth.")
private int maxLevel = 1;
@ApiModelProperty(position = 6, value = "Fetch entities that match the last level of search. Useful to find Devices that are strictly 'maxLevel' relations away from the root entity.")
private boolean fetchLastLevelOnly;
public RelationsSearchParameters(EntityId entityId, EntitySearchDirection direction, int maxLevel, boolean fetchLastLevelOnly) {

28
common/data/src/main/java/org/thingsboard/server/common/data/security/DeviceCredentials.java

@ -15,16 +15,18 @@
*/
package org.thingsboard.server.common.data.security;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.BaseData;
import org.thingsboard.server.common.data.id.DeviceCredentialsId;
import org.thingsboard.server.common.data.id.DeviceId;
@ApiModel
@EqualsAndHashCode(callSuper = true)
public class DeviceCredentials extends BaseData<DeviceCredentialsId> implements DeviceCredentialsFilter {
private static final long serialVersionUID = -7869261127032877765L;
private DeviceId deviceId;
private DeviceCredentialsType credentialsType;
private String credentialsId;
@ -46,6 +48,21 @@ public class DeviceCredentials extends BaseData<DeviceCredentialsId> implements
this.credentialsValue = deviceCredentials.getCredentialsValue();
}
@ApiModelProperty(position = 1, required = true, readOnly = true, value = "The Id is automatically generated during device creation. " +
"Use 'getDeviceCredentialsByDeviceId' to obtain the id based on device id. " +
"Use 'updateDeviceCredentials' to update device credentials. ", example = "784f394c-42b6-435a-983c-b7beff2784f9")
@Override
public DeviceCredentialsId getId() {
return super.getId();
}
@ApiModelProperty(position = 2, value = "Timestamp of the device credentials creation, in milliseconds", example = "1609459200000")
@Override
public long getCreatedTime() {
return super.getCreatedTime();
}
@ApiModelProperty(position = 3, required = true, value = "JSON object with the device Id.")
public DeviceId getDeviceId() {
return deviceId;
}
@ -54,6 +71,7 @@ public class DeviceCredentials extends BaseData<DeviceCredentialsId> implements
this.deviceId = deviceId;
}
@ApiModelProperty(position = 4, value = "Type of the credentials", allowableValues="ACCESS_TOKEN, X509_CERTIFICATE, MQTT_BASIC, LWM2M_CREDENTIALS")
@Override
public DeviceCredentialsType getCredentialsType() {
return credentialsType;
@ -63,6 +81,11 @@ public class DeviceCredentials extends BaseData<DeviceCredentialsId> implements
this.credentialsType = credentialsType;
}
@ApiModelProperty(position = 5, required = true, value = "Unique Credentials Id per platform instance. " +
"Used to lookup credentials from the database. " +
"By default, new access token for your device. " +
"Depends on the type of the credentials."
, example = "Access token or other value that depends on the credentials type")
@Override
public String getCredentialsId() {
return credentialsId;
@ -72,6 +95,9 @@ public class DeviceCredentials extends BaseData<DeviceCredentialsId> implements
this.credentialsId = credentialsId;
}
@ApiModelProperty(position = 6, value = "Value of the credentials. " +
"Null in case of ACCESS_TOKEN credentials type. Base64 value in case of X509_CERTIFICATE. " +
"Complex object in case of MQTT_BASIC and LWM2M_CREDENTIALS", example = "Null in case of ACCESS_TOKEN. See model definition.")
public String getCredentialsValue() {
return credentialsValue;
}

7
common/data/src/main/java/org/thingsboard/server/common/data/security/model/SecuritySettings.java

@ -15,15 +15,20 @@
*/
package org.thingsboard.server.common.data.security.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@ApiModel
@Data
public class SecuritySettings implements Serializable {
@ApiModelProperty(position = 1, value = "The user password policy object." )
private UserPasswordPolicy passwordPolicy;
@ApiModelProperty(position = 2, value = "Maximum number of failed login attempts allowed before user account is locked." )
private Integer maxFailedLoginAttempts;
@ApiModelProperty(position = 3, value = "Email to use for notifications about locked users." )
private String userLockoutNotificationEmail;
}

10
common/data/src/main/java/org/thingsboard/server/common/data/security/model/UserPasswordPolicy.java

@ -15,20 +15,30 @@
*/
package org.thingsboard.server.common.data.security.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@ApiModel
@Data
public class UserPasswordPolicy implements Serializable {
@ApiModelProperty(position = 1, value = "Minimum number of symbols in the password." )
private Integer minimumLength;
@ApiModelProperty(position = 1, value = "Minimum number of uppercase letters in the password." )
private Integer minimumUppercaseLetters;
@ApiModelProperty(position = 1, value = "Minimum number of lowercase letters in the password." )
private Integer minimumLowercaseLetters;
@ApiModelProperty(position = 1, value = "Minimum number of digits in the password." )
private Integer minimumDigits;
@ApiModelProperty(position = 1, value = "Minimum number of special in the password." )
private Integer minimumSpecialCharacters;
@ApiModelProperty(position = 1, value = "Password expiration period (days). Force expiration of the password." )
private Integer passwordExpirationPeriodDays;
@ApiModelProperty(position = 1, value = "Password reuse frequency (days). Disallow to use the same password for the defined number of days" )
private Integer passwordReuseFrequencyDays;
}

6
common/data/src/main/java/org/thingsboard/server/common/data/sms/config/AwsSnsSmsProviderConfiguration.java

@ -15,13 +15,19 @@
*/
package org.thingsboard.server.common.data.sms.config;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel
@Data
public class AwsSnsSmsProviderConfiguration implements SmsProviderConfiguration {
@ApiModelProperty(position = 1, value = "The AWS SNS Access Key ID.")
private String accessKeyId;
@ApiModelProperty(position = 2, value = "The AWS SNS Access Key.")
private String secretAccessKey;
@ApiModelProperty(position = 3, value = "The AWS region.")
private String region;
@Override

6
common/data/src/main/java/org/thingsboard/server/common/data/sms/config/TestSmsRequest.java

@ -15,13 +15,19 @@
*/
package org.thingsboard.server.common.data.sms.config;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel
@Data
public class TestSmsRequest {
@ApiModelProperty(position = 1, value = "The SMS provider configuration")
private SmsProviderConfiguration providerConfiguration;
@ApiModelProperty(position = 2, value = "The phone number or other identifier to specify as a recipient of the SMS.")
private String numberTo;
@ApiModelProperty(position = 3, value = "The test message")
private String message;
}

6
common/data/src/main/java/org/thingsboard/server/common/data/sms/config/TwilioSmsProviderConfiguration.java

@ -15,13 +15,19 @@
*/
package org.thingsboard.server.common.data.sms.config;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel
@Data
public class TwilioSmsProviderConfiguration implements SmsProviderConfiguration {
@ApiModelProperty(position = 1, value = "Twilio account Sid.")
private String accountSid;
@ApiModelProperty(position = 2, value = "Twilio account Token.")
private String accountToken;
@ApiModelProperty(position = 3, value = "The number/id of a sender.")
private String numberFrom;
@Override

6
pom.xml

@ -85,6 +85,7 @@
<jar-plugin.version>3.0.2</jar-plugin.version>
<springfox-swagger.version>2.6.1</springfox-swagger.version>
<springfox-swagger-ui-rfc6570.version>1.0.0</springfox-swagger-ui-rfc6570.version>
<swagger-annotations.version>1.5.10</swagger-annotations.version>
<spatial4j.version>0.7</spatial4j.version>
<jts.version>1.15.0</jts.version>
<bouncycastle.version>1.67</bouncycastle.version>
@ -1623,6 +1624,11 @@
<artifactId>springfox-swagger2</artifactId>
<version>${springfox-swagger.version}</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>${swagger-annotations.version}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>

Loading…
Cancel
Save