committed by
GitHub
1283 changed files with 59751 additions and 19684 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,37 @@ |
|||
-- |
|||
-- Copyright © 2016-2022 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. |
|||
-- |
|||
|
|||
CREATE TABLE IF NOT EXISTS queue ( |
|||
id uuid NOT NULL CONSTRAINT queue_pkey PRIMARY KEY, |
|||
created_time bigint NOT NULL, |
|||
tenant_id uuid, |
|||
name varchar(255), |
|||
topic varchar(255), |
|||
poll_interval int, |
|||
partitions int, |
|||
consumer_per_partition boolean, |
|||
pack_processing_timeout bigint, |
|||
submit_strategy varchar(255), |
|||
processing_strategy varchar(255), |
|||
additional_info varchar |
|||
); |
|||
|
|||
CREATE TABLE IF NOT EXISTS user_auth_settings ( |
|||
id uuid NOT NULL CONSTRAINT user_auth_settings_pkey PRIMARY KEY, |
|||
created_time bigint NOT NULL, |
|||
user_id uuid UNIQUE NOT NULL CONSTRAINT fk_user_auth_settings_user_id REFERENCES tb_user(id), |
|||
two_fa_settings varchar |
|||
); |
|||
@ -0,0 +1,49 @@ |
|||
-- |
|||
-- Copyright © 2016-2022 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. |
|||
-- |
|||
|
|||
ALTER TABLE device_profile |
|||
ADD COLUMN IF NOT EXISTS default_queue_id uuid; |
|||
|
|||
DO |
|||
$$ |
|||
BEGIN |
|||
IF EXISTS |
|||
(SELECT column_name |
|||
FROM information_schema.columns |
|||
WHERE table_name = 'device_profile' |
|||
AND column_name = 'default_queue_name' |
|||
) |
|||
THEN |
|||
UPDATE device_profile |
|||
SET default_queue_id = q.id |
|||
FROM queue as q |
|||
WHERE default_queue_name = q.name; |
|||
END IF; |
|||
END |
|||
$$; |
|||
|
|||
DO |
|||
$$ |
|||
BEGIN |
|||
IF NOT EXISTS(SELECT 1 FROM pg_constraint WHERE conname = 'fk_default_queue_device_profile') THEN |
|||
ALTER TABLE device_profile |
|||
ADD CONSTRAINT fk_default_queue_device_profile FOREIGN KEY (default_queue_id) REFERENCES queue (id); |
|||
END IF; |
|||
END; |
|||
$$; |
|||
|
|||
ALTER TABLE device_profile |
|||
DROP COLUMN IF EXISTS default_queue_name; |
|||
@ -0,0 +1,272 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.controller; |
|||
|
|||
import io.swagger.annotations.ApiOperation; |
|||
import io.swagger.annotations.ApiParam; |
|||
import lombok.Data; |
|||
import lombok.RequiredArgsConstructor; |
|||
import org.springframework.security.access.prepost.PreAuthorize; |
|||
import org.springframework.web.bind.annotation.DeleteMapping; |
|||
import org.springframework.web.bind.annotation.GetMapping; |
|||
import org.springframework.web.bind.annotation.PostMapping; |
|||
import org.springframework.web.bind.annotation.PutMapping; |
|||
import org.springframework.web.bind.annotation.RequestBody; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import org.springframework.web.bind.annotation.RequestParam; |
|||
import org.springframework.web.bind.annotation.RestController; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.security.model.mfa.PlatformTwoFaSettings; |
|||
import org.thingsboard.server.common.data.security.model.mfa.account.AccountTwoFaSettings; |
|||
import org.thingsboard.server.common.data.security.model.mfa.account.TwoFaAccountConfig; |
|||
import org.thingsboard.server.common.data.security.model.mfa.provider.TwoFaProviderConfig; |
|||
import org.thingsboard.server.common.data.security.model.mfa.provider.TwoFaProviderType; |
|||
import org.thingsboard.server.queue.util.TbCoreComponent; |
|||
import org.thingsboard.server.service.security.auth.mfa.TwoFactorAuthService; |
|||
import org.thingsboard.server.service.security.auth.mfa.config.TwoFaConfigManager; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
|
|||
import javax.validation.Valid; |
|||
import java.util.Collections; |
|||
import java.util.List; |
|||
import java.util.stream.Collectors; |
|||
|
|||
import static org.thingsboard.server.controller.ControllerConstants.NEW_LINE; |
|||
|
|||
@RestController |
|||
@RequestMapping("/api/2fa") |
|||
@TbCoreComponent |
|||
@RequiredArgsConstructor |
|||
public class TwoFaConfigController extends BaseController { |
|||
|
|||
private final TwoFaConfigManager twoFaConfigManager; |
|||
private final TwoFactorAuthService twoFactorAuthService; |
|||
|
|||
|
|||
@ApiOperation(value = "Get account 2FA settings (getAccountTwoFaSettings)", |
|||
notes = "Get user's account 2FA configuration. Configuration contains configs for different 2FA providers." + NEW_LINE + |
|||
"Example:\n" + |
|||
"```\n{\n \"configs\": {\n" + |
|||
" \"EMAIL\": {\n \"providerType\": \"EMAIL\",\n \"useByDefault\": true,\n \"email\": \"tenant@thingsboard.org\"\n },\n" + |
|||
" \"TOTP\": {\n \"providerType\": \"TOTP\",\n \"useByDefault\": false,\n \"authUrl\": \"otpauth://totp/TB%202FA:tenant@thingsboard.org?issuer=TB+2FA&secret=P6Z2TLYTASOGP6LCJZAD24ETT5DACNNX\"\n },\n" + |
|||
" \"SMS\": {\n \"providerType\": \"SMS\",\n \"useByDefault\": false,\n \"phoneNumber\": \"+380501253652\"\n }\n" + |
|||
" }\n}\n```" + |
|||
ControllerConstants.AVAILABLE_FOR_ANY_AUTHORIZED_USER) |
|||
@GetMapping("/account/settings") |
|||
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
|||
public AccountTwoFaSettings getAccountTwoFaSettings() throws ThingsboardException { |
|||
SecurityUser user = getCurrentUser(); |
|||
return twoFaConfigManager.getAccountTwoFaSettings(user.getTenantId(), user.getId()).orElse(null); |
|||
} |
|||
|
|||
|
|||
@ApiOperation(value = "Generate 2FA account config (generateTwoFaAccountConfig)", |
|||
notes = "Generate new 2FA account config template for specified provider type. " + NEW_LINE + |
|||
"For TOTP, this will return a corresponding account config template " + |
|||
"with a generated OTP auth URL (with new random secret key for each API call) that can be then " + |
|||
"converted to a QR code to scan with an authenticator app. Example:\n" + |
|||
"```\n{\n" + |
|||
" \"providerType\": \"TOTP\",\n" + |
|||
" \"useByDefault\": false,\n" + |
|||
" \"authUrl\": \"otpauth://totp/TB%202FA:tenant@thingsboard.org?issuer=TB+2FA&secret=PNJDNWJVAK4ZTUYT7RFGPQLXA7XGU7PX\"\n" + |
|||
"}\n```" + NEW_LINE + |
|||
"For EMAIL, the generated config will contain email from user's account:\n" + |
|||
"```\n{\n" + |
|||
" \"providerType\": \"EMAIL\",\n" + |
|||
" \"useByDefault\": false,\n" + |
|||
" \"email\": \"tenant@thingsboard.org\"\n" + |
|||
"}\n```" + NEW_LINE + |
|||
"For SMS 2FA this method will just return a config with empty/default values as there is nothing to generate/preset:\n" + |
|||
"```\n{\n" + |
|||
" \"providerType\": \"SMS\",\n" + |
|||
" \"useByDefault\": false,\n" + |
|||
" \"phoneNumber\": null\n" + |
|||
"}\n```" + NEW_LINE + |
|||
"Will throw an error (Bad Request) if the provider is not configured for usage. " + |
|||
ControllerConstants.AVAILABLE_FOR_ANY_AUTHORIZED_USER) |
|||
@PostMapping("/account/config/generate") |
|||
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
|||
public TwoFaAccountConfig generateTwoFaAccountConfig(@ApiParam(value = "2FA provider type to generate new account config for", defaultValue = "TOTP", required = true) |
|||
@RequestParam TwoFaProviderType providerType) throws Exception { |
|||
SecurityUser user = getCurrentUser(); |
|||
return twoFactorAuthService.generateNewAccountConfig(user, providerType); |
|||
} |
|||
|
|||
@ApiOperation(value = "Submit 2FA account config (submitTwoFaAccountConfig)", |
|||
notes = "Submit 2FA account config to prepare for a future verification. " + |
|||
"Basically, this method will send a verification code for a given account config, if this has " + |
|||
"sense for a chosen 2FA provider. This code is needed to then verify and save the account config." + NEW_LINE + |
|||
"Example of EMAIL 2FA account config:\n" + |
|||
"```\n{\n" + |
|||
" \"providerType\": \"EMAIL\",\n" + |
|||
" \"useByDefault\": true,\n" + |
|||
" \"email\": \"separate-email-for-2fa@thingsboard.org\"\n" + |
|||
"}\n```" + NEW_LINE + |
|||
"Example of SMS 2FA account config:\n" + |
|||
"```\n{\n" + |
|||
" \"providerType\": \"SMS\",\n" + |
|||
" \"useByDefault\": false,\n" + |
|||
" \"phoneNumber\": \"+38012312321\"\n" + |
|||
"}\n```" + NEW_LINE + |
|||
"For TOTP this method does nothing." + NEW_LINE + |
|||
"Will throw an error (Bad Request) if submitted account config is not valid, " + |
|||
"or if the provider is not configured for usage. " + |
|||
ControllerConstants.AVAILABLE_FOR_ANY_AUTHORIZED_USER) |
|||
@PostMapping("/account/config/submit") |
|||
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
|||
public void submitTwoFaAccountConfig(@Valid @RequestBody TwoFaAccountConfig accountConfig) throws Exception { |
|||
SecurityUser user = getCurrentUser(); |
|||
twoFactorAuthService.prepareVerificationCode(user, accountConfig, false); |
|||
} |
|||
|
|||
@ApiOperation(value = "Verify and save 2FA account config (verifyAndSaveTwoFaAccountConfig)", |
|||
notes = "Checks the verification code for submitted config, and if it is correct, saves the provided account config. " + NEW_LINE + |
|||
"Returns whole account's 2FA settings object.\n" + |
|||
"Will throw an error (Bad Request) if the provider is not configured for usage. " + |
|||
ControllerConstants.AVAILABLE_FOR_ANY_AUTHORIZED_USER) |
|||
@PostMapping("/account/config") |
|||
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
|||
public AccountTwoFaSettings verifyAndSaveTwoFaAccountConfig(@Valid @RequestBody TwoFaAccountConfig accountConfig, |
|||
@RequestParam(required = false) String verificationCode) throws Exception { |
|||
SecurityUser user = getCurrentUser(); |
|||
if (twoFaConfigManager.getTwoFaAccountConfig(user.getTenantId(), user.getId(), accountConfig.getProviderType()).isPresent()) { |
|||
throw new IllegalArgumentException("2FA provider is already configured"); |
|||
} |
|||
|
|||
boolean verificationSuccess; |
|||
if (accountConfig.getProviderType() != TwoFaProviderType.BACKUP_CODE) { |
|||
verificationSuccess = twoFactorAuthService.checkVerificationCode(user, verificationCode, accountConfig, false); |
|||
} else { |
|||
verificationSuccess = true; |
|||
} |
|||
if (verificationSuccess) { |
|||
return twoFaConfigManager.saveTwoFaAccountConfig(user.getTenantId(), user.getId(), accountConfig); |
|||
} else { |
|||
throw new IllegalArgumentException("Verification code is incorrect"); |
|||
} |
|||
} |
|||
|
|||
@ApiOperation(value = "Update 2FA account config (updateTwoFaAccountConfig)", notes = |
|||
"Update config for a given provider type. \n" + |
|||
"Update request example:\n" + |
|||
"```\n{\n \"useByDefault\": true\n}\n```\n" + |
|||
"Returns whole account's 2FA settings object.\n" + |
|||
ControllerConstants.AVAILABLE_FOR_ANY_AUTHORIZED_USER) |
|||
@PutMapping("/account/config") |
|||
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
|||
public AccountTwoFaSettings updateTwoFaAccountConfig(@RequestParam TwoFaProviderType providerType, |
|||
@RequestBody TwoFaAccountConfigUpdateRequest updateRequest) throws ThingsboardException { |
|||
SecurityUser user = getCurrentUser(); |
|||
|
|||
TwoFaAccountConfig accountConfig = twoFaConfigManager.getTwoFaAccountConfig(user.getTenantId(), user.getId(), providerType) |
|||
.orElseThrow(() -> new IllegalArgumentException("Config for " + providerType + " 2FA provider not found")); |
|||
accountConfig.setUseByDefault(updateRequest.isUseByDefault()); |
|||
return twoFaConfigManager.saveTwoFaAccountConfig(user.getTenantId(), user.getId(), accountConfig); |
|||
} |
|||
|
|||
@ApiOperation(value = "Delete 2FA account config (deleteTwoFaAccountConfig)", notes = |
|||
"Delete 2FA config for a given 2FA provider type. \n" + |
|||
"Returns whole account's 2FA settings object.\n" + |
|||
ControllerConstants.AVAILABLE_FOR_ANY_AUTHORIZED_USER) |
|||
@DeleteMapping("/account/config") |
|||
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
|||
public AccountTwoFaSettings deleteTwoFaAccountConfig(@RequestParam TwoFaProviderType providerType) throws ThingsboardException { |
|||
SecurityUser user = getCurrentUser(); |
|||
return twoFaConfigManager.deleteTwoFaAccountConfig(user.getTenantId(), user.getId(), providerType); |
|||
} |
|||
|
|||
|
|||
@ApiOperation(value = "Get available 2FA providers (getAvailableTwoFaProviders)", notes = |
|||
"Get the list of provider types available for user to use (the ones configured by tenant or sysadmin).\n" + |
|||
"Example of response:\n" + |
|||
"```\n[\n \"TOTP\",\n \"EMAIL\",\n \"SMS\"\n]\n```" + |
|||
ControllerConstants.AVAILABLE_FOR_ANY_AUTHORIZED_USER |
|||
) |
|||
@GetMapping("/providers") |
|||
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
|||
public List<TwoFaProviderType> getAvailableTwoFaProviders() throws ThingsboardException { |
|||
return twoFaConfigManager.getPlatformTwoFaSettings(getTenantId(), true) |
|||
.map(PlatformTwoFaSettings::getProviders).orElse(Collections.emptyList()).stream() |
|||
.map(TwoFaProviderConfig::getProviderType) |
|||
.collect(Collectors.toList()); |
|||
} |
|||
|
|||
|
|||
@ApiOperation(value = "Get platform 2FA settings (getPlatformTwoFaSettings)", |
|||
notes = "Get platform settings for 2FA. The settings are described for savePlatformTwoFaSettings API method. " + |
|||
"If 2FA is not configured, then an empty response will be returned." + |
|||
ControllerConstants.SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) |
|||
@GetMapping("/settings") |
|||
@PreAuthorize("hasAnyAuthority('SYS_ADMIN')") |
|||
public PlatformTwoFaSettings getPlatformTwoFaSettings() throws ThingsboardException { |
|||
return twoFaConfigManager.getPlatformTwoFaSettings(getTenantId(), false).orElse(null); |
|||
} |
|||
|
|||
@ApiOperation(value = "Save platform 2FA settings (savePlatformTwoFaSettings)", |
|||
notes = "Save 2FA settings for platform. The settings have following properties:\n" + |
|||
"- `providers` - the list of 2FA providers' configs. Users will only be allowed to use 2FA providers from this list. \n\n" + |
|||
"- `minVerificationCodeSendPeriod` - minimal period in seconds to wait after verification code send request to send next request. \n" + |
|||
"- `verificationCodeCheckRateLimit` - rate limit configuration for verification code checking.\n" + |
|||
"The format is standard: 'amountOfRequests:periodInSeconds'. The value of '1:60' would limit verification " + |
|||
"code checking requests to one per minute.\n" + |
|||
"- `maxVerificationFailuresBeforeUserLockout` - maximum number of verification failures before a user gets disabled.\n" + |
|||
"- `totalAllowedTimeForVerification` - total amount of time in seconds allotted for verification. " + |
|||
"Basically, this property sets a lifetime for pre-verification token. If not set, default value of 30 minutes is used.\n" + NEW_LINE + |
|||
"TOTP 2FA provider config has following settings:\n" + |
|||
"- `issuerName` - issuer name that will be displayed in an authenticator app near a username. Must not be blank.\n\n" + |
|||
"For SMS 2FA provider:\n" + |
|||
"- `smsVerificationMessageTemplate` - verification message template. Available template variables " + |
|||
"are ${code} and ${userEmail}. It must not be blank and must contain verification code variable.\n" + |
|||
"- `verificationCodeLifetime` - verification code lifetime in seconds. Required to be positive.\n\n" + |
|||
"For EMAIL provider type:\n" + |
|||
"- `verificationCodeLifetime` - the same as for SMS." + NEW_LINE + |
|||
"Example of the settings:\n" + |
|||
"```\n{\n" + |
|||
" \"providers\": [\n" + |
|||
" {\n" + |
|||
" \"providerType\": \"TOTP\",\n" + |
|||
" \"issuerName\": \"TB\"\n" + |
|||
" },\n" + |
|||
" {\n" + |
|||
" \"providerType\": \"EMAIL\",\n" + |
|||
" \"verificationCodeLifetime\": 60\n" + |
|||
" },\n" + |
|||
" {\n" + |
|||
" \"providerType\": \"SMS\",\n" + |
|||
" \"verificationCodeLifetime\": 60,\n" + |
|||
" \"smsVerificationMessageTemplate\": \"Here is your verification code: ${code}\"\n" + |
|||
" }\n" + |
|||
" ],\n" + |
|||
" \"minVerificationCodeSendPeriod\": 60,\n" + |
|||
" \"verificationCodeCheckRateLimit\": \"3:900\",\n" + |
|||
" \"maxVerificationFailuresBeforeUserLockout\": 10,\n" + |
|||
" \"totalAllowedTimeForVerification\": 600\n" + |
|||
"}\n```" + |
|||
ControllerConstants.SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) |
|||
@PostMapping("/settings") |
|||
@PreAuthorize("hasAnyAuthority('SYS_ADMIN')") |
|||
public PlatformTwoFaSettings savePlatformTwoFaSettings(@ApiParam(value = "Settings value", required = true) |
|||
@RequestBody PlatformTwoFaSettings twoFaSettings) throws ThingsboardException { |
|||
return twoFaConfigManager.savePlatformTwoFaSettings(getTenantId(), twoFaSettings); |
|||
} |
|||
|
|||
|
|||
@Data |
|||
public static class TwoFaAccountConfigUpdateRequest { |
|||
private boolean useByDefault; |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,152 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.controller; |
|||
|
|||
import io.swagger.annotations.ApiOperation; |
|||
import lombok.AllArgsConstructor; |
|||
import lombok.Builder; |
|||
import lombok.Data; |
|||
import lombok.RequiredArgsConstructor; |
|||
import org.springframework.security.access.prepost.PreAuthorize; |
|||
import org.springframework.web.bind.annotation.GetMapping; |
|||
import org.springframework.web.bind.annotation.PostMapping; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import org.springframework.web.bind.annotation.RequestParam; |
|||
import org.springframework.web.bind.annotation.RestController; |
|||
import org.thingsboard.server.common.data.StringUtils; |
|||
import org.thingsboard.server.common.data.audit.ActionType; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.security.model.mfa.PlatformTwoFaSettings; |
|||
import org.thingsboard.server.common.data.security.model.mfa.account.EmailTwoFaAccountConfig; |
|||
import org.thingsboard.server.common.data.security.model.mfa.account.SmsTwoFaAccountConfig; |
|||
import org.thingsboard.server.common.data.security.model.mfa.provider.TwoFaProviderType; |
|||
import org.thingsboard.server.dao.user.UserService; |
|||
import org.thingsboard.server.queue.util.TbCoreComponent; |
|||
import org.thingsboard.server.service.security.auth.mfa.TwoFactorAuthService; |
|||
import org.thingsboard.server.service.security.auth.mfa.config.TwoFaConfigManager; |
|||
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.token.JwtTokenFactory; |
|||
import org.thingsboard.server.service.security.system.SystemSecurityService; |
|||
|
|||
import javax.servlet.http.HttpServletRequest; |
|||
import java.util.Collections; |
|||
import java.util.List; |
|||
import java.util.Optional; |
|||
import java.util.stream.Collectors; |
|||
|
|||
import static org.thingsboard.server.controller.ControllerConstants.NEW_LINE; |
|||
|
|||
@RestController |
|||
@RequestMapping("/api/auth/2fa") |
|||
@TbCoreComponent |
|||
@RequiredArgsConstructor |
|||
public class TwoFactorAuthController extends BaseController { |
|||
|
|||
private final TwoFactorAuthService twoFactorAuthService; |
|||
private final TwoFaConfigManager twoFaConfigManager; |
|||
private final JwtTokenFactory tokenFactory; |
|||
private final SystemSecurityService systemSecurityService; |
|||
private final UserService userService; |
|||
|
|||
|
|||
@ApiOperation(value = "Request 2FA verification code (requestTwoFaVerificationCode)", |
|||
notes = "Request 2FA verification code." + NEW_LINE + |
|||
"To make a request to this endpoint, you need an access token with the scope of PRE_VERIFICATION_TOKEN, " + |
|||
"which is issued on username/password auth if 2FA is enabled." + NEW_LINE + |
|||
"The API method is rate limited (using rate limit config from TwoFactorAuthSettings). " + |
|||
"Will return a Bad Request error if provider is not configured for usage, " + |
|||
"and Too Many Requests error if rate limits are exceeded.") |
|||
@PostMapping("/verification/send") |
|||
@PreAuthorize("hasAuthority('PRE_VERIFICATION_TOKEN')") |
|||
public void requestTwoFaVerificationCode(@RequestParam TwoFaProviderType providerType) throws Exception { |
|||
SecurityUser user = getCurrentUser(); |
|||
twoFactorAuthService.prepareVerificationCode(user, providerType, true); |
|||
} |
|||
|
|||
@ApiOperation(value = "Check 2FA verification code (checkTwoFaVerificationCode)", |
|||
notes = "Checks 2FA verification code, and if it is correct the method returns a regular access and refresh token pair." + NEW_LINE + |
|||
"The API method is rate limited (using rate limit config from TwoFactorAuthSettings), and also will block a user " + |
|||
"after X unsuccessful verification attempts if such behavior is configured (in TwoFactorAuthSettings)." + NEW_LINE + |
|||
"Will return a Bad Request error if provider is not configured for usage, " + |
|||
"and Too Many Requests error if rate limits are exceeded.") |
|||
@PostMapping("/verification/check") |
|||
@PreAuthorize("hasAuthority('PRE_VERIFICATION_TOKEN')") |
|||
public JwtTokenPair checkTwoFaVerificationCode(@RequestParam TwoFaProviderType providerType, |
|||
@RequestParam String verificationCode, HttpServletRequest servletRequest) throws Exception { |
|||
SecurityUser user = getCurrentUser(); |
|||
boolean verificationSuccess = twoFactorAuthService.checkVerificationCode(user, providerType, verificationCode, true); |
|||
if (verificationSuccess) { |
|||
systemSecurityService.logLoginAction(user, new RestAuthenticationDetails(servletRequest), ActionType.LOGIN, null); |
|||
user = new SecurityUser(userService.findUserById(user.getTenantId(), user.getId()), true, user.getUserPrincipal()); |
|||
return tokenFactory.createTokenPair(user); |
|||
} else { |
|||
ThingsboardException error = new ThingsboardException("Verification code is incorrect", ThingsboardErrorCode.BAD_REQUEST_PARAMS); |
|||
systemSecurityService.logLoginAction(user, new RestAuthenticationDetails(servletRequest), ActionType.LOGIN, error); |
|||
throw error; |
|||
} |
|||
} |
|||
|
|||
|
|||
@ApiOperation(value = "Get available 2FA providers (getAvailableTwoFaProviders)", notes = |
|||
"Get the list of 2FA provider infos available for user to use. Example:\n" + |
|||
"```\n[\n" + |
|||
" {\n \"type\": \"EMAIL\",\n \"default\": true,\n \"contact\": \"ab*****ko@gmail.com\"\n },\n" + |
|||
" {\n \"type\": \"TOTP\",\n \"default\": false,\n \"contact\": null\n },\n" + |
|||
" {\n \"type\": \"SMS\",\n \"default\": false,\n \"contact\": \"+38********12\"\n }\n" + |
|||
"]\n```") |
|||
@GetMapping("/providers") |
|||
@PreAuthorize("hasAuthority('PRE_VERIFICATION_TOKEN')") |
|||
public List<TwoFaProviderInfo> getAvailableTwoFaProviders() throws ThingsboardException { |
|||
SecurityUser user = getCurrentUser(); |
|||
Optional<PlatformTwoFaSettings> platformTwoFaSettings = twoFaConfigManager.getPlatformTwoFaSettings(user.getTenantId(), true); |
|||
return twoFaConfigManager.getAccountTwoFaSettings(user.getTenantId(), user.getId()) |
|||
.map(settings -> settings.getConfigs().values()).orElse(Collections.emptyList()) |
|||
.stream().map(config -> { |
|||
String contact = null; |
|||
switch (config.getProviderType()) { |
|||
case SMS: |
|||
String phoneNumber = ((SmsTwoFaAccountConfig) config).getPhoneNumber(); |
|||
contact = StringUtils.obfuscate(phoneNumber, 2, '*', phoneNumber.indexOf('+') + 1, phoneNumber.length()); |
|||
break; |
|||
case EMAIL: |
|||
String email = ((EmailTwoFaAccountConfig) config).getEmail(); |
|||
contact = StringUtils.obfuscate(email, 2, '*', 0, email.indexOf('@')); |
|||
break; |
|||
} |
|||
return TwoFaProviderInfo.builder() |
|||
.type(config.getProviderType()) |
|||
.isDefault(config.isUseByDefault()) |
|||
.contact(contact) |
|||
.minVerificationCodeSendPeriod(platformTwoFaSettings.get().getMinVerificationCodeSendPeriod()) |
|||
.build(); |
|||
}) |
|||
.collect(Collectors.toList()); |
|||
} |
|||
|
|||
@Data |
|||
@AllArgsConstructor |
|||
@Builder |
|||
public static class TwoFaProviderInfo { |
|||
private TwoFaProviderType type; |
|||
private boolean isDefault; |
|||
private String contact; |
|||
private Integer minVerificationCodeSendPeriod; |
|||
} |
|||
|
|||
} |
|||
@ -1,48 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.edge.rpc; |
|||
|
|||
import com.fasterxml.jackson.databind.JsonNode; |
|||
import org.thingsboard.server.common.data.edge.EdgeEvent; |
|||
import org.thingsboard.server.common.data.edge.EdgeEventActionType; |
|||
import org.thingsboard.server.common.data.edge.EdgeEventType; |
|||
import org.thingsboard.server.common.data.id.EdgeId; |
|||
import org.thingsboard.server.common.data.id.EntityId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
|
|||
public final class EdgeEventUtils { |
|||
|
|||
private EdgeEventUtils() { |
|||
} |
|||
|
|||
public static EdgeEvent constructEdgeEvent(TenantId tenantId, |
|||
EdgeId edgeId, |
|||
EdgeEventType type, |
|||
EdgeEventActionType action, |
|||
EntityId entityId, |
|||
JsonNode body) { |
|||
EdgeEvent edgeEvent = new EdgeEvent(); |
|||
edgeEvent.setTenantId(tenantId); |
|||
edgeEvent.setEdgeId(edgeId); |
|||
edgeEvent.setType(type); |
|||
edgeEvent.setAction(action); |
|||
if (entityId != null) { |
|||
edgeEvent.setEntityId(entityId.getId()); |
|||
} |
|||
edgeEvent.setBody(body); |
|||
return edgeEvent; |
|||
} |
|||
} |
|||
@ -0,0 +1,245 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy; |
|||
|
|||
import com.google.common.util.concurrent.Futures; |
|||
import com.google.common.util.concurrent.ListenableFuture; |
|||
import lombok.Getter; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.thingsboard.server.cluster.TbClusterService; |
|||
import org.thingsboard.server.common.data.EntityType; |
|||
import org.thingsboard.server.common.data.HasName; |
|||
import org.thingsboard.server.common.data.User; |
|||
import org.thingsboard.server.common.data.alarm.AlarmInfo; |
|||
import org.thingsboard.server.common.data.alarm.AlarmQuery; |
|||
import org.thingsboard.server.common.data.audit.ActionType; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.id.AlarmId; |
|||
import org.thingsboard.server.common.data.id.CustomerId; |
|||
import org.thingsboard.server.common.data.id.EdgeId; |
|||
import org.thingsboard.server.common.data.id.EntityId; |
|||
import org.thingsboard.server.common.data.id.EntityIdFactory; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.page.PageData; |
|||
import org.thingsboard.server.common.data.page.PageDataIterableByTenantIdEntityId; |
|||
import org.thingsboard.server.common.data.page.TimePageLink; |
|||
import org.thingsboard.server.dao.alarm.AlarmService; |
|||
import org.thingsboard.server.dao.asset.AssetService; |
|||
import org.thingsboard.server.dao.attributes.AttributesService; |
|||
import org.thingsboard.server.dao.customer.CustomerService; |
|||
import org.thingsboard.server.dao.dashboard.DashboardService; |
|||
import org.thingsboard.server.dao.device.ClaimDevicesService; |
|||
import org.thingsboard.server.dao.device.DeviceCredentialsService; |
|||
import org.thingsboard.server.dao.device.DeviceProfileService; |
|||
import org.thingsboard.server.dao.device.DeviceService; |
|||
import org.thingsboard.server.dao.edge.EdgeService; |
|||
import org.thingsboard.server.dao.entityview.EntityViewService; |
|||
import org.thingsboard.server.dao.exception.DataValidationException; |
|||
import org.thingsboard.server.dao.exception.IncorrectParameterException; |
|||
import org.thingsboard.server.dao.model.ModelConstants; |
|||
import org.thingsboard.server.dao.ota.OtaPackageService; |
|||
import org.thingsboard.server.dao.queue.QueueService; |
|||
import org.thingsboard.server.dao.relation.RelationService; |
|||
import org.thingsboard.server.dao.rule.RuleChainService; |
|||
import org.thingsboard.server.dao.tenant.TbTenantProfileCache; |
|||
import org.thingsboard.server.dao.tenant.TenantService; |
|||
import org.thingsboard.server.dao.user.UserService; |
|||
import org.thingsboard.server.dao.widget.WidgetsBundleService; |
|||
import org.thingsboard.server.service.action.EntityActionService; |
|||
import org.thingsboard.server.service.edge.EdgeNotificationService; |
|||
import org.thingsboard.server.service.executors.DbCallbackExecutorService; |
|||
import org.thingsboard.server.service.install.InstallScripts; |
|||
import org.thingsboard.server.service.ota.OtaPackageStateService; |
|||
import org.thingsboard.server.service.resource.TbResourceService; |
|||
import org.thingsboard.server.service.rule.TbRuleChainService; |
|||
import org.thingsboard.server.service.security.permission.AccessControlService; |
|||
import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; |
|||
|
|||
import javax.mail.MessagingException; |
|||
import java.util.ArrayList; |
|||
import java.util.Collections; |
|||
import java.util.List; |
|||
import java.util.Optional; |
|||
import java.util.stream.Collectors; |
|||
|
|||
@Slf4j |
|||
public abstract class AbstractTbEntityService { |
|||
|
|||
protected static final int DEFAULT_PAGE_SIZE = 1000; |
|||
|
|||
@Value("${server.log_controller_error_stack_trace}") |
|||
@Getter |
|||
private boolean logControllerErrorStackTrace; |
|||
@Value("${edges.enabled}") |
|||
@Getter |
|||
protected boolean edgesEnabled; |
|||
|
|||
@Autowired |
|||
protected DbCallbackExecutorService dbExecutor; |
|||
@Autowired |
|||
protected TbNotificationEntityService notificationEntityService; |
|||
@Autowired(required = false) |
|||
protected EdgeService edgeService; |
|||
@Autowired |
|||
protected AlarmService alarmService; |
|||
@Autowired |
|||
protected EntityActionService entityActionService; |
|||
@Autowired |
|||
protected DeviceService deviceService; |
|||
@Autowired |
|||
protected AssetService assetService; |
|||
@Autowired |
|||
protected DeviceCredentialsService deviceCredentialsService; |
|||
@Autowired |
|||
protected TenantService tenantService; |
|||
@Autowired |
|||
protected CustomerService customerService; |
|||
@Autowired |
|||
protected ClaimDevicesService claimDevicesService; |
|||
@Autowired |
|||
protected TbTenantProfileCache tenantProfileCache; |
|||
@Autowired |
|||
protected RuleChainService ruleChainService; |
|||
@Autowired |
|||
protected TbRuleChainService tbRuleChainService; |
|||
@Autowired |
|||
protected EdgeNotificationService edgeNotificationService; |
|||
@Autowired |
|||
protected QueueService queueService; |
|||
@Autowired |
|||
protected DashboardService dashboardService; |
|||
@Autowired |
|||
protected EntityViewService entityViewService; |
|||
@Autowired |
|||
protected TelemetrySubscriptionService tsSubService; |
|||
@Autowired |
|||
protected AttributesService attributesService; |
|||
@Autowired |
|||
protected AccessControlService accessControlService; |
|||
@Autowired |
|||
protected DeviceProfileService deviceProfileService; |
|||
@Autowired |
|||
protected TbClusterService tbClusterService; |
|||
@Autowired |
|||
protected OtaPackageStateService otaPackageStateService; |
|||
@Autowired |
|||
protected RelationService relationService; |
|||
@Autowired |
|||
protected OtaPackageService otaPackageService; |
|||
@Autowired |
|||
protected InstallScripts installScripts; |
|||
@Autowired |
|||
protected UserService userService; |
|||
@Autowired |
|||
protected TbResourceService resourceService; |
|||
@Autowired |
|||
protected WidgetsBundleService widgetsBundleService; |
|||
|
|||
protected ListenableFuture<Void> removeAlarmsByEntityId(TenantId tenantId, EntityId entityId) { |
|||
ListenableFuture<PageData<AlarmInfo>> alarmsFuture = |
|||
alarmService.findAlarms(tenantId, new AlarmQuery(entityId, new TimePageLink(Integer.MAX_VALUE), null, null, false)); |
|||
|
|||
ListenableFuture<List<AlarmId>> alarmIdsFuture = Futures.transform(alarmsFuture, page -> |
|||
page.getData().stream().map(AlarmInfo::getId).collect(Collectors.toList()), dbExecutor); |
|||
|
|||
return Futures.transform(alarmIdsFuture, ids -> { |
|||
ids.stream().map(alarmId -> alarmService.deleteAlarm(tenantId, alarmId)).collect(Collectors.toList()); |
|||
return null; |
|||
}, dbExecutor); |
|||
} |
|||
|
|||
protected <E extends HasName, I extends EntityId> void logEntityAction(User user, TenantId tenantId, I entityId, E entity, CustomerId customerId, |
|||
ActionType actionType, Exception e, Object... additionalInfo) throws ThingsboardException { |
|||
if (user != null) { |
|||
entityActionService.logEntityAction(user, entityId, entity, customerId, actionType, e, additionalInfo); |
|||
} else if (e == null) { |
|||
entityActionService.pushEntityActionToRuleEngine(entityId, entity, tenantId, customerId, actionType, null, additionalInfo); |
|||
} |
|||
} |
|||
|
|||
protected <T> T checkNotNull(T reference) throws ThingsboardException { |
|||
return checkNotNull(reference, "Requested item wasn't found!"); |
|||
} |
|||
|
|||
protected <T> T checkNotNull(T reference, String notFoundMessage) throws ThingsboardException { |
|||
if (reference == null) { |
|||
throw new ThingsboardException(notFoundMessage, ThingsboardErrorCode.ITEM_NOT_FOUND); |
|||
} |
|||
return reference; |
|||
} |
|||
|
|||
protected <T> T checkNotNull(Optional<T> reference) throws ThingsboardException { |
|||
return checkNotNull(reference, "Requested item wasn't found!"); |
|||
} |
|||
|
|||
protected <T> T checkNotNull(Optional<T> reference, String notFoundMessage) throws ThingsboardException { |
|||
if (reference.isPresent()) { |
|||
return reference.get(); |
|||
} else { |
|||
throw new ThingsboardException(notFoundMessage, ThingsboardErrorCode.ITEM_NOT_FOUND); |
|||
} |
|||
} |
|||
|
|||
protected ThingsboardException handleException(Exception exception) { |
|||
return handleException(exception, true); |
|||
} |
|||
|
|||
protected ThingsboardException handleException(Exception exception, boolean logException) { |
|||
if (logException && logControllerErrorStackTrace) { |
|||
log.error("Error [{}]", exception.getMessage(), exception); |
|||
} |
|||
|
|||
String cause = ""; |
|||
if (exception.getCause() != null) { |
|||
cause = exception.getCause().getClass().getCanonicalName(); |
|||
} |
|||
|
|||
if (exception instanceof ThingsboardException) { |
|||
return (ThingsboardException) exception; |
|||
} else if (exception instanceof IllegalArgumentException || exception instanceof IncorrectParameterException |
|||
|| exception instanceof DataValidationException || cause.contains("IncorrectParameterException")) { |
|||
return new ThingsboardException(exception.getMessage(), ThingsboardErrorCode.BAD_REQUEST_PARAMS); |
|||
} else if (exception instanceof MessagingException) { |
|||
return new ThingsboardException("Unable to send mail: " + exception.getMessage(), ThingsboardErrorCode.GENERAL); |
|||
} else { |
|||
return new ThingsboardException(exception.getMessage(), exception, ThingsboardErrorCode.GENERAL); |
|||
} |
|||
} |
|||
|
|||
@SuppressWarnings("unchecked") |
|||
protected <I extends EntityId> I emptyId(EntityType entityType) { |
|||
return (I) EntityIdFactory.getByTypeAndUuid(entityType, ModelConstants.NULL_UUID); |
|||
} |
|||
|
|||
protected List<EdgeId> findRelatedEdgeIds(TenantId tenantId, EntityId entityId) { |
|||
if (!edgesEnabled) { |
|||
return null; |
|||
} |
|||
if (EntityType.EDGE.equals(entityId.getEntityType())) { |
|||
return Collections.singletonList(new EdgeId(entityId.getId())); |
|||
} |
|||
PageDataIterableByTenantIdEntityId<EdgeId> relatedEdgeIdsIterator = |
|||
new PageDataIterableByTenantIdEntityId<>(edgeService::findRelatedEdgeIdsByEntityId, tenantId, entityId, DEFAULT_PAGE_SIZE); |
|||
List<EdgeId> result = new ArrayList<>(); |
|||
for (EdgeId edgeId : relatedEdgeIdsIterator) { |
|||
result.add(edgeId); |
|||
} |
|||
return result; |
|||
} |
|||
} |
|||
@ -0,0 +1,362 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy; |
|||
|
|||
import com.fasterxml.jackson.core.JsonProcessingException; |
|||
import com.fasterxml.jackson.databind.ObjectMapper; |
|||
import lombok.RequiredArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.rule.engine.api.msg.DeviceCredentialsUpdateNotificationMsg; |
|||
import org.thingsboard.server.cluster.TbClusterService; |
|||
import org.thingsboard.server.common.data.DataConstants; |
|||
import org.thingsboard.server.common.data.Device; |
|||
import org.thingsboard.server.common.data.EntityType; |
|||
import org.thingsboard.server.common.data.HasName; |
|||
import org.thingsboard.server.common.data.Tenant; |
|||
import org.thingsboard.server.common.data.alarm.Alarm; |
|||
import org.thingsboard.server.common.data.audit.ActionType; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.common.data.edge.EdgeEventActionType; |
|||
import org.thingsboard.server.common.data.edge.EdgeEventType; |
|||
import org.thingsboard.server.common.data.id.CustomerId; |
|||
import org.thingsboard.server.common.data.id.DeviceId; |
|||
import org.thingsboard.server.common.data.id.EdgeId; |
|||
import org.thingsboard.server.common.data.id.EntityId; |
|||
import org.thingsboard.server.common.data.id.RuleChainId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; |
|||
import org.thingsboard.server.common.data.relation.EntityRelation; |
|||
import org.thingsboard.server.common.data.rule.RuleChain; |
|||
import org.thingsboard.server.common.data.rule.RuleChainType; |
|||
import org.thingsboard.server.common.data.security.DeviceCredentials; |
|||
import org.thingsboard.server.common.msg.TbMsg; |
|||
import org.thingsboard.server.common.msg.TbMsgDataType; |
|||
import org.thingsboard.server.common.msg.TbMsgMetaData; |
|||
import org.thingsboard.server.queue.util.TbCoreComponent; |
|||
import org.thingsboard.server.service.action.EntityActionService; |
|||
import org.thingsboard.server.service.gateway_device.GatewayNotificationsService; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
|
|||
import java.util.List; |
|||
|
|||
@Slf4j |
|||
@Service |
|||
@TbCoreComponent |
|||
@RequiredArgsConstructor |
|||
public class DefaultTbNotificationEntityService implements TbNotificationEntityService { |
|||
private static final ObjectMapper json = new ObjectMapper(); |
|||
|
|||
private final EntityActionService entityActionService; |
|||
private final TbClusterService tbClusterService; |
|||
private final GatewayNotificationsService gatewayNotificationsService; |
|||
|
|||
@Override |
|||
public <E extends HasName, I extends EntityId> void notifyEntity(TenantId tenantId, I entityId, E entity, CustomerId customerId, |
|||
ActionType actionType, SecurityUser user, Exception e, |
|||
Object... additionalInfo) { |
|||
logEntityAction(tenantId, entityId, entity, customerId, actionType, user, e, additionalInfo); |
|||
} |
|||
|
|||
@Override |
|||
public <E extends HasName, I extends EntityId> void notifyDeleteEntity(TenantId tenantId, I entityId, E entity, |
|||
CustomerId customerId, ActionType actionType, |
|||
List<EdgeId> relatedEdgeIds, |
|||
SecurityUser user, Object... additionalInfo) { |
|||
logEntityAction(tenantId, entityId, entity, customerId, actionType, user, additionalInfo); |
|||
sendDeleteNotificationMsg(tenantId, entityId, entity, relatedEdgeIds); |
|||
} |
|||
|
|||
public void notifyDeleteAlarm(TenantId tenantId, Alarm alarm, EntityId originatorId, |
|||
CustomerId customerId, |
|||
List<EdgeId> relatedEdgeIds, |
|||
SecurityUser user, |
|||
String body, Object... additionalInfo) { |
|||
logEntityAction(tenantId, originatorId, alarm, customerId, ActionType.DELETED, user, additionalInfo); |
|||
sendAlarmDeleteNotificationMsg(tenantId, alarm, relatedEdgeIds, body); |
|||
} |
|||
|
|||
@Override |
|||
public void notifyDeleteRuleChain(TenantId tenantId, RuleChain ruleChain, |
|||
List<EdgeId> relatedEdgeIds, SecurityUser user) { |
|||
RuleChainId ruleChainId = ruleChain.getId(); |
|||
logEntityAction(tenantId, ruleChainId, ruleChain, null, ActionType.DELETED, user, null, ruleChainId.toString()); |
|||
if (RuleChainType.EDGE.equals(ruleChain.getType())) { |
|||
sendDeleteNotificationMsg(tenantId, ruleChainId, relatedEdgeIds, null); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public <I extends EntityId> void notifySendMsgToEdgeService(TenantId tenantId, I entityId, EdgeEventActionType edgeEventActionType) { |
|||
sendEntityNotificationMsg(tenantId, entityId, edgeEventActionType); |
|||
} |
|||
|
|||
@Override |
|||
public <E extends HasName, I extends EntityId> void notifyAssignOrUnassignEntityToCustomer(TenantId tenantId, I entityId, |
|||
CustomerId customerId, E entity, |
|||
ActionType actionType, |
|||
EdgeEventActionType edgeActionType, |
|||
SecurityUser user, boolean sendToEdge, |
|||
Object... additionalInfo) { |
|||
logEntityAction(tenantId, entityId, entity, customerId, actionType, user, additionalInfo); |
|||
|
|||
if (sendToEdge) { |
|||
sendEntityAssignToCustomerNotificationMsg(tenantId, entityId, customerId, edgeActionType); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public <E extends HasName, I extends EntityId> void notifyAssignOrUnassignEntityToEdge(TenantId tenantId, I entityId, |
|||
CustomerId customerId, EdgeId edgeId, |
|||
E entity, ActionType actionType, |
|||
SecurityUser user, Object... additionalInfo) { |
|||
logEntityAction(tenantId, entityId, entity, customerId, actionType, user, additionalInfo); |
|||
sendEntityAssignToEdgeNotificationMsg(tenantId, edgeId, entityId, edgeTypeByActionType(actionType)); |
|||
} |
|||
|
|||
@Override |
|||
public void notifyCreateOruUpdateTenant(Tenant tenant, ComponentLifecycleEvent event) { |
|||
tbClusterService.onTenantChange(tenant, null); |
|||
tbClusterService.broadcastEntityStateChangeEvent(tenant.getId(), tenant.getId(), event); |
|||
} |
|||
|
|||
@Override |
|||
public void notifyDeleteTenant(Tenant tenant) { |
|||
tbClusterService.onTenantDelete(tenant, null); |
|||
tbClusterService.broadcastEntityStateChangeEvent(tenant.getId(), tenant.getId(), ComponentLifecycleEvent.DELETED); |
|||
} |
|||
|
|||
@Override |
|||
public void notifyCreateOrUpdateDevice(TenantId tenantId, DeviceId deviceId, CustomerId customerId, |
|||
Device device, Device oldDevice, ActionType actionType, |
|||
SecurityUser user, Object... additionalInfo) { |
|||
tbClusterService.onDeviceUpdated(device, oldDevice); |
|||
logEntityAction(tenantId, deviceId, device, customerId, actionType, user, additionalInfo); |
|||
} |
|||
|
|||
@Override |
|||
public void notifyDeleteDevice(TenantId tenantId, DeviceId deviceId, CustomerId customerId, Device device, |
|||
List<EdgeId> relatedEdgeIds, SecurityUser user, Object... additionalInfo) { |
|||
gatewayNotificationsService.onDeviceDeleted(device); |
|||
tbClusterService.onDeviceDeleted(device, null); |
|||
|
|||
notifyDeleteEntity(tenantId, deviceId, device, customerId, ActionType.DELETED, relatedEdgeIds, user, additionalInfo); |
|||
} |
|||
|
|||
@Override |
|||
public void notifyUpdateDeviceCredentials(TenantId tenantId, DeviceId deviceId, CustomerId customerId, Device device, |
|||
DeviceCredentials deviceCredentials, SecurityUser user) { |
|||
tbClusterService.pushMsgToCore(new DeviceCredentialsUpdateNotificationMsg(tenantId, deviceCredentials.getDeviceId(), deviceCredentials), null); |
|||
sendEntityNotificationMsg(tenantId, deviceId, EdgeEventActionType.CREDENTIALS_UPDATED); |
|||
logEntityAction(tenantId, deviceId, device, customerId, ActionType.CREDENTIALS_UPDATED, user, deviceCredentials); |
|||
} |
|||
|
|||
@Override |
|||
public void notifyAssignDeviceToTenant(TenantId tenantId, TenantId newTenantId, DeviceId deviceId, CustomerId customerId, |
|||
Device device, Tenant tenant, SecurityUser user, Object... additionalInfo) { |
|||
logEntityAction(tenantId, deviceId, device, customerId, ActionType.ASSIGNED_TO_TENANT, user, additionalInfo); |
|||
pushAssignedFromNotification(tenant, newTenantId, device); |
|||
} |
|||
|
|||
@Override |
|||
public <E extends HasName, I extends EntityId> void notifyCreateOrUpdateEntity(TenantId tenantId, I entityId, E entity, CustomerId customerId, ActionType actionType, SecurityUser user, Object... additionalInfo) { |
|||
logEntityAction(tenantId, entityId, entity, customerId, actionType, user, additionalInfo); |
|||
if (actionType == ActionType.UPDATED) { |
|||
sendEntityNotificationMsg(tenantId, entityId, EdgeEventActionType.UPDATED); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void notifyEdge(TenantId tenantId, EdgeId edgeId, CustomerId customerId, Edge edge, ActionType actionType, |
|||
SecurityUser user, Object... additionalInfo) { |
|||
ComponentLifecycleEvent lifecycleEvent; |
|||
EdgeEventActionType edgeEventActionType = null; |
|||
switch (actionType) { |
|||
case ADDED: |
|||
lifecycleEvent = ComponentLifecycleEvent.CREATED; |
|||
break; |
|||
case UPDATED: |
|||
lifecycleEvent = ComponentLifecycleEvent.UPDATED; |
|||
break; |
|||
case ASSIGNED_TO_CUSTOMER: |
|||
lifecycleEvent = ComponentLifecycleEvent.UPDATED; |
|||
edgeEventActionType = EdgeEventActionType.ASSIGNED_TO_CUSTOMER; |
|||
break; |
|||
case UNASSIGNED_FROM_CUSTOMER: |
|||
lifecycleEvent = ComponentLifecycleEvent.UPDATED; |
|||
edgeEventActionType = EdgeEventActionType.UNASSIGNED_FROM_CUSTOMER; |
|||
break; |
|||
case DELETED: |
|||
lifecycleEvent = ComponentLifecycleEvent.DELETED; |
|||
break; |
|||
default: |
|||
throw new IllegalArgumentException("Unknown actionType: " + actionType); |
|||
} |
|||
|
|||
tbClusterService.broadcastEntityStateChangeEvent(tenantId, edgeId, lifecycleEvent); |
|||
logEntityAction(tenantId, edgeId, edge, customerId, actionType, user, additionalInfo); |
|||
|
|||
//Send notification to edge
|
|||
if (edgeEventActionType != null) { |
|||
sendEntityAssignToCustomerNotificationMsg(tenantId, edgeId, customerId, edgeEventActionType); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void notifyCreateOrUpdateAlarm(Alarm alarm, ActionType actionType, SecurityUser user, Object... additionalInfo) { |
|||
logEntityAction(alarm.getTenantId(), alarm.getOriginator(), alarm, alarm.getCustomerId(), actionType, user, additionalInfo); |
|||
sendEntityNotificationMsg(alarm.getTenantId(), alarm.getId(), edgeTypeByActionType(actionType)); |
|||
} |
|||
|
|||
@Override |
|||
public <E extends HasName, I extends EntityId> void notifyCreateOrUpdateOrDelete(TenantId tenantId, CustomerId customerId, |
|||
I entityId, E entity, SecurityUser user, |
|||
ActionType actionType, boolean sendNotifyMsgToEdge, Exception e, |
|||
Object... additionalInfo) { |
|||
notifyEntity(tenantId, entityId, entity, customerId, actionType, user, e, additionalInfo); |
|||
if (sendNotifyMsgToEdge) { |
|||
sendEntityNotificationMsg(tenantId, entityId, edgeTypeByActionType(actionType)); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void notifyCreateOrUpdateOrDeleteRelation(TenantId tenantId, CustomerId customerId, |
|||
EntityRelation relation, SecurityUser user, |
|||
ActionType actionType, Exception e, |
|||
Object... additionalInfo) { |
|||
notifyEntity(tenantId, relation.getFrom(), null, customerId, actionType, user, e, additionalInfo); |
|||
notifyEntity(tenantId, relation.getTo(), null, customerId, actionType, user, e, additionalInfo); |
|||
if (e == null) { |
|||
try { |
|||
if (!relation.getFrom().getEntityType().equals(EntityType.EDGE) && |
|||
!relation.getTo().getEntityType().equals(EntityType.EDGE)) { |
|||
sendNotificationMsgToEdgeService(tenantId, null, null, json.writeValueAsString(relation), |
|||
EdgeEventType.RELATION, edgeTypeByActionType(actionType)); |
|||
} |
|||
} catch (Exception e1) { |
|||
log.warn("Failed to push relation to core: {}", relation, e1); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private <E extends HasName, I extends EntityId> void logEntityAction(TenantId tenantId, I entityId, E entity, CustomerId customerId, |
|||
ActionType actionType, SecurityUser user, Object... additionalInfo) { |
|||
logEntityAction(tenantId, entityId, entity, customerId, actionType, user, null, additionalInfo); |
|||
} |
|||
|
|||
private <E extends HasName, I extends EntityId> void logEntityAction(TenantId tenantId, I entityId, E entity, CustomerId customerId, |
|||
ActionType actionType, SecurityUser user, Exception e, Object... additionalInfo) { |
|||
if (user != null) { |
|||
entityActionService.logEntityAction(user, entityId, entity, customerId, actionType, e, additionalInfo); |
|||
} else if (e == null) { |
|||
entityActionService.pushEntityActionToRuleEngine(entityId, entity, tenantId, customerId, actionType, null, additionalInfo); |
|||
} |
|||
} |
|||
|
|||
private void sendEntityNotificationMsg(TenantId tenantId, EntityId entityId, EdgeEventActionType action) { |
|||
sendNotificationMsgToEdgeService(tenantId, null, entityId, null, null, action); |
|||
} |
|||
|
|||
private void sendEntityAssignToCustomerNotificationMsg(TenantId tenantId, EntityId entityId, CustomerId customerId, EdgeEventActionType action) { |
|||
try { |
|||
sendNotificationMsgToEdgeService(tenantId, null, entityId, json.writeValueAsString(customerId), null, action); |
|||
} catch (Exception e) { |
|||
log.warn("Failed to push assign/unassign to/from customer to core: {}", customerId, e); |
|||
} |
|||
} |
|||
|
|||
protected void sendAlarmDeleteNotificationMsg(TenantId tenantId, Alarm alarm, List<EdgeId> edgeIds, String body) { |
|||
try { |
|||
sendDeleteNotificationMsg(tenantId, alarm.getId(), edgeIds, body); |
|||
} catch (Exception e) { |
|||
log.warn("Failed to push delete msg to core: {}", alarm, e); |
|||
} |
|||
} |
|||
|
|||
protected <E extends HasName, I extends EntityId> void sendDeleteNotificationMsg(TenantId tenantId, I entityId, E entity, |
|||
List<EdgeId> edgeIds) { |
|||
try { |
|||
sendDeleteNotificationMsg(tenantId, entityId, edgeIds, null); |
|||
} catch (Exception e) { |
|||
log.warn("Failed to push delete msg to core: {}", entity, e); |
|||
} |
|||
} |
|||
|
|||
private void sendDeleteNotificationMsg(TenantId tenantId, EntityId entityId, List<EdgeId> edgeIds, String body) { |
|||
if (edgeIds != null && !edgeIds.isEmpty()) { |
|||
for (EdgeId edgeId : edgeIds) { |
|||
sendNotificationMsgToEdgeService(tenantId, edgeId, entityId, body, null, EdgeEventActionType.DELETED); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private void sendEntityAssignToEdgeNotificationMsg(TenantId tenantId, EdgeId edgeId, EntityId entityId, EdgeEventActionType action) { |
|||
sendNotificationMsgToEdgeService(tenantId, edgeId, entityId, null, null, action); |
|||
} |
|||
|
|||
private void sendNotificationMsgToEdgeService(TenantId tenantId, EdgeId edgeId, EntityId entityId, String body, EdgeEventType type, EdgeEventActionType action) { |
|||
tbClusterService.sendNotificationMsgToEdgeService(tenantId, edgeId, entityId, body, type, action); |
|||
} |
|||
|
|||
private void pushAssignedFromNotification(Tenant currentTenant, TenantId newTenantId, Device assignedDevice) { |
|||
String data = entityToStr(assignedDevice); |
|||
if (data != null) { |
|||
TbMsg tbMsg = TbMsg.newMsg(DataConstants.ENTITY_ASSIGNED_FROM_TENANT, assignedDevice.getId(), assignedDevice.getCustomerId(), getMetaDataForAssignedFrom(currentTenant), TbMsgDataType.JSON, data); |
|||
tbClusterService.pushMsgToRuleEngine(newTenantId, assignedDevice.getId(), tbMsg, null); |
|||
} |
|||
} |
|||
|
|||
private TbMsgMetaData getMetaDataForAssignedFrom(Tenant tenant) { |
|||
TbMsgMetaData metaData = new TbMsgMetaData(); |
|||
metaData.putValue("assignedFromTenantId", tenant.getId().getId().toString()); |
|||
metaData.putValue("assignedFromTenantName", tenant.getName()); |
|||
return metaData; |
|||
} |
|||
|
|||
private <E extends HasName> String entityToStr(E entity) { |
|||
try { |
|||
return json.writeValueAsString(json.valueToTree(entity)); |
|||
} catch (JsonProcessingException e) { |
|||
log.warn("[{}] Failed to convert entity to string!", entity, e); |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
private EdgeEventActionType edgeTypeByActionType(ActionType actionType) { |
|||
switch (actionType) { |
|||
case ADDED: |
|||
return EdgeEventActionType.ADDED; |
|||
case UPDATED: |
|||
return EdgeEventActionType.UPDATED; |
|||
case ALARM_ACK: |
|||
return EdgeEventActionType.ALARM_ACK; |
|||
case ALARM_CLEAR: |
|||
return EdgeEventActionType.ALARM_CLEAR; |
|||
case DELETED: |
|||
return EdgeEventActionType.DELETED; |
|||
case RELATION_ADD_OR_UPDATE: |
|||
return EdgeEventActionType.RELATION_ADD_OR_UPDATE; |
|||
case RELATION_DELETED: |
|||
return EdgeEventActionType.RELATION_DELETED; |
|||
case ASSIGNED_TO_EDGE: |
|||
return EdgeEventActionType.ASSIGNED_TO_EDGE; |
|||
case UNASSIGNED_FROM_EDGE: |
|||
return EdgeEventActionType.UNASSIGNED_FROM_EDGE; |
|||
default: |
|||
return null; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,105 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy; |
|||
|
|||
import org.thingsboard.server.common.data.Device; |
|||
import org.thingsboard.server.common.data.HasName; |
|||
import org.thingsboard.server.common.data.Tenant; |
|||
import org.thingsboard.server.common.data.alarm.Alarm; |
|||
import org.thingsboard.server.common.data.audit.ActionType; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.common.data.edge.EdgeEventActionType; |
|||
import org.thingsboard.server.common.data.id.CustomerId; |
|||
import org.thingsboard.server.common.data.id.DeviceId; |
|||
import org.thingsboard.server.common.data.id.EdgeId; |
|||
import org.thingsboard.server.common.data.id.EntityId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; |
|||
import org.thingsboard.server.common.data.relation.EntityRelation; |
|||
import org.thingsboard.server.common.data.rule.RuleChain; |
|||
import org.thingsboard.server.common.data.security.DeviceCredentials; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
|
|||
import java.util.List; |
|||
|
|||
public interface TbNotificationEntityService { |
|||
|
|||
<E extends HasName, I extends EntityId> void notifyEntity(TenantId tenantId, I entityId, E entity, CustomerId customerId, |
|||
ActionType actionType, SecurityUser user, Exception e, |
|||
Object... additionalInfo); |
|||
|
|||
<E extends HasName, I extends EntityId> void notifyCreateOrUpdateEntity(TenantId tenantId, I entityId, E entity, |
|||
CustomerId customerId, ActionType actionType, |
|||
SecurityUser user, Object... additionalInfo); |
|||
|
|||
<E extends HasName, I extends EntityId> void notifyDeleteEntity(TenantId tenantId, I entityId, E entity, |
|||
CustomerId customerId, ActionType actionType, |
|||
List<EdgeId> relatedEdgeIds, |
|||
SecurityUser user, Object... additionalInfo); |
|||
|
|||
void notifyDeleteAlarm(TenantId tenantId, Alarm alarm, EntityId originatorId, |
|||
CustomerId customerId, List<EdgeId> relatedEdgeIds, |
|||
SecurityUser user, String body, Object... additionalInfo); |
|||
|
|||
void notifyDeleteRuleChain(TenantId tenantId, RuleChain ruleChain, |
|||
List<EdgeId> relatedEdgeIds, SecurityUser user); |
|||
|
|||
<I extends EntityId> void notifySendMsgToEdgeService(TenantId tenantId, I entityId, EdgeEventActionType edgeEventActionType); |
|||
|
|||
<E extends HasName, I extends EntityId> void notifyAssignOrUnassignEntityToCustomer(TenantId tenantId, I entityId, |
|||
CustomerId customerId, E entity, |
|||
ActionType actionType, |
|||
EdgeEventActionType edgeActionType, |
|||
SecurityUser user, boolean sendToEdge, |
|||
Object... additionalInfo); |
|||
|
|||
<E extends HasName, I extends EntityId> void notifyAssignOrUnassignEntityToEdge(TenantId tenantId, I entityId, |
|||
CustomerId customerId, EdgeId edgeId, |
|||
E entity, ActionType actionType, |
|||
SecurityUser user, Object... additionalInfo); |
|||
|
|||
void notifyCreateOruUpdateTenant(Tenant tenant, ComponentLifecycleEvent event); |
|||
|
|||
|
|||
void notifyDeleteTenant(Tenant tenant); |
|||
|
|||
void notifyCreateOrUpdateDevice(TenantId tenantId, DeviceId deviceId, CustomerId customerId, Device device, |
|||
Device oldDevice, ActionType actionType, SecurityUser user, Object... additionalInfo); |
|||
|
|||
void notifyDeleteDevice(TenantId tenantId, DeviceId deviceId, CustomerId customerId, Device device, |
|||
List<EdgeId> relatedEdgeIds, SecurityUser user, Object... additionalInfo); |
|||
|
|||
void notifyUpdateDeviceCredentials(TenantId tenantId, DeviceId deviceId, CustomerId customerId, Device device, |
|||
DeviceCredentials deviceCredentials, SecurityUser user); |
|||
|
|||
void notifyAssignDeviceToTenant(TenantId tenantId, TenantId newTenantId, DeviceId deviceId, CustomerId customerId, |
|||
Device device, Tenant tenant, SecurityUser user, Object... additionalInfo); |
|||
|
|||
void notifyEdge(TenantId tenantId, EdgeId edgeId, CustomerId customerId, Edge edge, ActionType actionType, |
|||
SecurityUser user, Object... additionalInfo); |
|||
|
|||
void notifyCreateOrUpdateAlarm(Alarm alarm, ActionType actionType, SecurityUser user, Object... additionalInfo); |
|||
|
|||
<E extends HasName, I extends EntityId> void notifyCreateOrUpdateOrDelete(TenantId tenantId, CustomerId customerId, |
|||
I entityId, E entity, SecurityUser user, |
|||
ActionType actionType, boolean sendNotifyMsgToEdge, Exception e, |
|||
Object... additionalInfo); |
|||
|
|||
void notifyCreateOrUpdateOrDeleteRelation(TenantId tenantId, CustomerId customerId, |
|||
EntityRelation relation, SecurityUser user, |
|||
ActionType actionType, Exception e, |
|||
Object... additionalInfo); |
|||
} |
|||
@ -0,0 +1,90 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy.alarm; |
|||
|
|||
import lombok.AllArgsConstructor; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.common.util.JacksonUtil; |
|||
import org.thingsboard.server.common.data.EntityType; |
|||
import org.thingsboard.server.common.data.alarm.Alarm; |
|||
import org.thingsboard.server.common.data.alarm.AlarmStatus; |
|||
import org.thingsboard.server.common.data.audit.ActionType; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.id.EdgeId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.queue.util.TbCoreComponent; |
|||
import org.thingsboard.server.service.entitiy.AbstractTbEntityService; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
|
|||
import java.util.List; |
|||
|
|||
@Service |
|||
@TbCoreComponent |
|||
@AllArgsConstructor |
|||
public class DefaultTbAlarmService extends AbstractTbEntityService implements TbAlarmService { |
|||
|
|||
@Override |
|||
public Alarm save(Alarm alarm, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = alarm.getId() == null ? ActionType.ADDED : ActionType.UPDATED; |
|||
TenantId tenantId = alarm.getTenantId(); |
|||
try { |
|||
Alarm savedAlarm = checkNotNull(alarmService.createOrUpdateAlarm(alarm).getAlarm()); |
|||
notificationEntityService.notifyCreateOrUpdateAlarm(savedAlarm, actionType, user); |
|||
return savedAlarm; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ALARM), alarm, null, actionType, user, e); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void ack(Alarm alarm, SecurityUser user) throws ThingsboardException { |
|||
try { |
|||
long ackTs = System.currentTimeMillis(); |
|||
alarmService.ackAlarm(user.getTenantId(), alarm.getId(), ackTs).get(); |
|||
alarm.setAckTs(ackTs); |
|||
alarm.setStatus(alarm.getStatus().isCleared() ? AlarmStatus.CLEARED_ACK : AlarmStatus.ACTIVE_ACK); |
|||
notificationEntityService.notifyCreateOrUpdateAlarm(alarm, ActionType.ALARM_ACK, user); |
|||
} catch (Exception e) { |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void clear(Alarm alarm, SecurityUser user) throws ThingsboardException { |
|||
try { |
|||
long clearTs = System.currentTimeMillis(); |
|||
alarmService.clearAlarm(user.getTenantId(), alarm.getId(), null, clearTs).get(); |
|||
alarm.setClearTs(clearTs); |
|||
alarm.setStatus(alarm.getStatus().isAck() ? AlarmStatus.CLEARED_ACK : AlarmStatus.CLEARED_UNACK); |
|||
notificationEntityService.notifyCreateOrUpdateAlarm(alarm, ActionType.ALARM_CLEAR, user); |
|||
} catch (Exception e) { |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Boolean delete(Alarm alarm, SecurityUser user) throws ThingsboardException { |
|||
try { |
|||
List<EdgeId> relatedEdgeIds = findRelatedEdgeIds(user.getTenantId(), alarm.getOriginator()); |
|||
notificationEntityService.notifyDeleteAlarm(user.getTenantId(), alarm, alarm.getOriginator(), user.getCustomerId(), |
|||
relatedEdgeIds, user, JacksonUtil.OBJECT_MAPPER.writeValueAsString(alarm)); |
|||
return alarmService.deleteAlarm(user.getTenantId(), alarm.getId()).isSuccessful(); |
|||
} catch (Exception e) { |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy.alarm; |
|||
|
|||
import org.thingsboard.server.common.data.alarm.Alarm; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
|
|||
public interface TbAlarmService { |
|||
|
|||
Alarm save(Alarm entity, SecurityUser user) throws ThingsboardException; |
|||
|
|||
void ack(Alarm alarm, SecurityUser user) throws ThingsboardException; |
|||
|
|||
void clear(Alarm alarm, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Boolean delete(Alarm alarm, SecurityUser user) throws ThingsboardException; |
|||
} |
|||
@ -0,0 +1,165 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy.asset; |
|||
|
|||
import com.google.common.util.concurrent.ListenableFuture; |
|||
import lombok.AllArgsConstructor; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.common.data.Customer; |
|||
import org.thingsboard.server.common.data.EntityType; |
|||
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; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.id.AssetId; |
|||
import org.thingsboard.server.common.data.id.CustomerId; |
|||
import org.thingsboard.server.common.data.id.EdgeId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.queue.util.TbCoreComponent; |
|||
import org.thingsboard.server.service.entitiy.AbstractTbEntityService; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
|
|||
import java.util.List; |
|||
|
|||
@Service |
|||
@TbCoreComponent |
|||
@AllArgsConstructor |
|||
public class DefaultTbAssetService extends AbstractTbEntityService implements TbAssetService { |
|||
|
|||
@Override |
|||
public Asset save(Asset asset, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = asset.getId() == null ? ActionType.ADDED : ActionType.UPDATED; |
|||
TenantId tenantId = asset.getTenantId(); |
|||
try { |
|||
Asset savedAsset = checkNotNull(assetService.saveAsset(asset)); |
|||
notificationEntityService.notifyCreateOrUpdateEntity(tenantId, savedAsset.getId(), asset, savedAsset.getCustomerId(), actionType, user); |
|||
return savedAsset; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ASSET), asset, null, actionType, user, e); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public ListenableFuture<Void> delete(Asset asset, SecurityUser user) throws ThingsboardException { |
|||
TenantId tenantId = asset.getTenantId(); |
|||
AssetId assetId = asset.getId(); |
|||
try { |
|||
List<EdgeId> relatedEdgeIds = findRelatedEdgeIds(tenantId, assetId); |
|||
assetService.deleteAsset(tenantId, assetId); |
|||
notificationEntityService.notifyDeleteEntity(tenantId, assetId, asset, asset.getCustomerId(), ActionType.DELETED, |
|||
relatedEdgeIds, user, assetId.toString()); |
|||
|
|||
return removeAlarmsByEntityId(tenantId, assetId); |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ASSET), null, null, |
|||
ActionType.DELETED, user, e, assetId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Asset assignAssetToCustomer(TenantId tenantId, AssetId assetId, Customer customer, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.ASSIGNED_TO_CUSTOMER; |
|||
CustomerId customerId = customer.getId(); |
|||
try { |
|||
Asset savedAsset = checkNotNull(assetService.assignAssetToCustomer(tenantId, assetId, customerId)); |
|||
notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, assetId, customerId, savedAsset, |
|||
actionType, EdgeEventActionType.ASSIGNED_TO_CUSTOMER, user, true, customerId.toString(), customer.getName()); |
|||
|
|||
return savedAsset; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ASSET), null, null, |
|||
actionType, user, e, assetId.toString(), customerId.toString()); |
|||
|
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Asset unassignAssetToCustomer(TenantId tenantId, AssetId assetId, Customer customer, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.UNASSIGNED_FROM_CUSTOMER; |
|||
try { |
|||
Asset savedAsset = checkNotNull(assetService.unassignAssetFromCustomer(tenantId, assetId)); |
|||
CustomerId customerId = customer.getId(); |
|||
|
|||
notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, assetId, customerId, savedAsset, |
|||
actionType, EdgeEventActionType.UNASSIGNED_FROM_CUSTOMER, user, |
|||
true, customerId.toString(), customer.getName()); |
|||
|
|||
return savedAsset; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ASSET), null, null, |
|||
actionType, user, e, assetId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Asset assignAssetToPublicCustomer(TenantId tenantId, AssetId assetId, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.ASSIGNED_TO_CUSTOMER; |
|||
try { |
|||
Customer publicCustomer = customerService.findOrCreatePublicCustomer(tenantId); |
|||
Asset savedAsset = checkNotNull(assetService.assignAssetToCustomer(tenantId, assetId, publicCustomer.getId())); |
|||
|
|||
notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, assetId, savedAsset.getCustomerId(), savedAsset, |
|||
actionType, null, user, false, actionType.toString(), |
|||
publicCustomer.getId().toString(), publicCustomer.getName()); |
|||
|
|||
return savedAsset; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ASSET), null, null, |
|||
actionType, user, e, assetId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Asset assignAssetToEdge(TenantId tenantId, AssetId assetId, Edge edge, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.ASSIGNED_TO_EDGE; |
|||
EdgeId edgeId = edge.getId(); |
|||
try { |
|||
Asset savedAsset = checkNotNull(assetService.assignAssetToEdge(tenantId, assetId, edgeId)); |
|||
notificationEntityService.notifyAssignOrUnassignEntityToEdge(tenantId, assetId, savedAsset.getCustomerId(), |
|||
edgeId, savedAsset, actionType, user, assetId.toString(), edgeId.toString(), edge.getName()); |
|||
|
|||
return savedAsset; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ASSET), null, null, |
|||
actionType, user, e, assetId.toString(), edgeId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Asset unassignAssetFromEdge(TenantId tenantId, Asset asset, Edge edge, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.UNASSIGNED_FROM_EDGE; |
|||
AssetId assetId = asset.getId(); |
|||
EdgeId edgeId = edge.getId(); |
|||
try { |
|||
Asset savedAsset = checkNotNull(assetService.unassignAssetFromEdge(tenantId, assetId, edgeId)); |
|||
|
|||
notificationEntityService.notifyAssignOrUnassignEntityToEdge(tenantId, assetId, asset.getCustomerId(), |
|||
edgeId, asset, actionType, user, assetId.toString(), edgeId.toString(), edge.getName()); |
|||
return savedAsset; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ASSET), null, null, |
|||
actionType, user, e, assetId.toString(), edgeId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,43 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy.asset; |
|||
|
|||
import com.google.common.util.concurrent.ListenableFuture; |
|||
import org.thingsboard.server.common.data.Customer; |
|||
import org.thingsboard.server.common.data.asset.Asset; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.id.AssetId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
|
|||
public interface TbAssetService { |
|||
|
|||
Asset save(Asset asset, SecurityUser user) throws ThingsboardException; |
|||
|
|||
ListenableFuture<Void> delete(Asset asset, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Asset assignAssetToCustomer(TenantId tenantId, AssetId assetId, Customer customer, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Asset unassignAssetToCustomer(TenantId tenantId, AssetId assetId, Customer customer, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Asset assignAssetToPublicCustomer(TenantId tenantId, AssetId assetId, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Asset assignAssetToEdge(TenantId tenantId, AssetId assetId, Edge edge, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Asset unassignAssetFromEdge(TenantId tenantId, Asset asset, Edge edge, SecurityUser user) throws ThingsboardException; |
|||
|
|||
} |
|||
@ -0,0 +1,71 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy.customer; |
|||
|
|||
import lombok.AllArgsConstructor; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.common.data.Customer; |
|||
import org.thingsboard.server.common.data.EntityType; |
|||
import org.thingsboard.server.common.data.audit.ActionType; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.id.CustomerId; |
|||
import org.thingsboard.server.common.data.id.EdgeId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; |
|||
import org.thingsboard.server.queue.util.TbCoreComponent; |
|||
import org.thingsboard.server.service.entitiy.AbstractTbEntityService; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
|
|||
import java.util.List; |
|||
|
|||
@Service |
|||
@TbCoreComponent |
|||
@AllArgsConstructor |
|||
public class DefaultTbCustomerService extends AbstractTbEntityService implements TbCustomerService { |
|||
|
|||
@Override |
|||
public Customer save(Customer customer, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = customer.getId() == null ? ActionType.ADDED : ActionType.UPDATED; |
|||
TenantId tenantId = customer.getTenantId(); |
|||
CustomerId customerId = customer.getId(); |
|||
try { |
|||
Customer savedCustomer = checkNotNull(customerService.saveCustomer(customer)); |
|||
notificationEntityService.notifyCreateOrUpdateEntity(tenantId, savedCustomer.getId(), savedCustomer, customerId, actionType, user); |
|||
return savedCustomer; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.CUSTOMER), customer, null, actionType, user, e); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
|
|||
@Override |
|||
public void delete(Customer customer, SecurityUser user) throws ThingsboardException { |
|||
TenantId tenantId = customer.getTenantId(); |
|||
CustomerId customerId = customer.getId(); |
|||
try { |
|||
List<EdgeId> relatedEdgeIds = findRelatedEdgeIds(tenantId, customer.getId()); |
|||
customerService.deleteCustomer(tenantId, customerId); |
|||
notificationEntityService.notifyDeleteEntity(tenantId, customer.getId(), customer, customerId, |
|||
ActionType.DELETED, relatedEdgeIds, user, customerId.toString()); |
|||
tbClusterService.broadcastEntityStateChangeEvent(tenantId, customer.getId(), ComponentLifecycleEvent.DELETED); |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.CUSTOMER), null, null, |
|||
ActionType.DELETED, user, e, customer.getId().toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy.customer; |
|||
|
|||
import org.thingsboard.server.common.data.Customer; |
|||
import org.thingsboard.server.service.entitiy.SimpleTbEntityService; |
|||
|
|||
public interface TbCustomerService extends SimpleTbEntityService<Customer> { |
|||
|
|||
} |
|||
@ -0,0 +1,275 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy.dashboard; |
|||
|
|||
import lombok.AllArgsConstructor; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.common.data.Customer; |
|||
import org.thingsboard.server.common.data.Dashboard; |
|||
import org.thingsboard.server.common.data.EntityType; |
|||
import org.thingsboard.server.common.data.ShortCustomerInfo; |
|||
import org.thingsboard.server.common.data.audit.ActionType; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.common.data.edge.EdgeEventActionType; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.id.CustomerId; |
|||
import org.thingsboard.server.common.data.id.DashboardId; |
|||
import org.thingsboard.server.common.data.id.EdgeId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.queue.util.TbCoreComponent; |
|||
import org.thingsboard.server.service.entitiy.AbstractTbEntityService; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
|
|||
import java.util.HashSet; |
|||
import java.util.List; |
|||
import java.util.Set; |
|||
|
|||
@Service |
|||
@TbCoreComponent |
|||
@AllArgsConstructor |
|||
public class DefaultTbDashboardService extends AbstractTbEntityService implements TbDashboardService { |
|||
|
|||
@Override |
|||
public Dashboard save(Dashboard dashboard, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = dashboard.getId() == null ? ActionType.ADDED : ActionType.UPDATED; |
|||
TenantId tenantId = dashboard.getTenantId(); |
|||
try { |
|||
Dashboard savedDashboard = checkNotNull(dashboardService.saveDashboard(dashboard)); |
|||
notificationEntityService.notifyCreateOrUpdateEntity(tenantId, savedDashboard.getId(), savedDashboard, |
|||
null, actionType, user); |
|||
return savedDashboard; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DASHBOARD), dashboard, null, actionType, user, e); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void delete(Dashboard dashboard, SecurityUser user) throws ThingsboardException { |
|||
DashboardId dashboardId = dashboard.getId(); |
|||
TenantId tenantId = dashboard.getTenantId(); |
|||
try { |
|||
List<EdgeId> relatedEdgeIds = findRelatedEdgeIds(tenantId, dashboardId); |
|||
dashboardService.deleteDashboard(tenantId, dashboardId); |
|||
notificationEntityService.notifyDeleteEntity(tenantId, dashboardId, dashboard, null, |
|||
ActionType.DELETED, relatedEdgeIds, user, dashboardId.toString()); |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DASHBOARD), null, null, |
|||
ActionType.DELETED, user, e, dashboardId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Dashboard assignDashboardToCustomer(DashboardId dashboardId, Customer customer, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.ASSIGNED_TO_CUSTOMER; |
|||
CustomerId customerId = customer.getId(); |
|||
try { |
|||
Dashboard savedDashboard = checkNotNull(dashboardService.assignDashboardToCustomer(user.getTenantId(), dashboardId, customerId)); |
|||
notificationEntityService.notifyAssignOrUnassignEntityToCustomer(user.getTenantId(), dashboardId, customerId, savedDashboard, |
|||
actionType, EdgeEventActionType.ASSIGNED_TO_CUSTOMER, user, true, customerId.toString(), customer.getName()); |
|||
return savedDashboard; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(user.getTenantId(), emptyId(EntityType.DASHBOARD), null, null, |
|||
actionType, user, e, dashboardId.toString(), customerId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Dashboard assignDashboardToPublicCustomer(DashboardId dashboardId, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.ASSIGNED_TO_CUSTOMER; |
|||
try { |
|||
Customer publicCustomer = customerService.findOrCreatePublicCustomer(user.getTenantId()); |
|||
Dashboard savedDashboard = checkNotNull(dashboardService.assignDashboardToCustomer(user.getTenantId(), dashboardId, publicCustomer.getId())); |
|||
notificationEntityService.notifyAssignOrUnassignEntityToCustomer(user.getTenantId(), dashboardId, user.getCustomerId(), savedDashboard, |
|||
actionType, null, user, false, dashboardId.toString(), |
|||
publicCustomer.getId().toString(), publicCustomer.getName()); |
|||
return savedDashboard; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(user.getTenantId(), emptyId(EntityType.DASHBOARD), null, null, |
|||
actionType, user, e, dashboardId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Dashboard unassignDashboardFromPublicCustomer(Dashboard dashboard, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.UNASSIGNED_FROM_CUSTOMER; |
|||
try { |
|||
Customer publicCustomer = customerService.findOrCreatePublicCustomer(dashboard.getTenantId()); |
|||
Dashboard savedDashboard = checkNotNull(dashboardService.unassignDashboardFromCustomer(user.getTenantId(), dashboard.getId(), publicCustomer.getId())); |
|||
notificationEntityService.notifyAssignOrUnassignEntityToCustomer(user.getTenantId(), dashboard.getId(), user.getCustomerId(), dashboard, |
|||
actionType, null, user, false, dashboard.getId().toString(), |
|||
publicCustomer.getId().toString(), publicCustomer.getName()); |
|||
return savedDashboard; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(user.getTenantId(), emptyId(EntityType.DASHBOARD), null, null, |
|||
actionType, user, e, dashboard.getId().toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Dashboard updateDashboardCustomers(Dashboard dashboard, Set<CustomerId> customerIds, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.ASSIGNED_TO_CUSTOMER; |
|||
TenantId tenantId = user.getTenantId(); |
|||
try { |
|||
Set<CustomerId> addedCustomerIds = new HashSet<>(); |
|||
Set<CustomerId> removedCustomerIds = new HashSet<>(); |
|||
for (CustomerId customerId : customerIds) { |
|||
if (!dashboard.isAssignedToCustomer(customerId)) { |
|||
addedCustomerIds.add(customerId); |
|||
} |
|||
} |
|||
|
|||
Set<ShortCustomerInfo> assignedCustomers = dashboard.getAssignedCustomers(); |
|||
if (assignedCustomers != null) { |
|||
for (ShortCustomerInfo customerInfo : assignedCustomers) { |
|||
if (!customerIds.contains(customerInfo.getCustomerId())) { |
|||
removedCustomerIds.add(customerInfo.getCustomerId()); |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (addedCustomerIds.isEmpty() && removedCustomerIds.isEmpty()) { |
|||
return dashboard; |
|||
} else { |
|||
Dashboard savedDashboard = null; |
|||
for (CustomerId customerId : addedCustomerIds) { |
|||
savedDashboard = checkNotNull(dashboardService.assignDashboardToCustomer(tenantId, dashboard.getId(), customerId)); |
|||
ShortCustomerInfo customerInfo = savedDashboard.getAssignedCustomerInfo(customerId); |
|||
notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, savedDashboard.getId(), customerId, savedDashboard, |
|||
actionType, EdgeEventActionType.ASSIGNED_TO_CUSTOMER, user, true, customerInfo.getTitle()); |
|||
} |
|||
for (CustomerId customerId : removedCustomerIds) { |
|||
ShortCustomerInfo customerInfo = dashboard.getAssignedCustomerInfo(customerId); |
|||
savedDashboard = checkNotNull(dashboardService.unassignDashboardFromCustomer(tenantId, dashboard.getId(), customerId)); |
|||
notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, savedDashboard.getId(), customerId, savedDashboard, |
|||
ActionType.UNASSIGNED_FROM_CUSTOMER, EdgeEventActionType.UNASSIGNED_FROM_CUSTOMER, user, true, customerInfo.getTitle()); |
|||
} |
|||
return savedDashboard; |
|||
} |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DASHBOARD), null, null, |
|||
actionType, user, e, dashboard.getId().toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Dashboard addDashboardCustomers(Dashboard dashboard, Set<CustomerId> customerIds, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.ASSIGNED_TO_CUSTOMER; |
|||
TenantId tenantId = user.getTenantId(); |
|||
try { |
|||
if (customerIds.isEmpty()) { |
|||
return dashboard; |
|||
} else { |
|||
Dashboard savedDashboard = null; |
|||
for (CustomerId customerId : customerIds) { |
|||
savedDashboard = checkNotNull(dashboardService.assignDashboardToCustomer(tenantId, dashboard.getId(), customerId)); |
|||
ShortCustomerInfo customerInfo = savedDashboard.getAssignedCustomerInfo(customerId); |
|||
notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, savedDashboard.getId(), customerId, savedDashboard, |
|||
actionType, EdgeEventActionType.ASSIGNED_TO_CUSTOMER, user, true, customerInfo.getTitle()); |
|||
} |
|||
return savedDashboard; |
|||
} |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DASHBOARD), null, null, |
|||
actionType, user, e, dashboard.getId().toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Dashboard removeDashboardCustomers(Dashboard dashboard, Set<CustomerId> customerIds, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.UNASSIGNED_FROM_CUSTOMER; |
|||
TenantId tenantId = user.getTenantId(); |
|||
try { |
|||
if (customerIds.isEmpty()) { |
|||
return dashboard; |
|||
} else { |
|||
Dashboard savedDashboard = null; |
|||
for (CustomerId customerId : customerIds) { |
|||
ShortCustomerInfo customerInfo = dashboard.getAssignedCustomerInfo(customerId); |
|||
savedDashboard = checkNotNull(dashboardService.unassignDashboardFromCustomer(tenantId, dashboard.getId(), customerId)); |
|||
notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, savedDashboard.getId(), customerId, savedDashboard, |
|||
actionType, EdgeEventActionType.UNASSIGNED_FROM_CUSTOMER, user, true, customerInfo.getTitle()); |
|||
} |
|||
return savedDashboard; |
|||
} |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DASHBOARD), null, null, |
|||
actionType, user, e, dashboard.getId().toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Dashboard asignDashboardToEdge(DashboardId dashboardId, Edge edge, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.ASSIGNED_TO_EDGE; |
|||
TenantId tenantId = user.getTenantId(); |
|||
EdgeId edgeId = edge.getId(); |
|||
try { |
|||
Dashboard savedDashboard = checkNotNull(dashboardService.assignDashboardToEdge(tenantId, dashboardId, edgeId)); |
|||
notificationEntityService.notifyAssignOrUnassignEntityToEdge(tenantId, dashboardId, user.getCustomerId(), |
|||
edgeId, savedDashboard, actionType, user, dashboardId.toString(), |
|||
edgeId.toString(), edge.getName()); |
|||
return savedDashboard; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, |
|||
actionType, user, e, dashboardId.toString(), edgeId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Dashboard unassignDashboardFromEdge(Dashboard dashboard, Edge edge, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.UNASSIGNED_FROM_EDGE; |
|||
TenantId tenantId = dashboard.getTenantId(); |
|||
DashboardId dashboardId = dashboard.getId(); |
|||
EdgeId edgeId = edge.getId(); |
|||
try { |
|||
Dashboard savedDevice = checkNotNull(dashboardService.unassignDashboardFromEdge(tenantId, dashboardId, edgeId)); |
|||
|
|||
notificationEntityService.notifyAssignOrUnassignEntityToEdge(tenantId, dashboardId, user.getCustomerId(), |
|||
edgeId, dashboard, actionType, user, dashboardId.toString(), |
|||
edgeId.toString(), edge.getName()); |
|||
return savedDevice; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DASHBOARD), null, null, |
|||
actionType, user, e, dashboardId.toString(), edgeId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Dashboard unassignDashboardFromCustomer(Dashboard dashboard, Customer customer, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.UNASSIGNED_FROM_CUSTOMER; |
|||
TenantId tenantId = dashboard.getTenantId(); |
|||
try { |
|||
Dashboard savedDashboard = checkNotNull(dashboardService.unassignDashboardFromCustomer(tenantId, dashboard.getId(), customer.getId())); |
|||
notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, dashboard.getId(), customer.getId(), savedDashboard, |
|||
actionType, EdgeEventActionType.UNASSIGNED_FROM_CUSTOMER, user, true, customer.getId().toString(), customer.getName()); |
|||
return savedDashboard; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DASHBOARD), null, null, |
|||
actionType, user, e, dashboard.getId().toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,49 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy.dashboard; |
|||
|
|||
import org.thingsboard.server.common.data.Customer; |
|||
import org.thingsboard.server.common.data.Dashboard; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.id.CustomerId; |
|||
import org.thingsboard.server.common.data.id.DashboardId; |
|||
import org.thingsboard.server.service.entitiy.SimpleTbEntityService; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
|
|||
import java.util.Set; |
|||
|
|||
public interface TbDashboardService extends SimpleTbEntityService<Dashboard> { |
|||
|
|||
Dashboard assignDashboardToCustomer(DashboardId dashboardId, Customer customer, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Dashboard assignDashboardToPublicCustomer(DashboardId dashboardId, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Dashboard unassignDashboardFromPublicCustomer(Dashboard dashboard, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Dashboard updateDashboardCustomers(Dashboard dashboard, Set<CustomerId> customerIds, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Dashboard addDashboardCustomers(Dashboard dashboard, Set<CustomerId> customerIds, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Dashboard removeDashboardCustomers(Dashboard dashboard, Set<CustomerId> customerIds, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Dashboard asignDashboardToEdge(DashboardId dashboardId, Edge edge, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Dashboard unassignDashboardFromEdge(Dashboard dashboard, Edge edge, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Dashboard unassignDashboardFromCustomer(Dashboard dashboard, Customer customer, SecurityUser user) throws ThingsboardException; |
|||
|
|||
} |
|||
@ -0,0 +1,279 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy.device; |
|||
|
|||
import com.google.common.util.concurrent.Futures; |
|||
import com.google.common.util.concurrent.ListenableFuture; |
|||
import com.google.common.util.concurrent.MoreExecutors; |
|||
import lombok.AllArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.common.data.Customer; |
|||
import org.thingsboard.server.common.data.Device; |
|||
import org.thingsboard.server.common.data.EntityType; |
|||
import org.thingsboard.server.common.data.Tenant; |
|||
import org.thingsboard.server.common.data.audit.ActionType; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.common.data.edge.EdgeEventActionType; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.id.CustomerId; |
|||
import org.thingsboard.server.common.data.id.DeviceId; |
|||
import org.thingsboard.server.common.data.id.EdgeId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.security.DeviceCredentials; |
|||
import org.thingsboard.server.dao.device.claim.ClaimResponse; |
|||
import org.thingsboard.server.dao.device.claim.ClaimResult; |
|||
import org.thingsboard.server.dao.device.claim.ReclaimResult; |
|||
import org.thingsboard.server.queue.util.TbCoreComponent; |
|||
import org.thingsboard.server.service.entitiy.AbstractTbEntityService; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
|
|||
import java.util.List; |
|||
|
|||
@AllArgsConstructor |
|||
@TbCoreComponent |
|||
@Service |
|||
@Slf4j |
|||
public class DefaultTbDeviceService extends AbstractTbEntityService implements TbDeviceService { |
|||
|
|||
@Override |
|||
public Device save(TenantId tenantId, Device device, Device oldDevice, String accessToken, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = device.getId() == null ? ActionType.ADDED : ActionType.UPDATED; |
|||
try { |
|||
Device savedDevice = checkNotNull(deviceService.saveDeviceWithAccessToken(device, accessToken)); |
|||
notificationEntityService.notifyCreateOrUpdateDevice(tenantId, savedDevice.getId(), savedDevice.getCustomerId(), |
|||
savedDevice, oldDevice, actionType, user); |
|||
|
|||
return savedDevice; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), device, null, actionType, user, e); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Device saveDeviceWithCredentials(TenantId tenantId, Device device, DeviceCredentials credentials, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = device.getId() == null ? ActionType.ADDED : ActionType.UPDATED; |
|||
try { |
|||
Device savedDevice = checkNotNull(deviceService.saveDeviceWithCredentials(device, credentials)); |
|||
notificationEntityService.notifyCreateOrUpdateDevice(tenantId, savedDevice.getId(), savedDevice.getCustomerId(), |
|||
savedDevice, device, actionType, user); |
|||
|
|||
return savedDevice; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), device, null, actionType, user, e); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public ListenableFuture<Void> delete(Device device, SecurityUser user) throws ThingsboardException { |
|||
TenantId tenantId = device.getTenantId(); |
|||
DeviceId deviceId = device.getId(); |
|||
try { |
|||
List<EdgeId> relatedEdgeIds = findRelatedEdgeIds(tenantId, deviceId); |
|||
deviceService.deleteDevice(tenantId, deviceId); |
|||
notificationEntityService.notifyDeleteDevice(tenantId, deviceId, device.getCustomerId(), device, |
|||
relatedEdgeIds, user, deviceId.toString()); |
|||
|
|||
return removeAlarmsByEntityId(tenantId, deviceId); |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, |
|||
ActionType.DELETED, user, e, deviceId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Device assignDeviceToCustomer(TenantId tenantId, DeviceId deviceId, Customer customer, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.ASSIGNED_TO_CUSTOMER; |
|||
CustomerId customerId = customer.getId(); |
|||
try { |
|||
Device savedDevice = checkNotNull(deviceService.assignDeviceToCustomer(user.getTenantId(), deviceId, customerId)); |
|||
notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, deviceId, customerId, savedDevice, |
|||
actionType, EdgeEventActionType.ASSIGNED_TO_CUSTOMER, user, true, customerId.toString(), customer.getName()); |
|||
|
|||
return savedDevice; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, |
|||
actionType, user, e, deviceId.toString(), customerId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Device unassignDeviceFromCustomer(Device device, Customer customer, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.UNASSIGNED_FROM_CUSTOMER; |
|||
TenantId tenantId = device.getTenantId(); |
|||
DeviceId deviceId = device.getId(); |
|||
try { |
|||
Device savedDevice = checkNotNull(deviceService.unassignDeviceFromCustomer(tenantId, deviceId)); |
|||
CustomerId customerId = customer.getId(); |
|||
|
|||
notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, deviceId, customerId, savedDevice, |
|||
actionType, EdgeEventActionType.UNASSIGNED_FROM_CUSTOMER, user, |
|||
true, customerId.toString(), customer.getName()); |
|||
|
|||
return savedDevice; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, |
|||
actionType, user, e, deviceId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Device assignDeviceToPublicCustomer(TenantId tenantId, DeviceId deviceId, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.ASSIGNED_TO_CUSTOMER; |
|||
try { |
|||
Customer publicCustomer = customerService.findOrCreatePublicCustomer(tenantId); |
|||
Device savedDevice = checkNotNull(deviceService.assignDeviceToCustomer(tenantId, deviceId, publicCustomer.getId())); |
|||
|
|||
notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, deviceId, savedDevice.getCustomerId(), savedDevice, |
|||
actionType, null, user, false, deviceId.toString(), |
|||
publicCustomer.getId().toString(), publicCustomer.getName()); |
|||
|
|||
return savedDevice; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, |
|||
actionType, user, e, deviceId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public DeviceCredentials getDeviceCredentialsByDeviceId(Device device, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.CREDENTIALS_READ; |
|||
TenantId tenantId = device.getTenantId(); |
|||
DeviceId deviceId = device.getId(); |
|||
try { |
|||
DeviceCredentials deviceCredentials = checkNotNull(deviceCredentialsService.findDeviceCredentialsByDeviceId(tenantId, deviceId)); |
|||
notificationEntityService.notifyEntity(tenantId, deviceId, device, device.getCustomerId(), |
|||
actionType, user, null, deviceId.toString()); |
|||
return deviceCredentials; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, |
|||
actionType, user, e, deviceId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public DeviceCredentials updateDeviceCredentials(Device device, DeviceCredentials deviceCredentials, SecurityUser user) throws ThingsboardException { |
|||
TenantId tenantId = device.getTenantId(); |
|||
DeviceId deviceId = device.getId(); |
|||
try { |
|||
DeviceCredentials result = checkNotNull(deviceCredentialsService.updateDeviceCredentials(tenantId, deviceCredentials)); |
|||
notificationEntityService.notifyUpdateDeviceCredentials(tenantId, deviceId, device.getCustomerId(), device, result, user); |
|||
return result; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, |
|||
ActionType.CREDENTIALS_UPDATED, user, e, deviceCredentials); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public ListenableFuture<ClaimResult> claimDevice(TenantId tenantId, Device device, CustomerId customerId, String secretKey, SecurityUser user) throws ThingsboardException { |
|||
try { |
|||
ListenableFuture<ClaimResult> future = claimDevicesService.claimDevice(device, customerId, secretKey); |
|||
|
|||
return Futures.transform(future, result -> { |
|||
if (result != null && result.getResponse().equals(ClaimResponse.SUCCESS)) { |
|||
notificationEntityService.notifyEntity(tenantId, device.getId(), result.getDevice(), customerId, |
|||
ActionType.ASSIGNED_TO_CUSTOMER, user, null, device.getId().toString(), customerId.toString(), |
|||
customerService.findCustomerById(tenantId, customerId).getName()); |
|||
} |
|||
return result; |
|||
}, MoreExecutors.directExecutor()); |
|||
} catch (Exception e) { |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public ListenableFuture<ReclaimResult> reclaimDevice(TenantId tenantId, Device device, SecurityUser user) throws ThingsboardException { |
|||
try { |
|||
ListenableFuture<ReclaimResult> future = claimDevicesService.reClaimDevice(tenantId, device); |
|||
|
|||
return Futures.transform(future, result -> { |
|||
Customer unassignedCustomer = result.getUnassignedCustomer(); |
|||
if (unassignedCustomer != null) { |
|||
notificationEntityService.notifyEntity(tenantId, device.getId(), device, device.getCustomerId(), ActionType.UNASSIGNED_FROM_CUSTOMER, user, null, |
|||
device.getId().toString(), unassignedCustomer.getId().toString(), unassignedCustomer.getName()); |
|||
} |
|||
return result; |
|||
}, MoreExecutors.directExecutor()); |
|||
} catch (Exception e) { |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Device assignDeviceToTenant(Device device, Tenant newTenant, SecurityUser user) throws ThingsboardException { |
|||
TenantId tenantId = device.getTenantId(); |
|||
TenantId newTenantId = newTenant.getId(); |
|||
try { |
|||
Tenant tenant = tenantService.findTenantById(tenantId); |
|||
Device assignedDevice = deviceService.assignDeviceToTenant(newTenantId, device); |
|||
|
|||
notificationEntityService.notifyAssignDeviceToTenant(tenantId, newTenantId, device.getId(), |
|||
assignedDevice.getCustomerId(), assignedDevice, tenant, user, newTenantId.toString(), newTenant.getName()); |
|||
|
|||
return assignedDevice; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, |
|||
ActionType.ASSIGNED_TO_TENANT, user, e, newTenantId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Device assignDeviceToEdge(TenantId tenantId, DeviceId deviceId, Edge edge, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.ASSIGNED_TO_EDGE; |
|||
EdgeId edgeId = edge.getId(); |
|||
try { |
|||
Device savedDevice = checkNotNull(deviceService.assignDeviceToEdge(tenantId, deviceId, edgeId)); |
|||
notificationEntityService.notifyAssignOrUnassignEntityToEdge(tenantId, deviceId, savedDevice.getCustomerId(), |
|||
edgeId, savedDevice, actionType, user, deviceId.toString(), edgeId.toString(), edge.getName()); |
|||
return savedDevice; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, |
|||
actionType, user, e, deviceId.toString(), edgeId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Device unassignDeviceFromEdge(Device device, Edge edge, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.UNASSIGNED_FROM_EDGE; |
|||
TenantId tenantId = device.getTenantId(); |
|||
DeviceId deviceId = device.getId(); |
|||
EdgeId edgeId = edge.getId(); |
|||
try { |
|||
Device savedDevice = checkNotNull(deviceService.unassignDeviceFromEdge(tenantId, deviceId, edgeId)); |
|||
|
|||
notificationEntityService.notifyAssignOrUnassignEntityToEdge(tenantId, deviceId, device.getCustomerId(), |
|||
edgeId, device, actionType, user, deviceId.toString(), edgeId.toString(), edge.getName()); |
|||
return savedDevice; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, |
|||
actionType, user, e, deviceId.toString(), edgeId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,59 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy.device; |
|||
|
|||
import com.google.common.util.concurrent.ListenableFuture; |
|||
import org.thingsboard.server.common.data.Customer; |
|||
import org.thingsboard.server.common.data.Device; |
|||
import org.thingsboard.server.common.data.Tenant; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.id.CustomerId; |
|||
import org.thingsboard.server.common.data.id.DeviceId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.security.DeviceCredentials; |
|||
import org.thingsboard.server.dao.device.claim.ClaimResult; |
|||
import org.thingsboard.server.dao.device.claim.ReclaimResult; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
|
|||
public interface TbDeviceService { |
|||
|
|||
Device save(TenantId tenantId, Device device, Device oldDevice, String accessToken, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Device saveDeviceWithCredentials(TenantId tenantId, Device device, DeviceCredentials deviceCredentials, SecurityUser user) throws ThingsboardException; |
|||
|
|||
ListenableFuture<Void> delete(Device device, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Device assignDeviceToCustomer(TenantId tenantId, DeviceId deviceId, Customer customer, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Device unassignDeviceFromCustomer(Device device, Customer customer, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Device assignDeviceToPublicCustomer(TenantId tenantId, DeviceId deviceId, SecurityUser user) throws ThingsboardException; |
|||
|
|||
DeviceCredentials getDeviceCredentialsByDeviceId(Device device, SecurityUser user) throws ThingsboardException; |
|||
|
|||
DeviceCredentials updateDeviceCredentials(Device device, DeviceCredentials deviceCredentials, SecurityUser user) throws ThingsboardException; |
|||
|
|||
ListenableFuture<ClaimResult> claimDevice(TenantId tenantId, Device device, CustomerId customerId, String secretKey, SecurityUser user) throws ThingsboardException; |
|||
|
|||
ListenableFuture<ReclaimResult> reclaimDevice(TenantId tenantId, Device device, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Device assignDeviceToTenant(Device device, Tenant newTenant, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Device assignDeviceToEdge(TenantId tenantId, DeviceId deviceId, Edge edge, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Device unassignDeviceFromEdge(Device device, Edge edge, SecurityUser user) throws ThingsboardException; |
|||
} |
|||
@ -0,0 +1,111 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy.deviceProfile; |
|||
|
|||
import lombok.AllArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.common.data.DeviceProfile; |
|||
import org.thingsboard.server.common.data.EntityType; |
|||
import org.thingsboard.server.common.data.audit.ActionType; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.id.DeviceProfileId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; |
|||
import org.thingsboard.server.queue.util.TbCoreComponent; |
|||
import org.thingsboard.server.service.entitiy.AbstractTbEntityService; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
|
|||
import java.util.Objects; |
|||
|
|||
@Service |
|||
@TbCoreComponent |
|||
@AllArgsConstructor |
|||
@Slf4j |
|||
public class DefaultTbDeviceProfileService extends AbstractTbEntityService implements TbDeviceProfileService { |
|||
@Override |
|||
public DeviceProfile save(DeviceProfile deviceProfile, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = deviceProfile.getId() == null ? ActionType.ADDED : ActionType.UPDATED; |
|||
TenantId tenantId = deviceProfile.getTenantId(); |
|||
try { |
|||
boolean isFirmwareChanged = false; |
|||
boolean isSoftwareChanged = false; |
|||
|
|||
if (actionType.equals(ActionType.UPDATED)) { |
|||
DeviceProfile oldDeviceProfile = deviceProfileService.findDeviceProfileById(tenantId, deviceProfile.getId()); |
|||
if (!Objects.equals(deviceProfile.getFirmwareId(), oldDeviceProfile.getFirmwareId())) { |
|||
isFirmwareChanged = true; |
|||
} |
|||
if (!Objects.equals(deviceProfile.getSoftwareId(), oldDeviceProfile.getSoftwareId())) { |
|||
isSoftwareChanged = true; |
|||
} |
|||
} |
|||
DeviceProfile savedDeviceProfile = checkNotNull(deviceProfileService.saveDeviceProfile(deviceProfile)); |
|||
|
|||
tbClusterService.onDeviceProfileChange(savedDeviceProfile, null); |
|||
tbClusterService.broadcastEntityStateChangeEvent(tenantId, savedDeviceProfile.getId(), |
|||
actionType.equals(ActionType.ADDED) ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED); |
|||
|
|||
otaPackageStateService.update(savedDeviceProfile, isFirmwareChanged, isSoftwareChanged); |
|||
|
|||
notificationEntityService.notifyCreateOrUpdateOrDelete(tenantId, null, savedDeviceProfile.getId(), savedDeviceProfile, user, actionType, true, null); |
|||
return savedDeviceProfile; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyCreateOrUpdateOrDelete(tenantId, null, emptyId(EntityType.DEVICE_PROFILE), deviceProfile, user, actionType, false, e); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void delete(DeviceProfile deviceProfile, SecurityUser user) throws ThingsboardException { |
|||
DeviceProfileId deviceProfileId = deviceProfile.getId(); |
|||
TenantId tenantId = deviceProfile.getTenantId(); |
|||
try { |
|||
deviceProfileService.deleteDeviceProfile(tenantId, deviceProfileId); |
|||
|
|||
tbClusterService.onDeviceProfileDelete(deviceProfile, null); |
|||
tbClusterService.broadcastEntityStateChangeEvent(tenantId, deviceProfileId, ComponentLifecycleEvent.DELETED); |
|||
notificationEntityService.notifyCreateOrUpdateOrDelete(tenantId, null, deviceProfileId, deviceProfile, user, ActionType.DELETED, true, null, deviceProfileId.toString()); |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyCreateOrUpdateOrDelete(tenantId, null, emptyId(EntityType.DEVICE_PROFILE), null, user, ActionType.DELETED, false, e, deviceProfileId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public DeviceProfile setDefaultDeviceProfile(DeviceProfile deviceProfile, DeviceProfile previousDefaultDeviceProfile, SecurityUser user) throws ThingsboardException { |
|||
TenantId tenantId = deviceProfile.getTenantId(); |
|||
try { |
|||
|
|||
if (deviceProfileService.setDefaultDeviceProfile(tenantId, deviceProfile.getId())) { |
|||
if (previousDefaultDeviceProfile != null) { |
|||
previousDefaultDeviceProfile = deviceProfileService.findDeviceProfileById(tenantId, previousDefaultDeviceProfile.getId()); |
|||
notificationEntityService.notifyEntity(tenantId, previousDefaultDeviceProfile.getId(), previousDefaultDeviceProfile, null, |
|||
ActionType.UPDATED, user, null); |
|||
} |
|||
deviceProfile = deviceProfileService.findDeviceProfileById(tenantId, deviceProfile.getId()); |
|||
|
|||
notificationEntityService.notifyEntity(tenantId, deviceProfile.getId(), deviceProfile, null, |
|||
ActionType.UPDATED, user, null); |
|||
} |
|||
return deviceProfile; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE_PROFILE), null, null, |
|||
ActionType.UPDATED, user, e, deviceProfile.getId().toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy.deviceProfile; |
|||
|
|||
import org.thingsboard.server.common.data.DeviceProfile; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.service.entitiy.SimpleTbEntityService; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
|
|||
public interface TbDeviceProfileService extends SimpleTbEntityService<DeviceProfile> { |
|||
|
|||
DeviceProfile setDefaultDeviceProfile(DeviceProfile deviceProfile, DeviceProfile previousDefaultDeviceProfile, SecurityUser user) throws ThingsboardException; |
|||
} |
|||
@ -0,0 +1,150 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy.edge; |
|||
|
|||
import lombok.AllArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.common.data.Customer; |
|||
import org.thingsboard.server.common.data.EntityType; |
|||
import org.thingsboard.server.common.data.audit.ActionType; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.id.CustomerId; |
|||
import org.thingsboard.server.common.data.id.EdgeId; |
|||
import org.thingsboard.server.common.data.id.RuleChainId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.rule.RuleChain; |
|||
import org.thingsboard.server.queue.util.TbCoreComponent; |
|||
import org.thingsboard.server.service.entitiy.AbstractTbEntityService; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
|
|||
@AllArgsConstructor |
|||
@TbCoreComponent |
|||
@Service |
|||
@Slf4j |
|||
public class DefaultTbEdgeService extends AbstractTbEntityService implements TbEdgeService { |
|||
|
|||
@Override |
|||
public Edge save(Edge edge, RuleChain edgeTemplateRootRuleChain, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = edge.getId() == null ? ActionType.ADDED : ActionType.UPDATED; |
|||
TenantId tenantId = edge.getTenantId(); |
|||
try { |
|||
Edge savedEdge = checkNotNull(edgeService.saveEdge(edge)); |
|||
EdgeId edgeId = savedEdge.getId(); |
|||
|
|||
if (actionType == ActionType.ADDED) { |
|||
ruleChainService.assignRuleChainToEdge(tenantId, edgeTemplateRootRuleChain.getId(), edgeId); |
|||
edgeNotificationService.setEdgeRootRuleChain(tenantId, savedEdge, edgeTemplateRootRuleChain.getId()); |
|||
edgeService.assignDefaultRuleChainsToEdge(tenantId, edgeId); |
|||
} |
|||
|
|||
notificationEntityService.notifyEdge(tenantId, edgeId, savedEdge.getCustomerId(), savedEdge, actionType, user); |
|||
|
|||
return savedEdge; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.EDGE), edge, null, actionType, user, e); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void delete(Edge edge, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.DELETED; |
|||
EdgeId edgeId = edge.getId(); |
|||
TenantId tenantId = edge.getTenantId(); |
|||
try { |
|||
edgeService.deleteEdge(tenantId, edgeId); |
|||
notificationEntityService.notifyEdge(tenantId, edgeId, edge.getCustomerId(), edge, actionType, user, edgeId.toString()); |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.EDGE), edge, null, actionType, |
|||
user, e, edgeId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Edge assignEdgeToCustomer(TenantId tenantId, EdgeId edgeId, Customer customer, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.ASSIGNED_TO_CUSTOMER; |
|||
CustomerId customerId = customer.getId(); |
|||
try { |
|||
Edge savedEdge = checkNotNull(edgeService.assignEdgeToCustomer(tenantId, edgeId, customerId)); |
|||
|
|||
notificationEntityService.notifyEdge(tenantId, edgeId, customerId, savedEdge, actionType, user, |
|||
edgeId.toString(), customerId.toString(), customer.getName()); |
|||
|
|||
return savedEdge; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.EDGE), null, null, |
|||
actionType, user, e, edgeId.toString(), customerId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Edge unassignEdgeFromCustomer(Edge edge, Customer customer, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.UNASSIGNED_FROM_CUSTOMER; |
|||
TenantId tenantId = edge.getTenantId(); |
|||
EdgeId edgeId = edge.getId(); |
|||
CustomerId customerId = customer.getId(); |
|||
try { |
|||
Edge savedEdge = checkNotNull(edgeService.unassignEdgeFromCustomer(tenantId, edgeId)); |
|||
|
|||
notificationEntityService.notifyEdge(tenantId, edgeId, customerId, savedEdge, actionType, user, |
|||
edgeId.toString(), customerId.toString(), customer.getName()); |
|||
return savedEdge; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.EDGE), null, null, |
|||
actionType, user, e, edgeId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Edge assignEdgeToPublicCustomer(TenantId tenantId, EdgeId edgeId, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.ASSIGNED_TO_CUSTOMER; |
|||
try { |
|||
Customer publicCustomer = customerService.findOrCreatePublicCustomer(tenantId); |
|||
CustomerId customerId = publicCustomer.getId(); |
|||
Edge savedEdge = checkNotNull(edgeService.assignEdgeToCustomer(tenantId, edgeId, customerId)); |
|||
|
|||
notificationEntityService.notifyEdge(tenantId, edgeId, customerId, savedEdge, actionType, user, |
|||
edgeId.toString(), customerId.toString(), publicCustomer.getName()); |
|||
|
|||
return savedEdge; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.EDGE), null, null, |
|||
actionType, user, e, edgeId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public Edge setEdgeRootRuleChain(Edge edge, RuleChainId ruleChainId, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.UPDATED; |
|||
TenantId tenantId = edge.getTenantId(); |
|||
EdgeId edgeId = edge.getId(); |
|||
try { |
|||
Edge updatedEdge = edgeNotificationService.setEdgeRootRuleChain(tenantId, edge, ruleChainId); |
|||
notificationEntityService.notifyEdge(tenantId, edgeId, null, updatedEdge, actionType, user); |
|||
return updatedEdge; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.EDGE), null, null, |
|||
actionType, user, e, edgeId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy.edge; |
|||
|
|||
import org.thingsboard.server.common.data.Customer; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.id.EdgeId; |
|||
import org.thingsboard.server.common.data.id.RuleChainId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.rule.RuleChain; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
|
|||
public interface TbEdgeService { |
|||
Edge save(Edge edge, RuleChain edgeTemplateRootRuleChain, SecurityUser user) throws ThingsboardException; |
|||
|
|||
void delete(Edge edge, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Edge assignEdgeToCustomer(TenantId tenantId, EdgeId edgeId, Customer customer, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Edge unassignEdgeFromCustomer(Edge edge, Customer customer, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Edge assignEdgeToPublicCustomer(TenantId tenantId, EdgeId edgeId, SecurityUser user) throws ThingsboardException; |
|||
|
|||
Edge setEdgeRootRuleChain(Edge edge, RuleChainId ruleChainId, SecurityUser user) throws ThingsboardException; |
|||
} |
|||
@ -0,0 +1,76 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy.entityRelation; |
|||
|
|||
import lombok.AllArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.common.data.audit.ActionType; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.id.CustomerId; |
|||
import org.thingsboard.server.common.data.id.EntityId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.relation.EntityRelation; |
|||
import org.thingsboard.server.queue.util.TbCoreComponent; |
|||
import org.thingsboard.server.service.entitiy.AbstractTbEntityService; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
|
|||
@Service |
|||
@TbCoreComponent |
|||
@AllArgsConstructor |
|||
@Slf4j |
|||
public class DefaultTbEntityRelationService extends AbstractTbEntityService implements TbEntityRelationService { |
|||
@Override |
|||
public void save(TenantId tenantId, CustomerId customerId, EntityRelation relation, SecurityUser user) throws ThingsboardException { |
|||
try { |
|||
relationService.saveRelation(tenantId, relation); |
|||
notificationEntityService.notifyCreateOrUpdateOrDeleteRelation (tenantId, customerId, |
|||
relation, user, ActionType.RELATION_ADD_OR_UPDATE, null, relation); |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyCreateOrUpdateOrDeleteRelation (tenantId, customerId, |
|||
relation, user, ActionType.RELATION_ADD_OR_UPDATE, e, relation); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void delete(TenantId tenantId, CustomerId customerId, EntityRelation relation, SecurityUser user) throws ThingsboardException { |
|||
try { |
|||
Boolean found = relationService.deleteRelation(tenantId, relation.getFrom(), relation.getTo(), relation.getType(), relation.getTypeGroup()); |
|||
if (!found) { |
|||
throw new ThingsboardException("Requested item wasn't found!", ThingsboardErrorCode.ITEM_NOT_FOUND); |
|||
} |
|||
notificationEntityService.notifyCreateOrUpdateOrDeleteRelation (tenantId, customerId, |
|||
relation, user, ActionType.RELATION_DELETED, null, relation); |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyCreateOrUpdateOrDeleteRelation (tenantId, customerId, |
|||
relation, user, ActionType.RELATION_DELETED, e, relation); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void deleteRelations(TenantId tenantId, CustomerId customerId, EntityId entityId, SecurityUser user) throws ThingsboardException { |
|||
try { |
|||
relationService.deleteEntityRelations(tenantId, entityId); |
|||
notificationEntityService.notifyEntity(tenantId, entityId, null, customerId, ActionType.RELATIONS_DELETED, user, null); |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, entityId, null, customerId, ActionType.RELATIONS_DELETED, user, e); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy.entityRelation; |
|||
|
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.id.CustomerId; |
|||
import org.thingsboard.server.common.data.id.EntityId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.relation.EntityRelation; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
|
|||
public interface TbEntityRelationService { |
|||
|
|||
void save(TenantId tenantId, CustomerId customerId, EntityRelation entity, SecurityUser user) throws ThingsboardException; |
|||
|
|||
void delete (TenantId tenantId, CustomerId customerId, EntityRelation entity, SecurityUser user) throws ThingsboardException; |
|||
|
|||
void deleteRelations (TenantId tenantId, CustomerId customerId, EntityId entityId, SecurityUser user) throws ThingsboardException; |
|||
|
|||
} |
|||
@ -0,0 +1,388 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy.entityView; |
|||
|
|||
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 com.google.common.util.concurrent.SettableFuture; |
|||
import lombok.AllArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.common.data.Customer; |
|||
import org.thingsboard.server.common.data.DataConstants; |
|||
import org.thingsboard.server.common.data.EntityType; |
|||
import org.thingsboard.server.common.data.EntityView; |
|||
import org.thingsboard.server.common.data.audit.ActionType; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.common.data.edge.EdgeEventActionType; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.id.CustomerId; |
|||
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.kv.AttributeKvEntry; |
|||
import org.thingsboard.server.common.data.kv.BaseReadTsKvQuery; |
|||
import org.thingsboard.server.common.data.kv.ReadTsKvQuery; |
|||
import org.thingsboard.server.common.data.kv.TsKvEntry; |
|||
import org.thingsboard.server.dao.timeseries.TimeseriesService; |
|||
import org.thingsboard.server.queue.util.TbCoreComponent; |
|||
import org.thingsboard.server.service.entitiy.AbstractTbEntityService; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
|
|||
import javax.annotation.Nullable; |
|||
import java.util.ArrayList; |
|||
import java.util.Collection; |
|||
import java.util.Collections; |
|||
import java.util.List; |
|||
import java.util.concurrent.ExecutionException; |
|||
import java.util.stream.Collectors; |
|||
|
|||
import static org.apache.commons.lang3.StringUtils.isBlank; |
|||
|
|||
@Service |
|||
@TbCoreComponent |
|||
@AllArgsConstructor |
|||
@Slf4j |
|||
public class DefaultTbEntityViewService extends AbstractTbEntityService implements TbEntityViewService { |
|||
|
|||
private final TimeseriesService tsService; |
|||
|
|||
@Override |
|||
public EntityView save(EntityView entityView, EntityView existingEntityView, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = entityView.getId() == null ? ActionType.ADDED : ActionType.UPDATED; |
|||
try { |
|||
List<ListenableFuture<?>> futures = new ArrayList<>(); |
|||
if (existingEntityView != null) { |
|||
if (existingEntityView.getKeys() != null && existingEntityView.getKeys().getAttributes() != null) { |
|||
futures.add(deleteAttributesFromEntityView(existingEntityView, DataConstants.CLIENT_SCOPE, existingEntityView.getKeys().getAttributes().getCs(), user)); |
|||
futures.add(deleteAttributesFromEntityView(existingEntityView, DataConstants.SERVER_SCOPE, existingEntityView.getKeys().getAttributes().getCs(), user)); |
|||
futures.add(deleteAttributesFromEntityView(existingEntityView, DataConstants.SHARED_SCOPE, existingEntityView.getKeys().getAttributes().getCs(), user)); |
|||
} |
|||
List<String> tsKeys = existingEntityView.getKeys() != null && existingEntityView.getKeys().getTimeseries() != null ? |
|||
existingEntityView.getKeys().getTimeseries() : Collections.emptyList(); |
|||
futures.add(deleteLatestFromEntityView(existingEntityView, tsKeys, user)); |
|||
} |
|||
EntityView savedEntityView = checkNotNull(entityViewService.saveEntityView(entityView)); |
|||
if (savedEntityView.getKeys() != null) { |
|||
if (savedEntityView.getKeys().getAttributes() != null) { |
|||
futures.add(copyAttributesFromEntityToEntityView(savedEntityView, DataConstants.CLIENT_SCOPE, savedEntityView.getKeys().getAttributes().getCs(), user)); |
|||
futures.add(copyAttributesFromEntityToEntityView(savedEntityView, DataConstants.SERVER_SCOPE, savedEntityView.getKeys().getAttributes().getSs(), user)); |
|||
futures.add(copyAttributesFromEntityToEntityView(savedEntityView, DataConstants.SHARED_SCOPE, savedEntityView.getKeys().getAttributes().getSh(), user)); |
|||
} |
|||
futures.add(copyLatestFromEntityToEntityView(savedEntityView, user)); |
|||
} |
|||
for (ListenableFuture<?> future : futures) { |
|||
try { |
|||
future.get(); |
|||
} catch (InterruptedException | ExecutionException e) { |
|||
throw new RuntimeException("Failed to copy attributes to entity view", e); |
|||
} |
|||
} |
|||
|
|||
notificationEntityService.notifyCreateOrUpdateEntity(savedEntityView.getTenantId(), savedEntityView.getId(), savedEntityView, |
|||
null, actionType, user); |
|||
|
|||
return savedEntityView; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(user.getTenantId(), emptyId(EntityType.ENTITY_VIEW), entityView, null, actionType, user, e); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void delete(EntityView entityView, SecurityUser user) throws ThingsboardException { |
|||
TenantId tenantId = entityView.getTenantId(); |
|||
EntityViewId entityViewId = entityView.getId(); |
|||
try { |
|||
List<EdgeId> relatedEdgeIds = findRelatedEdgeIds(tenantId, entityViewId); |
|||
entityViewService.deleteEntityView(tenantId, entityViewId); |
|||
notificationEntityService.notifyDeleteEntity(tenantId, entityViewId, entityView, entityView.getCustomerId(), ActionType.DELETED, |
|||
relatedEdgeIds, user, entityViewId.toString()); |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ENTITY_VIEW), null, null, |
|||
ActionType.DELETED, user, e, entityViewId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public EntityView assignEntityViewToCustomer(TenantId tenantId, EntityViewId entityViewId, Customer customer, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.ASSIGNED_TO_CUSTOMER; |
|||
CustomerId customerId = customer.getId(); |
|||
try { |
|||
EntityView savedEntityView = checkNotNull(entityViewService.assignEntityViewToCustomer(tenantId, entityViewId, customerId)); |
|||
notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, entityViewId, customerId, savedEntityView, |
|||
actionType, EdgeEventActionType.ASSIGNED_TO_CUSTOMER, user, true, customerId.toString(), customer.getName()); |
|||
return savedEntityView; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ENTITY_VIEW), null, null, |
|||
actionType, user, e, entityViewId.toString(), customerId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public EntityView assignEntityViewToPublicCustomer(TenantId tenantId, CustomerId customerId, Customer publicCustomer, |
|||
EntityViewId entityViewId, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.ASSIGNED_TO_CUSTOMER; |
|||
try { |
|||
EntityView savedEntityView = checkNotNull(entityViewService.assignEntityViewToCustomer(tenantId, |
|||
entityViewId, publicCustomer.getId())); |
|||
notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, entityViewId, customerId, savedEntityView, |
|||
actionType, null, user, false, savedEntityView.getEntityId().toString(), |
|||
publicCustomer.getId().toString(), publicCustomer.getName()); |
|||
return savedEntityView; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ENTITY_VIEW), null, null, |
|||
actionType, user, e, entityViewId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public EntityView assignEntityViewToEdge(TenantId tenantId, CustomerId customerId, EntityViewId entityViewId, Edge edge, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.ASSIGNED_TO_EDGE; |
|||
EdgeId edgeId = edge.getId(); |
|||
EntityView savedEntityView = checkNotNull(entityViewService.assignEntityViewToEdge(tenantId, entityViewId, edgeId)); |
|||
try { |
|||
notificationEntityService.notifyAssignOrUnassignEntityToEdge(tenantId, entityViewId, customerId, |
|||
edgeId, savedEntityView, actionType, user, savedEntityView.getEntityId().toString(), |
|||
edgeId.toString(), edge.getName()); |
|||
return savedEntityView; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.DEVICE), null, null, |
|||
actionType, user, e, entityViewId.toString(), edgeId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public EntityView unassignEntityViewFromEdge(TenantId tenantId, CustomerId customerId, EntityView entityView, |
|||
Edge edge, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.UNASSIGNED_FROM_EDGE; |
|||
EntityViewId entityViewId = entityView.getId(); |
|||
EdgeId edgeId = edge.getId(); |
|||
try { |
|||
EntityView savedEntityView = checkNotNull(entityViewService.unassignEntityViewFromEdge(tenantId, entityViewId, edgeId)); |
|||
notificationEntityService.notifyAssignOrUnassignEntityToEdge(tenantId, entityViewId, customerId, |
|||
edgeId, entityView, actionType, user, entityViewId.toString(), |
|||
edgeId.toString(), edge.getName()); |
|||
return savedEntityView; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ENTITY_VIEW), null, null, |
|||
actionType, user, e, entityViewId.toString(), edgeId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public EntityView unassignEntityViewFromCustomer(TenantId tenantId, EntityViewId entityViewId, Customer customer, SecurityUser user) throws ThingsboardException { |
|||
ActionType actionType = ActionType.UNASSIGNED_FROM_CUSTOMER; |
|||
try { |
|||
EntityView savedEntityView = checkNotNull(entityViewService.unassignEntityViewFromCustomer(tenantId, entityViewId)); |
|||
notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, entityViewId, customer.getId(), savedEntityView, |
|||
actionType, EdgeEventActionType.UNASSIGNED_FROM_CUSTOMER, user, true, customer.getId().toString(), customer.getName()); |
|||
return savedEntityView; |
|||
} catch (Exception e) { |
|||
notificationEntityService.notifyEntity(tenantId, emptyId(EntityType.ENTITY_VIEW), null, null, |
|||
actionType, user, e, entityViewId.toString()); |
|||
throw handleException(e); |
|||
} |
|||
} |
|||
|
|||
private ListenableFuture<List<Void>> copyAttributesFromEntityToEntityView(EntityView entityView, String scope, Collection<String> keys, SecurityUser user) throws ThingsboardException { |
|||
EntityViewId entityId = entityView.getId(); |
|||
if (keys != null && !keys.isEmpty()) { |
|||
ListenableFuture<List<AttributeKvEntry>> getAttrFuture = attributesService.find(entityView.getTenantId(), entityView.getEntityId(), scope, keys); |
|||
return Futures.transform(getAttrFuture, attributeKvEntries -> { |
|||
List<AttributeKvEntry> attributes; |
|||
if (attributeKvEntries != null && !attributeKvEntries.isEmpty()) { |
|||
attributes = |
|||
attributeKvEntries.stream() |
|||
.filter(attributeKvEntry -> { |
|||
long startTime = entityView.getStartTimeMs(); |
|||
long endTime = entityView.getEndTimeMs(); |
|||
long lastUpdateTs = attributeKvEntry.getLastUpdateTs(); |
|||
return startTime == 0 && endTime == 0 || |
|||
(endTime == 0 && startTime < lastUpdateTs) || |
|||
(startTime == 0 && endTime > lastUpdateTs) |
|||
? true : startTime < lastUpdateTs && endTime > lastUpdateTs; |
|||
}).collect(Collectors.toList()); |
|||
tsSubService.saveAndNotify(entityView.getTenantId(), entityId, scope, attributes, new FutureCallback<Void>() { |
|||
@Override |
|||
public void onSuccess(@Nullable Void tmp) { |
|||
try { |
|||
logAttributesUpdated(entityView.getTenantId(), user, entityId, scope, attributes, null); |
|||
} catch (ThingsboardException e) { |
|||
log.error("Failed to log attribute updates", e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void onFailure(Throwable t) { |
|||
try { |
|||
logAttributesUpdated(entityView.getTenantId(), user, entityId, scope, attributes, t); |
|||
} catch (ThingsboardException e) { |
|||
log.error("Failed to log attribute updates", e); |
|||
} |
|||
} |
|||
}); |
|||
} |
|||
return null; |
|||
}, MoreExecutors.directExecutor()); |
|||
} else { |
|||
return Futures.immediateFuture(null); |
|||
} |
|||
} |
|||
|
|||
private ListenableFuture<List<Void>> copyLatestFromEntityToEntityView(EntityView entityView, SecurityUser user) { |
|||
EntityViewId entityId = entityView.getId(); |
|||
List<String> keys = entityView.getKeys() != null && entityView.getKeys().getTimeseries() != null ? |
|||
entityView.getKeys().getTimeseries() : Collections.emptyList(); |
|||
long startTs = entityView.getStartTimeMs(); |
|||
long endTs = entityView.getEndTimeMs() == 0 ? Long.MAX_VALUE : entityView.getEndTimeMs(); |
|||
ListenableFuture<List<String>> keysFuture; |
|||
if (keys.isEmpty()) { |
|||
keysFuture = Futures.transform(tsService.findAllLatest(user.getTenantId(), |
|||
entityView.getEntityId()), latest -> latest.stream().map(TsKvEntry::getKey).collect(Collectors.toList()), MoreExecutors.directExecutor()); |
|||
} else { |
|||
keysFuture = Futures.immediateFuture(keys); |
|||
} |
|||
ListenableFuture<List<TsKvEntry>> latestFuture = Futures.transformAsync(keysFuture, fetchKeys -> { |
|||
List<ReadTsKvQuery> queries = fetchKeys.stream().filter(key -> !isBlank(key)).map(key -> new BaseReadTsKvQuery(key, startTs, endTs, 1, "DESC")).collect(Collectors.toList()); |
|||
if (!queries.isEmpty()) { |
|||
return tsService.findAll(user.getTenantId(), entityView.getEntityId(), queries); |
|||
} else { |
|||
return Futures.immediateFuture(null); |
|||
} |
|||
}, MoreExecutors.directExecutor()); |
|||
return Futures.transform(latestFuture, latestValues -> { |
|||
if (latestValues != null && !latestValues.isEmpty()) { |
|||
tsSubService.saveLatestAndNotify(entityView.getTenantId(), entityId, latestValues, new FutureCallback<Void>() { |
|||
@Override |
|||
public void onSuccess(@Nullable Void tmp) { |
|||
} |
|||
|
|||
@Override |
|||
public void onFailure(Throwable t) { |
|||
} |
|||
}); |
|||
} |
|||
return null; |
|||
}, MoreExecutors.directExecutor()); |
|||
} |
|||
|
|||
private ListenableFuture<Void> deleteAttributesFromEntityView(EntityView entityView, String scope, List<String> keys, SecurityUser user) { |
|||
EntityViewId entityId = entityView.getId(); |
|||
SettableFuture<Void> resultFuture = SettableFuture.create(); |
|||
if (keys != null && !keys.isEmpty()) { |
|||
tsSubService.deleteAndNotify(entityView.getTenantId(), entityId, scope, keys, new FutureCallback<Void>() { |
|||
@Override |
|||
public void onSuccess(@Nullable Void tmp) { |
|||
try { |
|||
logAttributesDeleted(entityView.getTenantId(), user, entityId, scope, keys, null); |
|||
} catch (ThingsboardException e) { |
|||
log.error("Failed to log attribute delete", e); |
|||
} |
|||
resultFuture.set(tmp); |
|||
} |
|||
|
|||
@Override |
|||
public void onFailure(Throwable t) { |
|||
try { |
|||
logAttributesDeleted(entityView.getTenantId(), user, entityId, scope, keys, t); |
|||
} catch (ThingsboardException e) { |
|||
log.error("Failed to log attribute delete", e); |
|||
} |
|||
resultFuture.setException(t); |
|||
} |
|||
}); |
|||
} else { |
|||
resultFuture.set(null); |
|||
} |
|||
return resultFuture; |
|||
} |
|||
|
|||
private ListenableFuture<Void> deleteLatestFromEntityView(EntityView entityView, List<String> keys, SecurityUser user) { |
|||
EntityViewId entityId = entityView.getId(); |
|||
SettableFuture<Void> resultFuture = SettableFuture.create(); |
|||
if (keys != null && !keys.isEmpty()) { |
|||
tsSubService.deleteLatest(entityView.getTenantId(), entityId, keys, new FutureCallback<Void>() { |
|||
@Override |
|||
public void onSuccess(@Nullable Void tmp) { |
|||
try { |
|||
logTimeseriesDeleted(entityView.getTenantId(), user, entityId, keys, null); |
|||
} catch (ThingsboardException e) { |
|||
log.error("Failed to log timeseries delete", e); |
|||
} |
|||
resultFuture.set(tmp); |
|||
} |
|||
|
|||
@Override |
|||
public void onFailure(Throwable t) { |
|||
try { |
|||
logTimeseriesDeleted(entityView.getTenantId(),user, entityId, keys, t); |
|||
} catch (ThingsboardException e) { |
|||
log.error("Failed to log timeseries delete", e); |
|||
} |
|||
resultFuture.setException(t); |
|||
} |
|||
}); |
|||
} else { |
|||
tsSubService.deleteAllLatest(entityView.getTenantId(), entityId, new FutureCallback<Collection<String>>() { |
|||
@Override |
|||
public void onSuccess(@Nullable Collection<String> keys) { |
|||
try { |
|||
logTimeseriesDeleted(entityView.getTenantId(), user, entityId, new ArrayList<>(keys), null); |
|||
} catch (ThingsboardException e) { |
|||
log.error("Failed to log timeseries delete", e); |
|||
} |
|||
resultFuture.set(null); |
|||
} |
|||
|
|||
@Override |
|||
public void onFailure(Throwable t) { |
|||
try { |
|||
logTimeseriesDeleted(entityView.getTenantId(), user, entityId, Collections.emptyList(), t); |
|||
} catch (ThingsboardException e) { |
|||
log.error("Failed to log timeseries delete", e); |
|||
} |
|||
resultFuture.setException(t); |
|||
} |
|||
}); |
|||
} |
|||
return resultFuture; |
|||
} |
|||
|
|||
private void logAttributesUpdated(TenantId tenantId, SecurityUser user, EntityId entityId, String scope, List<AttributeKvEntry> attributes, Throwable e) throws ThingsboardException { |
|||
notificationEntityService.notifyEntity(tenantId, entityId, null, null, ActionType.ATTRIBUTES_UPDATED, user, toException(e), scope, attributes); |
|||
} |
|||
|
|||
private void logAttributesDeleted(TenantId tenantId, SecurityUser user, EntityId entityId, String scope, List<String> keys, Throwable e) throws ThingsboardException { |
|||
notificationEntityService.notifyEntity(tenantId, entityId, null, null, ActionType.ATTRIBUTES_DELETED, user, toException(e), scope, keys); |
|||
} |
|||
|
|||
private void logTimeseriesDeleted(TenantId tenantId, SecurityUser user, EntityId entityId, List<String> keys, Throwable e) throws ThingsboardException { |
|||
notificationEntityService.notifyEntity(tenantId, entityId, null, null, ActionType.TIMESERIES_DELETED, user, toException(e), keys); |
|||
} |
|||
|
|||
public static Exception toException(Throwable error) { |
|||
return error != null ? (Exception.class.isInstance(error) ? (Exception) error : new Exception(error)) : null; |
|||
} |
|||
} |
|||
@ -0,0 +1,47 @@ |
|||
/** |
|||
* Copyright © 2016-2022 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.entitiy.entityView; |
|||
|
|||
import org.thingsboard.server.common.data.Customer; |
|||
import org.thingsboard.server.common.data.EntityView; |
|||
import org.thingsboard.server.common.data.edge.Edge; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.id.CustomerId; |
|||
import org.thingsboard.server.common.data.id.EntityViewId; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
|
|||
public interface TbEntityViewService { |
|||
|
|||
EntityView save(EntityView entityView, EntityView existingEntityView, SecurityUser user) throws ThingsboardException; |
|||
|
|||
void delete (EntityView entity, SecurityUser user) throws ThingsboardException; |
|||
|
|||
EntityView assignEntityViewToCustomer(TenantId tenantId, EntityViewId entityViewId, Customer customer, |
|||
SecurityUser user) throws ThingsboardException; |
|||
|
|||
EntityView assignEntityViewToPublicCustomer(TenantId tenantId, CustomerId customerId, Customer publicCustomer, |
|||
EntityViewId entityViewId, SecurityUser user) throws ThingsboardException; |
|||
|
|||
EntityView assignEntityViewToEdge(TenantId tenantId, CustomerId customerId, EntityViewId entityViewId, Edge edge, |
|||
SecurityUser user) throws ThingsboardException; |
|||
|
|||
EntityView unassignEntityViewFromEdge(TenantId tenantId, CustomerId customerId, EntityView entityView, |
|||
Edge edge, SecurityUser user) throws ThingsboardException; |
|||
|
|||
EntityView unassignEntityViewFromCustomer(TenantId tenantId, EntityViewId entityViewId, Customer customer, |
|||
SecurityUser user) throws ThingsboardException; |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue