Browse Source

Merge pull request #13667 from AndriiLandiak/add-admin-settings-entity-type

Add entity type for admin settings
pull/13726/head
Viacheslav Klimov 1 year ago
committed by GitHub
parent
commit
4ff470088f
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 61
      application/src/main/java/org/thingsboard/server/controller/AdminController.java
  2. 183
      application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java
  3. 22
      application/src/main/java/org/thingsboard/server/service/mail/TbMailSender.java
  4. 3
      application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationSuccessHandler.java
  5. 2
      application/src/main/java/org/thingsboard/server/service/security/permission/Resource.java
  6. 16
      application/src/main/java/org/thingsboard/server/service/sms/DefaultSmsSenderFactory.java
  7. 12
      application/src/main/java/org/thingsboard/server/service/sms/DefaultSmsService.java
  8. 5
      common/dao-api/src/main/java/org/thingsboard/server/dao/settings/AdminSettingsService.java
  9. 6
      common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java
  10. 18
      common/data/src/main/java/org/thingsboard/server/common/data/id/AdminSettingsId.java
  11. 3
      common/data/src/main/java/org/thingsboard/server/common/data/id/EdgeId.java
  12. 4
      common/data/src/main/java/org/thingsboard/server/common/data/id/EntityId.java
  13. 190
      common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java
  14. 4
      common/data/src/main/java/org/thingsboard/server/common/data/id/JobId.java
  15. 2
      common/data/src/main/java/org/thingsboard/server/common/data/id/TenantId.java
  16. 12
      common/proto/src/main/java/org/thingsboard/server/common/util/ProtoUtils.java
  17. 1
      common/proto/src/main/proto/queue.proto
  18. 10
      dao/src/main/java/org/thingsboard/server/dao/oauth2/HybridClientRegistrationRepository.java
  19. 14
      dao/src/main/java/org/thingsboard/server/dao/settings/AdminSettingsDao.java
  20. 22
      dao/src/main/java/org/thingsboard/server/dao/settings/AdminSettingsServiceImpl.java
  21. 3
      dao/src/main/java/org/thingsboard/server/dao/sql/settings/AdminSettingsRepository.java
  22. 34
      dao/src/main/java/org/thingsboard/server/dao/sql/settings/JpaAdminSettingsDao.java
  23. 8
      dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java
  24. 1
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/TenantIdLoader.java
  25. 8
      rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/TenantIdLoaderTest.java

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

@ -37,14 +37,13 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize; 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.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult; import org.springframework.web.context.request.async.DeferredResult;
@ -125,14 +124,13 @@ public class AdminController extends BaseController {
@ApiOperation(value = "Get the Administration Settings object using key (getAdminSettings)", @ApiOperation(value = "Get the Administration Settings object using key (getAdminSettings)",
notes = "Get the Administration Settings object using specified string key. Referencing non-existing key will cause an error." + SYSTEM_AUTHORITY_PARAGRAPH) notes = "Get the Administration Settings object using specified string key. Referencing non-existing key will cause an error." + SYSTEM_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('SYS_ADMIN')") @PreAuthorize("hasAuthority('SYS_ADMIN')")
@RequestMapping(value = "/settings/{key}", method = RequestMethod.GET) @GetMapping(value = "/settings/{key}")
@ResponseBody
public AdminSettings getAdminSettings( public AdminSettings getAdminSettings(
@Parameter(description = "A string value of the key (e.g. 'general' or 'mail').") @Parameter(description = "A string value of the key (e.g. 'general' or 'mail').")
@PathVariable("key") String key) throws ThingsboardException { @PathVariable("key") String key) throws ThingsboardException {
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ); accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ);
AdminSettings adminSettings = checkNotNull(adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, key), "No Administration settings found for key: " + key); AdminSettings adminSettings = checkNotNull(adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, key), "No Administration settings found for key: " + key);
if (adminSettings.getKey().equals("mail")) { if (adminSettings.getKey().equals(MAIL_SETTINGS_KEY)) {
((ObjectNode) adminSettings.getJsonValue()).remove("password"); ((ObjectNode) adminSettings.getJsonValue()).remove("password");
((ObjectNode) adminSettings.getJsonValue()).remove("refreshToken"); ((ObjectNode) adminSettings.getJsonValue()).remove("refreshToken");
} }
@ -144,15 +142,14 @@ public class AdminController extends BaseController {
"The Administration Settings Id will be present in the response. Specify the Administration Settings Id when you would like to update the Administration Settings. " + "The Administration Settings Id will be present in the response. Specify the Administration Settings Id when you would like to update the Administration Settings. " +
"Referencing non-existing Administration Settings Id will cause an error." + SYSTEM_AUTHORITY_PARAGRAPH) "Referencing non-existing Administration Settings Id will cause an error." + SYSTEM_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('SYS_ADMIN')") @PreAuthorize("hasAuthority('SYS_ADMIN')")
@RequestMapping(value = "/settings", method = RequestMethod.POST) @PostMapping(value = "/settings")
@ResponseBody
public AdminSettings saveAdminSettings( public AdminSettings saveAdminSettings(
@Parameter(description = "A JSON value representing the Administration Settings.") @Parameter(description = "A JSON value representing the Administration Settings.")
@RequestBody AdminSettings adminSettings) throws ThingsboardException { @RequestBody AdminSettings adminSettings) throws ThingsboardException {
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.WRITE); accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.WRITE);
adminSettings.setTenantId(getTenantId()); adminSettings.setTenantId(getTenantId());
adminSettings = checkNotNull(adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, adminSettings)); adminSettings = checkNotNull(adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, adminSettings));
if (adminSettings.getKey().equals("mail")) { if (adminSettings.getKey().equals(MAIL_SETTINGS_KEY)) {
mailService.updateMailConfiguration(); mailService.updateMailConfiguration();
((ObjectNode) adminSettings.getJsonValue()).remove("password"); ((ObjectNode) adminSettings.getJsonValue()).remove("password");
((ObjectNode) adminSettings.getJsonValue()).remove("refreshToken"); ((ObjectNode) adminSettings.getJsonValue()).remove("refreshToken");
@ -165,8 +162,7 @@ public class AdminController extends BaseController {
@ApiOperation(value = "Get the Security Settings object (getSecuritySettings)", @ApiOperation(value = "Get the Security Settings object (getSecuritySettings)",
notes = "Get the Security Settings object that contains password policy, etc." + SYSTEM_AUTHORITY_PARAGRAPH) notes = "Get the Security Settings object that contains password policy, etc." + SYSTEM_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('SYS_ADMIN')") @PreAuthorize("hasAuthority('SYS_ADMIN')")
@RequestMapping(value = "/securitySettings", method = RequestMethod.GET) @GetMapping(value = "/securitySettings")
@ResponseBody
public SecuritySettings getSecuritySettings() throws ThingsboardException { public SecuritySettings getSecuritySettings() throws ThingsboardException {
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ); accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ);
return checkNotNull(securitySettingsService.getSecuritySettings()); return checkNotNull(securitySettingsService.getSecuritySettings());
@ -175,8 +171,7 @@ public class AdminController extends BaseController {
@ApiOperation(value = "Update Security Settings (saveSecuritySettings)", @ApiOperation(value = "Update Security Settings (saveSecuritySettings)",
notes = "Updates the Security Settings object that contains password policy, etc." + SYSTEM_AUTHORITY_PARAGRAPH) notes = "Updates the Security Settings object that contains password policy, etc." + SYSTEM_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('SYS_ADMIN')") @PreAuthorize("hasAuthority('SYS_ADMIN')")
@RequestMapping(value = "/securitySettings", method = RequestMethod.POST) @PostMapping(value = "/securitySettings")
@ResponseBody
public SecuritySettings saveSecuritySettings( public SecuritySettings saveSecuritySettings(
@Parameter(description = "A JSON value representing the Security Settings.") @Parameter(description = "A JSON value representing the Security Settings.")
@RequestBody SecuritySettings securitySettings) throws ThingsboardException { @RequestBody SecuritySettings securitySettings) throws ThingsboardException {
@ -188,8 +183,7 @@ public class AdminController extends BaseController {
@ApiOperation(value = "Get the JWT Settings object (getJwtSettings)", @ApiOperation(value = "Get the JWT Settings object (getJwtSettings)",
notes = "Get the JWT Settings object that contains JWT token policy, etc. " + SYSTEM_AUTHORITY_PARAGRAPH) notes = "Get the JWT Settings object that contains JWT token policy, etc. " + SYSTEM_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('SYS_ADMIN')") @PreAuthorize("hasAuthority('SYS_ADMIN')")
@RequestMapping(value = "/jwtSettings", method = RequestMethod.GET) @GetMapping(value = "/jwtSettings")
@ResponseBody
public JwtSettings getJwtSettings() throws ThingsboardException { public JwtSettings getJwtSettings() throws ThingsboardException {
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ); accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ);
return checkNotNull(jwtSettingsService.getJwtSettings()); return checkNotNull(jwtSettingsService.getJwtSettings());
@ -198,8 +192,7 @@ public class AdminController extends BaseController {
@ApiOperation(value = "Update JWT Settings (saveJwtSettings)", @ApiOperation(value = "Update JWT Settings (saveJwtSettings)",
notes = "Updates the JWT Settings object that contains JWT token policy, etc. The tokenSigningKey field is a Base64 encoded string." + SYSTEM_AUTHORITY_PARAGRAPH) notes = "Updates the JWT Settings object that contains JWT token policy, etc. The tokenSigningKey field is a Base64 encoded string." + SYSTEM_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('SYS_ADMIN')") @PreAuthorize("hasAuthority('SYS_ADMIN')")
@RequestMapping(value = "/jwtSettings", method = RequestMethod.POST) @PostMapping(value = "/jwtSettings")
@ResponseBody
public JwtPair saveJwtSettings( public JwtPair saveJwtSettings(
@Parameter(description = "A JSON value representing the JWT Settings.") @Parameter(description = "A JSON value representing the JWT Settings.")
@RequestBody JwtSettings jwtSettings) throws ThingsboardException { @RequestBody JwtSettings jwtSettings) throws ThingsboardException {
@ -213,15 +206,15 @@ public class AdminController extends BaseController {
notes = "Attempts to send test email to the System Administrator User using Mail Settings provided as a parameter. " + notes = "Attempts to send test email to the System Administrator User using Mail Settings provided as a parameter. " +
"You may change the 'To' email in the user profile of the System Administrator. " + SYSTEM_AUTHORITY_PARAGRAPH) "You may change the 'To' email in the user profile of the System Administrator. " + SYSTEM_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('SYS_ADMIN')") @PreAuthorize("hasAuthority('SYS_ADMIN')")
@RequestMapping(value = "/settings/testMail", method = RequestMethod.POST) @PostMapping(value = "/settings/testMail")
public void sendTestMail( public void sendTestMail(
@Parameter(description = "A JSON value representing the Mail Settings.") @Parameter(description = "A JSON value representing the Mail Settings.")
@RequestBody AdminSettings adminSettings) throws ThingsboardException { @RequestBody AdminSettings adminSettings) throws ThingsboardException {
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ); accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ);
adminSettings = checkNotNull(adminSettings); adminSettings = checkNotNull(adminSettings);
if (adminSettings.getKey().equals("mail")) { if (adminSettings.getKey().equals(MAIL_SETTINGS_KEY)) {
if (adminSettings.getJsonValue().has("enableOauth2") && adminSettings.getJsonValue().get("enableOauth2").asBoolean()) { if (adminSettings.getJsonValue().has("enableOauth2") && adminSettings.getJsonValue().get("enableOauth2").asBoolean()) {
AdminSettings mailSettings = checkNotNull(adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, "mail")); AdminSettings mailSettings = checkNotNull(adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, MAIL_SETTINGS_KEY));
JsonNode refreshToken = mailSettings.getJsonValue().get("refreshToken"); JsonNode refreshToken = mailSettings.getJsonValue().get("refreshToken");
if (refreshToken == null) { if (refreshToken == null) {
throw new ThingsboardException("Refresh token was not generated. Please, generate refresh token.", ThingsboardErrorCode.GENERAL); throw new ThingsboardException("Refresh token was not generated. Please, generate refresh token.", ThingsboardErrorCode.GENERAL);
@ -230,7 +223,7 @@ public class AdminController extends BaseController {
settings.put("refreshToken", refreshToken.asText()); settings.put("refreshToken", refreshToken.asText());
} else { } else {
if (!adminSettings.getJsonValue().has("password")) { if (!adminSettings.getJsonValue().has("password")) {
AdminSettings mailSettings = checkNotNull(adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, "mail")); AdminSettings mailSettings = checkNotNull(adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, MAIL_SETTINGS_KEY));
((ObjectNode) adminSettings.getJsonValue()).put("password", mailSettings.getJsonValue().get("password").asText()); ((ObjectNode) adminSettings.getJsonValue()).put("password", mailSettings.getJsonValue().get("password").asText());
} }
} }
@ -251,7 +244,7 @@ public class AdminController extends BaseController {
notes = "Attempts to send test sms to the System Administrator User using SMS Settings and phone number provided as a parameters of the request. " notes = "Attempts to send test sms to the System Administrator User using SMS Settings and phone number provided as a parameters of the request. "
+ SYSTEM_AUTHORITY_PARAGRAPH) + SYSTEM_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('SYS_ADMIN')") @PreAuthorize("hasAuthority('SYS_ADMIN')")
@RequestMapping(value = "/settings/testSms", method = RequestMethod.POST) @PostMapping(value = "/settings/testSms")
public void sendTestSms( public void sendTestSms(
@Parameter(description = "A JSON value representing the Test SMS request.") @Parameter(description = "A JSON value representing the Test SMS request.")
@RequestBody TestSmsRequest testSmsRequest) throws ThingsboardException { @RequestBody TestSmsRequest testSmsRequest) throws ThingsboardException {
@ -325,7 +318,7 @@ public class AdminController extends BaseController {
notes = "Deletes the repository settings." notes = "Deletes the repository settings."
+ TENANT_AUTHORITY_PARAGRAPH) + TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/repositorySettings", method = RequestMethod.DELETE) @DeleteMapping(value = "/repositorySettings")
@ResponseStatus(value = HttpStatus.OK) @ResponseStatus(value = HttpStatus.OK)
public DeferredResult<Void> deleteRepositorySettings() throws Exception { public DeferredResult<Void> deleteRepositorySettings() throws Exception {
accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.DELETE); accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.DELETE);
@ -335,7 +328,7 @@ public class AdminController extends BaseController {
@ApiOperation(value = "Check repository access (checkRepositoryAccess)", @ApiOperation(value = "Check repository access (checkRepositoryAccess)",
notes = "Attempts to check repository access. " + TENANT_AUTHORITY_PARAGRAPH) notes = "Attempts to check repository access. " + TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/repositorySettings/checkAccess", method = RequestMethod.POST) @PostMapping(value = "/repositorySettings/checkAccess")
public DeferredResult<Void> checkRepositoryAccess( public DeferredResult<Void> checkRepositoryAccess(
@Parameter(description = "A JSON value representing the Repository Settings.") @Parameter(description = "A JSON value representing the Repository Settings.")
@RequestBody RepositorySettings settings) throws Exception { @RequestBody RepositorySettings settings) throws Exception {
@ -376,7 +369,7 @@ public class AdminController extends BaseController {
notes = "Deletes the auto commit settings." notes = "Deletes the auto commit settings."
+ TENANT_AUTHORITY_PARAGRAPH) + TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/autoCommitSettings", method = RequestMethod.DELETE) @DeleteMapping(value = "/autoCommitSettings")
@ResponseStatus(value = HttpStatus.OK) @ResponseStatus(value = HttpStatus.OK)
public void deleteAutoCommitSettings() throws ThingsboardException { public void deleteAutoCommitSettings() throws ThingsboardException {
accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.DELETE); accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.DELETE);
@ -387,9 +380,8 @@ public class AdminController extends BaseController {
notes = "Check notifications about new platform releases. " notes = "Check notifications about new platform releases. "
+ SYSTEM_AUTHORITY_PARAGRAPH) + SYSTEM_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('SYS_ADMIN')") @PreAuthorize("hasAuthority('SYS_ADMIN')")
@RequestMapping(value = "/updates", method = RequestMethod.GET) @GetMapping(value = "/updates")
@ResponseBody public UpdateMessage checkUpdates() {
public UpdateMessage checkUpdates() throws ThingsboardException {
return updateService.checkUpdates(); return updateService.checkUpdates();
} }
@ -397,9 +389,8 @@ public class AdminController extends BaseController {
notes = "Get main information about system. " notes = "Get main information about system. "
+ SYSTEM_AUTHORITY_PARAGRAPH) + SYSTEM_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('SYS_ADMIN')") @PreAuthorize("hasAuthority('SYS_ADMIN')")
@RequestMapping(value = "/systemInfo", method = RequestMethod.GET) @GetMapping(value = "/systemInfo")
@ResponseBody public SystemInfo getSystemInfo() {
public SystemInfo getSystemInfo() throws ThingsboardException {
return systemInfoService.getSystemInfo(); return systemInfoService.getSystemInfo();
} }
@ -407,8 +398,7 @@ public class AdminController extends BaseController {
notes = "Get information about enabled/disabled features. " notes = "Get information about enabled/disabled features. "
+ SYSTEM_AUTHORITY_PARAGRAPH) + SYSTEM_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('SYS_ADMIN')") @PreAuthorize("hasAuthority('SYS_ADMIN')")
@RequestMapping(value = "/featuresInfo", method = RequestMethod.GET) @GetMapping(value = "/featuresInfo")
@ResponseBody
public FeaturesInfo getFeaturesInfo() { public FeaturesInfo getFeaturesInfo() {
return systemInfoService.getFeaturesInfo(); return systemInfoService.getFeaturesInfo();
} }
@ -417,8 +407,7 @@ public class AdminController extends BaseController {
"double quotes. After successful authentication with OAuth2 provider and user consent for requested scope, it makes a redirect to this path so that the platform can do " + "double quotes. After successful authentication with OAuth2 provider and user consent for requested scope, it makes a redirect to this path so that the platform can do " +
"further log in processing and generating access tokens. " + SYSTEM_AUTHORITY_PARAGRAPH) "further log in processing and generating access tokens. " + SYSTEM_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('SYS_ADMIN')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN')")
@RequestMapping(value = "/mail/oauth2/loginProcessingUrl", method = RequestMethod.GET) @GetMapping(value = "/mail/oauth2/loginProcessingUrl")
@ResponseBody
public String getMailProcessingUrl() throws ThingsboardException { public String getMailProcessingUrl() throws ThingsboardException {
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ); accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ);
return "\"/api/admin/mail/oauth2/code\""; return "\"/api/admin/mail/oauth2/code\"";
@ -427,7 +416,7 @@ public class AdminController extends BaseController {
@ApiOperation(value = "Redirect user to mail provider login page. ", notes = "After user logged in and provided access" + @ApiOperation(value = "Redirect user to mail provider login page. ", notes = "After user logged in and provided access" +
"provider sends authorization code to specified redirect uri.)") "provider sends authorization code to specified redirect uri.)")
@PreAuthorize("hasAuthority('SYS_ADMIN')") @PreAuthorize("hasAuthority('SYS_ADMIN')")
@RequestMapping(value = "/mail/oauth2/authorize", method = RequestMethod.GET, produces = "application/text") @GetMapping(value = "/mail/oauth2/authorize", produces = "application/text")
public String getAuthorizationUrl(HttpServletRequest request, HttpServletResponse response) throws ThingsboardException { public String getAuthorizationUrl(HttpServletRequest request, HttpServletResponse response) throws ThingsboardException {
String state = StringUtils.generateSafeToken(); String state = StringUtils.generateSafeToken();
if (request.getParameter(PREV_URI_PATH_PARAMETER) != null) { if (request.getParameter(PREV_URI_PATH_PARAMETER) != null) {
@ -452,7 +441,7 @@ public class AdminController extends BaseController {
.build() + "\""; .build() + "\"";
} }
@RequestMapping(value = "/mail/oauth2/code", params = {"code", "state"}, method = RequestMethod.GET) @GetMapping(value = "/mail/oauth2/code", params = {"code", "state"})
public void codeProcessingUrl( public void codeProcessingUrl(
@RequestParam(value = "code") String code, @RequestParam(value = "state") String state, @RequestParam(value = "code") String code, @RequestParam(value = "state") String state,
HttpServletRequest request, HttpServletResponse response) throws ThingsboardException, IOException { HttpServletRequest request, HttpServletResponse response) throws ThingsboardException, IOException {

183
application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java

@ -22,9 +22,9 @@ import freemarker.template.Template;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy; import jakarta.annotation.PreDestroy;
import jakarta.mail.internet.MimeMessage; import jakarta.mail.internet.MimeMessage;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.MessageSource; import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
@ -64,55 +64,37 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
@Service
@Slf4j @Slf4j
@Service
@RequiredArgsConstructor
public class DefaultMailService implements MailService { public class DefaultMailService implements MailService {
public static final String TARGET_EMAIL = "targetEmail"; private static final String TARGET_EMAIL = "targetEmail";
public static final String UTF_8 = "UTF-8"; private static final String UTF_8 = "UTF-8";
private static final long DEFAULT_TIMEOUT = 10_000;
private final ScheduledExecutorService timeoutScheduler = ThingsBoardExecutors.newSingleThreadScheduledExecutor("mail-service-watchdog");
private final MessageSource messages; private final MessageSource messages;
private final Configuration freemarkerConfig; private final Configuration freemarkerConfig;
private final AdminSettingsService adminSettingsService; private final AdminSettingsService adminSettingsService;
private final TbApiUsageReportClient apiUsageClient; private final TbApiUsageReportClient apiUsageClient;
private static final long DEFAULT_TIMEOUT = 10_000;
@Lazy @Lazy
@Autowired private final TbApiUsageStateService apiUsageStateService;
private TbApiUsageStateService apiUsageStateService; private final MailSenderInternalExecutorService mailExecutorService;
private final PasswordResetExecutorService passwordResetExecutorService;
@Autowired private final TbMailContextComponent ctx;
private MailSenderInternalExecutorService mailExecutorService; private final RateLimitService rateLimitService;
@Autowired
private PasswordResetExecutorService passwordResetExecutorService;
@Autowired
private TbMailContextComponent ctx;
@Autowired
private RateLimitService rateLimitService;
@Value("${mail.per_tenant_rate_limits:}") @Value("${mail.per_tenant_rate_limits:}")
private String perTenantRateLimitConfig; private String perTenantRateLimitConfig;
private final ScheduledExecutorService timeoutScheduler;
private TbMailSender mailSender; private TbMailSender mailSender;
private String mailFrom; private String mailFrom;
private long timeout; private long timeout;
public DefaultMailService(MessageSource messages, Configuration freemarkerConfig, AdminSettingsService adminSettingsService, TbApiUsageReportClient apiUsageClient) {
this.messages = messages;
this.freemarkerConfig = freemarkerConfig;
this.adminSettingsService = adminSettingsService;
this.apiUsageClient = apiUsageClient;
this.timeoutScheduler = ThingsBoardExecutors.newSingleThreadScheduledExecutor("mail-service-watchdog");
}
@PostConstruct @PostConstruct
private void init() { private void init() {
updateMailConfiguration(); updateMailConfiguration();
@ -120,9 +102,7 @@ public class DefaultMailService implements MailService {
@PreDestroy @PreDestroy
public void destroy() { public void destroy() {
if (timeoutScheduler != null) { timeoutScheduler.shutdownNow();
timeoutScheduler.shutdownNow();
}
} }
@Override @Override
@ -311,22 +291,21 @@ public class DefaultMailService implements MailService {
model.put("apiFeature", apiFeature.getLabel()); model.put("apiFeature", apiFeature.getLabel());
model.put(TARGET_EMAIL, email); model.put(TARGET_EMAIL, email);
String message = null; String message = switch (stateValue) {
case ENABLED -> {
switch (stateValue) {
case ENABLED:
model.put("apiLabel", toEnabledValueLabel(apiFeature)); model.put("apiLabel", toEnabledValueLabel(apiFeature));
message = mergeTemplateIntoString("state.enabled.ftl", model); yield mergeTemplateIntoString("state.enabled.ftl", model);
break; }
case WARNING: case WARNING -> {
model.put("apiValueLabel", toDisabledValueLabel(apiFeature) + " " + toWarningValueLabel(recordState)); model.put("apiValueLabel", toDisabledValueLabel(apiFeature) + " " + toWarningValueLabel(recordState));
message = mergeTemplateIntoString("state.warning.ftl", model); yield mergeTemplateIntoString("state.warning.ftl", model);
break; }
case DISABLED: case DISABLED -> {
model.put("apiLimitValueLabel", toDisabledValueLabel(apiFeature) + " " + toDisabledValueLabel(recordState)); model.put("apiLimitValueLabel", toDisabledValueLabel(apiFeature) + " " + toDisabledValueLabel(recordState));
message = mergeTemplateIntoString("state.disabled.ftl", model); yield mergeTemplateIntoString("state.disabled.ftl", model);
break; }
} };
sendMail(mailSender, mailFrom, email, subject, message, timeout); sendMail(mailSender, mailFrom, email, subject, message, timeout);
} }
@ -341,89 +320,55 @@ public class DefaultMailService implements MailService {
} }
private String toEnabledValueLabel(ApiFeature apiFeature) { private String toEnabledValueLabel(ApiFeature apiFeature) {
switch (apiFeature) { return switch (apiFeature) {
case DB: case DB -> "save";
return "save"; case TRANSPORT -> "receive";
case TRANSPORT: case JS -> "invoke";
return "receive"; case RE -> "process";
case JS: case EMAIL, SMS -> "send";
return "invoke"; case ALARM -> "create";
case RE: default -> throw new RuntimeException("Not implemented!");
return "process"; };
case EMAIL:
case SMS:
return "send";
case ALARM:
return "create";
default:
throw new RuntimeException("Not implemented!");
}
} }
private String toDisabledValueLabel(ApiFeature apiFeature) { private String toDisabledValueLabel(ApiFeature apiFeature) {
switch (apiFeature) { return switch (apiFeature) {
case DB: case DB -> "saved";
return "saved"; case TRANSPORT -> "received";
case TRANSPORT: case JS -> "invoked";
return "received"; case RE -> "processed";
case JS: case EMAIL, SMS -> "sent";
return "invoked"; case ALARM -> "created";
case RE: default -> throw new RuntimeException("Not implemented!");
return "processed"; };
case EMAIL:
case SMS:
return "sent";
case ALARM:
return "created";
default:
throw new RuntimeException("Not implemented!");
}
} }
private String toWarningValueLabel(ApiUsageRecordState recordState) { private String toWarningValueLabel(ApiUsageRecordState recordState) {
String valueInM = recordState.getValueAsString(); String valueInM = recordState.getValueAsString();
String thresholdInM = recordState.getThresholdAsString(); String thresholdInM = recordState.getThresholdAsString();
switch (recordState.getKey()) { return switch (recordState.getKey()) {
case STORAGE_DP_COUNT: case STORAGE_DP_COUNT, TRANSPORT_DP_COUNT -> valueInM + " out of " + thresholdInM + " allowed data points";
case TRANSPORT_DP_COUNT: case TRANSPORT_MSG_COUNT -> valueInM + " out of " + thresholdInM + " allowed messages";
return valueInM + " out of " + thresholdInM + " allowed data points"; case JS_EXEC_COUNT -> valueInM + " out of " + thresholdInM + " allowed JavaScript functions";
case TRANSPORT_MSG_COUNT: case TBEL_EXEC_COUNT -> valueInM + " out of " + thresholdInM + " allowed Tbel functions";
return valueInM + " out of " + thresholdInM + " allowed messages"; case RE_EXEC_COUNT -> valueInM + " out of " + thresholdInM + " allowed Rule Engine messages";
case JS_EXEC_COUNT: case EMAIL_EXEC_COUNT -> valueInM + " out of " + thresholdInM + " allowed Email messages";
return valueInM + " out of " + thresholdInM + " allowed JavaScript functions"; case SMS_EXEC_COUNT -> valueInM + " out of " + thresholdInM + " allowed SMS messages";
case TBEL_EXEC_COUNT: default -> throw new RuntimeException("Not implemented!");
return valueInM + " out of " + thresholdInM + " allowed Tbel functions"; };
case RE_EXEC_COUNT:
return valueInM + " out of " + thresholdInM + " allowed Rule Engine messages";
case EMAIL_EXEC_COUNT:
return valueInM + " out of " + thresholdInM + " allowed Email messages";
case SMS_EXEC_COUNT:
return valueInM + " out of " + thresholdInM + " allowed SMS messages";
default:
throw new RuntimeException("Not implemented!");
}
} }
private String toDisabledValueLabel(ApiUsageRecordState recordState) { private String toDisabledValueLabel(ApiUsageRecordState recordState) {
switch (recordState.getKey()) { return switch (recordState.getKey()) {
case STORAGE_DP_COUNT: case STORAGE_DP_COUNT, TRANSPORT_DP_COUNT -> recordState.getValueAsString() + " data points";
case TRANSPORT_DP_COUNT: case TRANSPORT_MSG_COUNT -> recordState.getValueAsString() + " messages";
return recordState.getValueAsString() + " data points"; case JS_EXEC_COUNT -> "JavaScript functions " + recordState.getValueAsString() + " times";
case TRANSPORT_MSG_COUNT: case TBEL_EXEC_COUNT -> "TBEL functions " + recordState.getValueAsString() + " times";
return recordState.getValueAsString() + " messages"; case RE_EXEC_COUNT -> recordState.getValueAsString() + " Rule Engine messages";
case JS_EXEC_COUNT: case EMAIL_EXEC_COUNT -> recordState.getValueAsString() + " Email messages";
return "JavaScript functions " + recordState.getValueAsString() + " times"; case SMS_EXEC_COUNT -> recordState.getValueAsString() + " SMS messages";
case TBEL_EXEC_COUNT: default -> throw new RuntimeException("Not implemented!");
return "TBEL functions " + recordState.getValueAsString() + " times"; };
case RE_EXEC_COUNT:
return recordState.getValueAsString() + " Rule Engine messages";
case EMAIL_EXEC_COUNT:
return recordState.getValueAsString() + " Email messages";
case SMS_EXEC_COUNT:
return recordState.getValueAsString() + " SMS messages";
default:
throw new RuntimeException("Not implemented!");
}
} }
private void sendMail(JavaMailSenderImpl mailSender, String mailFrom, String email, private void sendMail(JavaMailSenderImpl mailSender, String mailFrom, String email,

22
application/src/main/java/org/thingsboard/server/service/mail/TbMailSender.java

@ -25,6 +25,7 @@ import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.gson.GsonFactory; import com.google.api.client.json.gson.GsonFactory;
import jakarta.mail.MessagingException; import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage; import jakarta.mail.internet.MimeMessage;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.mail.MailException; import org.springframework.mail.MailException;
@ -50,8 +51,10 @@ public class TbMailSender extends JavaMailSenderImpl {
private final TbMailContextComponent ctx; private final TbMailContextComponent ctx;
private final Lock lock; private final Lock lock;
@Getter
private final Boolean oauth2Enabled; private final Boolean oauth2Enabled;
private volatile String accessToken; private volatile String accessToken;
@Getter
private volatile long tokenExpires; private volatile long tokenExpires;
public TbMailSender(TbMailContextComponent ctx, JsonNode jsonConfig) { public TbMailSender(TbMailContextComponent ctx, JsonNode jsonConfig) {
@ -70,14 +73,6 @@ public class TbMailSender extends JavaMailSenderImpl {
setJavaMailProperties(createJavaMailProperties(jsonConfig)); setJavaMailProperties(createJavaMailProperties(jsonConfig));
} }
public Boolean getOauth2Enabled() {
return oauth2Enabled;
}
public long getTokenExpires() {
return tokenExpires;
}
@Override @Override
protected void doSend(MimeMessage[] mimeMessages, @Nullable Object[] originalMessages) throws MailException { protected void doSend(MimeMessage[] mimeMessages, @Nullable Object[] originalMessages) throws MailException {
updateOauth2PasswordIfExpired(); updateOauth2PasswordIfExpired();
@ -98,8 +93,8 @@ public class TbMailSender extends JavaMailSenderImpl {
super.testConnection(); super.testConnection();
} }
public void updateOauth2PasswordIfExpired() { public void updateOauth2PasswordIfExpired() {
if (getOauth2Enabled() && (System.currentTimeMillis() > getTokenExpires())){ if (getOauth2Enabled() && (System.currentTimeMillis() > getTokenExpires())) {
refreshAccessToken(); refreshAccessToken();
setPassword(accessToken); setPassword(accessToken);
} }
@ -168,8 +163,8 @@ public class TbMailSender extends JavaMailSenderImpl {
.setClientAuthentication(new ClientParametersAuthentication(clientId, clientSecret)) .setClientAuthentication(new ClientParametersAuthentication(clientId, clientSecret))
.execute(); .execute();
if (MailOauth2Provider.OFFICE_365.name().equals(providerId)) { if (MailOauth2Provider.OFFICE_365.name().equals(providerId)) {
((ObjectNode)jsonValue).put("refreshToken", tokenResponse.getRefreshToken()); ((ObjectNode) jsonValue).put("refreshToken", tokenResponse.getRefreshToken());
((ObjectNode)jsonValue).put("refreshTokenExpires", Instant.now().plus(Duration.ofDays(AZURE_DEFAULT_REFRESH_TOKEN_LIFETIME_IN_DAYS)).toEpochMilli()); ((ObjectNode) jsonValue).put("refreshTokenExpires", Instant.now().plus(Duration.ofDays(AZURE_DEFAULT_REFRESH_TOKEN_LIFETIME_IN_DAYS)).toEpochMilli());
ctx.getAdminSettingsService().saveAdminSettings(TenantId.SYS_TENANT_ID, settings); ctx.getAdminSettingsService().saveAdminSettings(TenantId.SYS_TENANT_ID, settings);
} }
accessToken = tokenResponse.getAccessToken(); accessToken = tokenResponse.getAccessToken();
@ -190,4 +185,5 @@ public class TbMailSender extends JavaMailSenderImpl {
throw new IncorrectParameterException(String.format("Invalid smtp port value: %s", strPort)); throw new IncorrectParameterException(String.format("Invalid smtp port value: %s", strPort));
} }
} }
}
}

3
application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationSuccessHandler.java

@ -121,7 +121,7 @@ public class Oauth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationS
errorPrefix = "/login?loginError="; errorPrefix = "/login?loginError=";
} }
getRedirectStrategy().sendRedirect(request, response, baseUrl + errorPrefix + getRedirectStrategy().sendRedirect(request, response, baseUrl + errorPrefix +
URLEncoder.encode(e.getMessage(), StandardCharsets.UTF_8.toString())); URLEncoder.encode(e.getMessage(), StandardCharsets.UTF_8));
} }
} }
@ -138,4 +138,5 @@ public class Oauth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationS
} }
return baseUrl + "accessToken=" + tokenPair.getToken() + "&refreshToken=" + tokenPair.getRefreshToken(); return baseUrl + "accessToken=" + tokenPair.getToken() + "&refreshToken=" + tokenPair.getRefreshToken();
} }
} }

2
application/src/main/java/org/thingsboard/server/service/security/permission/Resource.java

@ -21,7 +21,7 @@ import java.util.Collections;
import java.util.Set; import java.util.Set;
public enum Resource { public enum Resource {
ADMIN_SETTINGS(), ADMIN_SETTINGS(EntityType.ADMIN_SETTINGS),
ALARM(EntityType.ALARM), ALARM(EntityType.ALARM),
DEVICE(EntityType.DEVICE), DEVICE(EntityType.DEVICE),
ASSET(EntityType.ASSET), ASSET(EntityType.ASSET),

16
application/src/main/java/org/thingsboard/server/service/sms/DefaultSmsSenderFactory.java

@ -31,16 +31,12 @@ public class DefaultSmsSenderFactory implements SmsSenderFactory {
@Override @Override
public SmsSender createSmsSender(SmsProviderConfiguration config) { public SmsSender createSmsSender(SmsProviderConfiguration config) {
switch (config.getType()) { return switch (config.getType()) {
case AWS_SNS: case AWS_SNS -> new AwsSmsSender((AwsSnsSmsProviderConfiguration) config);
return new AwsSmsSender((AwsSnsSmsProviderConfiguration)config); case TWILIO -> new TwilioSmsSender((TwilioSmsProviderConfiguration) config);
case TWILIO: case SMPP -> new SmppSmsSender((SmppSmsProviderConfiguration) config);
return new TwilioSmsSender((TwilioSmsProviderConfiguration)config); default -> throw new RuntimeException("Unknown SMS provider type " + config.getType());
case SMPP: };
return new SmppSmsSender((SmppSmsProviderConfiguration) config);
default:
throw new RuntimeException("Unknown SMS provider type " + config.getType());
}
} }
} }

12
application/src/main/java/org/thingsboard/server/service/sms/DefaultSmsService.java

@ -18,6 +18,7 @@ package org.thingsboard.server.service.sms;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy; import jakarta.annotation.PreDestroy;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.core.NestedRuntimeException; import org.springframework.core.NestedRuntimeException;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -37,8 +38,9 @@ import org.thingsboard.server.common.stats.TbApiUsageReportClient;
import org.thingsboard.server.dao.settings.AdminSettingsService; import org.thingsboard.server.dao.settings.AdminSettingsService;
import org.thingsboard.server.service.apiusage.TbApiUsageStateService; import org.thingsboard.server.service.apiusage.TbApiUsageStateService;
@Service
@Slf4j @Slf4j
@Service
@RequiredArgsConstructor
public class DefaultSmsService implements SmsService { public class DefaultSmsService implements SmsService {
private final SmsSenderFactory smsSenderFactory; private final SmsSenderFactory smsSenderFactory;
@ -48,13 +50,6 @@ public class DefaultSmsService implements SmsService {
private SmsSender smsSender; private SmsSender smsSender;
public DefaultSmsService(SmsSenderFactory smsSenderFactory, AdminSettingsService adminSettingsService, TbApiUsageStateService apiUsageStateService, TbApiUsageReportClient apiUsageClient) {
this.smsSenderFactory = smsSenderFactory;
this.adminSettingsService = adminSettingsService;
this.apiUsageStateService = apiUsageStateService;
this.apiUsageClient = apiUsageClient;
}
@PostConstruct @PostConstruct
private void init() { private void init() {
updateSmsConfiguration(); updateSmsConfiguration();
@ -148,4 +143,5 @@ public class DefaultSmsService implements SmsService {
return new ThingsboardException(String.format("Unable to send SMS: %s", message), return new ThingsboardException(String.format("Unable to send SMS: %s", message),
ThingsboardErrorCode.GENERAL); ThingsboardErrorCode.GENERAL);
} }
} }

5
common/dao-api/src/main/java/org/thingsboard/server/dao/settings/AdminSettingsService.java

@ -18,8 +18,9 @@ package org.thingsboard.server.dao.settings;
import org.thingsboard.server.common.data.AdminSettings; import org.thingsboard.server.common.data.AdminSettings;
import org.thingsboard.server.common.data.id.AdminSettingsId; import org.thingsboard.server.common.data.id.AdminSettingsId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.entity.EntityDaoService;
public interface AdminSettingsService { public interface AdminSettingsService extends EntityDaoService {
AdminSettings findAdminSettingsById(TenantId tenantId, AdminSettingsId adminSettingsId); AdminSettings findAdminSettingsById(TenantId tenantId, AdminSettingsId adminSettingsId);
@ -31,6 +32,4 @@ public interface AdminSettingsService {
boolean deleteAdminSettingsByTenantIdAndKey(TenantId tenantId, String key); boolean deleteAdminSettingsByTenantIdAndKey(TenantId tenantId, String key);
void deleteAdminSettingsByTenantId(TenantId tenantId);
} }

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

@ -22,9 +22,6 @@ import java.util.Arrays;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
/**
* @author Andrew Shvayka
*/
public enum EntityType { public enum EntityType {
TENANT(1), TENANT(1),
CUSTOMER(2), CUSTOMER(2),
@ -65,7 +62,8 @@ public enum EntityType {
MOBILE_APP_BUNDLE(38), MOBILE_APP_BUNDLE(38),
CALCULATED_FIELD(39), CALCULATED_FIELD(39),
CALCULATED_FIELD_LINK(40), CALCULATED_FIELD_LINK(40),
JOB(41); JOB(41),
ADMIN_SETTINGS(42);
@Getter @Getter
private final int protoNumber; // Corresponds to EntityTypeProto private final int protoNumber; // Corresponds to EntityTypeProto

18
common/data/src/main/java/org/thingsboard/server/common/data/id/AdminSettingsId.java

@ -17,14 +17,26 @@ package org.thingsboard.server.common.data.id;
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import org.thingsboard.server.common.data.EntityType;
import java.io.Serial;
import java.util.UUID; import java.util.UUID;
public class AdminSettingsId extends UUIDBased { public class AdminSettingsId extends UUIDBased implements EntityId {
@Serial
private static final long serialVersionUID = -4208011957475806567L;
@JsonCreator @JsonCreator
public AdminSettingsId(@JsonProperty("id") UUID id){ public AdminSettingsId(@JsonProperty("id") UUID id) {
super(id); super(id);
} }
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, description = "string", example = "ADMIN_SETTINGS", allowableValues = "ADMIN_SETTINGS")
@Override
public EntityType getEntityType() {
return EntityType.ADMIN_SETTINGS;
}
} }

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

@ -23,10 +23,12 @@ import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.ConcurrentReferenceHashMap.ReferenceType; import org.springframework.util.ConcurrentReferenceHashMap.ReferenceType;
import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityType;
import java.io.Serial;
import java.util.UUID; import java.util.UUID;
public class EdgeId extends UUIDBased implements EntityId { public class EdgeId extends UUIDBased implements EntityId {
@Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@JsonIgnore @JsonIgnore
@ -51,4 +53,5 @@ public class EdgeId extends UUIDBased implements EntityId {
public static EdgeId fromUUID(@JsonProperty("id") UUID id) { public static EdgeId fromUUID(@JsonProperty("id") UUID id) {
return edges.computeIfAbsent(id, EdgeId::new); return edges.computeIfAbsent(id, EdgeId::new);
} }
} }

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

@ -24,10 +24,6 @@ import org.thingsboard.server.common.data.EntityType;
import java.io.Serializable; import java.io.Serializable;
import java.util.UUID; import java.util.UUID;
/**
* @author Andrew Shvayka
*/
@JsonDeserialize(using = EntityIdDeserializer.class) @JsonDeserialize(using = EntityIdDeserializer.class)
@JsonSerialize(using = EntityIdSerializer.class) @JsonSerialize(using = EntityIdSerializer.class)
@Schema @Schema

190
common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java

@ -20,9 +20,6 @@ import org.thingsboard.server.common.data.edge.EdgeEventType;
import java.util.UUID; import java.util.UUID;
/**
* Created by ashvayka on 25.04.17.
*/
public class EntityIdFactory { public class EntityIdFactory {
public static EntityId getByTypeAndUuid(int type, String uuid) { public static EntityId getByTypeAndUuid(int type, String uuid) {
@ -50,131 +47,74 @@ public class EntityIdFactory {
} }
public static EntityId getByTypeAndUuid(EntityType type, UUID uuid) { public static EntityId getByTypeAndUuid(EntityType type, UUID uuid) {
switch (type) { return switch (type) {
case TENANT: case TENANT -> TenantId.fromUUID(uuid);
return TenantId.fromUUID(uuid); case CUSTOMER -> new CustomerId(uuid);
case CUSTOMER: case USER -> new UserId(uuid);
return new CustomerId(uuid); case DASHBOARD -> new DashboardId(uuid);
case USER: case DEVICE -> new DeviceId(uuid);
return new UserId(uuid); case ASSET -> new AssetId(uuid);
case DASHBOARD: case ALARM -> new AlarmId(uuid);
return new DashboardId(uuid); case RULE_CHAIN -> new RuleChainId(uuid);
case DEVICE: case RULE_NODE -> new RuleNodeId(uuid);
return new DeviceId(uuid); case ENTITY_VIEW -> new EntityViewId(uuid);
case ASSET: case WIDGETS_BUNDLE -> new WidgetsBundleId(uuid);
return new AssetId(uuid); case WIDGET_TYPE -> new WidgetTypeId(uuid);
case ALARM: case DEVICE_PROFILE -> new DeviceProfileId(uuid);
return new AlarmId(uuid); case ASSET_PROFILE -> new AssetProfileId(uuid);
case RULE_CHAIN: case TENANT_PROFILE -> new TenantProfileId(uuid);
return new RuleChainId(uuid); case API_USAGE_STATE -> new ApiUsageStateId(uuid);
case RULE_NODE: case TB_RESOURCE -> new TbResourceId(uuid);
return new RuleNodeId(uuid); case OTA_PACKAGE -> new OtaPackageId(uuid);
case ENTITY_VIEW: case EDGE -> EdgeId.fromUUID(uuid);
return new EntityViewId(uuid); case RPC -> new RpcId(uuid);
case WIDGETS_BUNDLE: case QUEUE -> new QueueId(uuid);
return new WidgetsBundleId(uuid); case NOTIFICATION_TARGET -> new NotificationTargetId(uuid);
case WIDGET_TYPE: case NOTIFICATION_REQUEST -> new NotificationRequestId(uuid);
return new WidgetTypeId(uuid); case NOTIFICATION_RULE -> new NotificationRuleId(uuid);
case DEVICE_PROFILE: case NOTIFICATION_TEMPLATE -> new NotificationTemplateId(uuid);
return new DeviceProfileId(uuid); case NOTIFICATION -> new NotificationId(uuid);
case ASSET_PROFILE: case QUEUE_STATS -> new QueueStatsId(uuid);
return new AssetProfileId(uuid); case OAUTH2_CLIENT -> new OAuth2ClientId(uuid);
case TENANT_PROFILE: case MOBILE_APP -> new MobileAppId(uuid);
return new TenantProfileId(uuid); case DOMAIN -> new DomainId(uuid);
case API_USAGE_STATE: case MOBILE_APP_BUNDLE -> new MobileAppBundleId(uuid);
return new ApiUsageStateId(uuid); case CALCULATED_FIELD -> new CalculatedFieldId(uuid);
case TB_RESOURCE: case CALCULATED_FIELD_LINK -> new CalculatedFieldLinkId(uuid);
return new TbResourceId(uuid); case JOB -> new JobId(uuid);
case OTA_PACKAGE: case ADMIN_SETTINGS -> new AdminSettingsId(uuid);
return new OtaPackageId(uuid); default -> throw new IllegalArgumentException("EntityType " + type + " is not supported!");
case EDGE: };
return new EdgeId(uuid);
case RPC:
return new RpcId(uuid);
case QUEUE:
return new QueueId(uuid);
case NOTIFICATION_TARGET:
return new NotificationTargetId(uuid);
case NOTIFICATION_REQUEST:
return new NotificationRequestId(uuid);
case NOTIFICATION_RULE:
return new NotificationRuleId(uuid);
case NOTIFICATION_TEMPLATE:
return new NotificationTemplateId(uuid);
case NOTIFICATION:
return new NotificationId(uuid);
case QUEUE_STATS:
return new QueueStatsId(uuid);
case OAUTH2_CLIENT:
return new OAuth2ClientId(uuid);
case MOBILE_APP:
return new MobileAppId(uuid);
case DOMAIN:
return new DomainId(uuid);
case MOBILE_APP_BUNDLE:
return new MobileAppBundleId(uuid);
case CALCULATED_FIELD:
return new CalculatedFieldId(uuid);
case CALCULATED_FIELD_LINK:
return new CalculatedFieldLinkId(uuid);
case JOB:
return new JobId(uuid);
}
throw new IllegalArgumentException("EntityType " + type + " is not supported!");
} }
public static EntityId getByEdgeEventTypeAndUuid(EdgeEventType edgeEventType, UUID uuid) { public static EntityId getByEdgeEventTypeAndUuid(EdgeEventType edgeEventType, UUID uuid) {
switch (edgeEventType) { return switch (edgeEventType) {
case TENANT: case TENANT -> TenantId.fromUUID(uuid);
return TenantId.fromUUID(uuid); case CUSTOMER -> new CustomerId(uuid);
case CUSTOMER: case USER -> new UserId(uuid);
return new CustomerId(uuid); case DASHBOARD -> new DashboardId(uuid);
case USER: case DEVICE -> new DeviceId(uuid);
return new UserId(uuid); case ASSET -> new AssetId(uuid);
case DASHBOARD: case ALARM -> new AlarmId(uuid);
return new DashboardId(uuid); case RULE_CHAIN -> new RuleChainId(uuid);
case DEVICE: case ENTITY_VIEW -> new EntityViewId(uuid);
return new DeviceId(uuid); case WIDGETS_BUNDLE -> new WidgetsBundleId(uuid);
case ASSET: case WIDGET_TYPE -> new WidgetTypeId(uuid);
return new AssetId(uuid); case DEVICE_PROFILE -> new DeviceProfileId(uuid);
case ALARM: case ASSET_PROFILE -> new AssetProfileId(uuid);
return new AlarmId(uuid); case TENANT_PROFILE -> new TenantProfileId(uuid);
case RULE_CHAIN: case OTA_PACKAGE -> new OtaPackageId(uuid);
return new RuleChainId(uuid); case EDGE -> EdgeId.fromUUID(uuid);
case ENTITY_VIEW: case QUEUE -> new QueueId(uuid);
return new EntityViewId(uuid); case TB_RESOURCE -> new TbResourceId(uuid);
case WIDGETS_BUNDLE: case NOTIFICATION_RULE -> new NotificationRuleId(uuid);
return new WidgetsBundleId(uuid); case NOTIFICATION_TARGET -> new NotificationTargetId(uuid);
case WIDGET_TYPE: case NOTIFICATION_TEMPLATE -> new NotificationTemplateId(uuid);
return new WidgetTypeId(uuid); case OAUTH2_CLIENT -> new OAuth2ClientId(uuid);
case DEVICE_PROFILE: case DOMAIN -> new DomainId(uuid);
return new DeviceProfileId(uuid); case CALCULATED_FIELD -> new CalculatedFieldId(uuid);
case ASSET_PROFILE: default -> throw new IllegalArgumentException("EdgeEventType " + edgeEventType + " is not supported!");
return new AssetProfileId(uuid); };
case TENANT_PROFILE:
return new TenantProfileId(uuid);
case OTA_PACKAGE:
return new OtaPackageId(uuid);
case EDGE:
return new EdgeId(uuid);
case QUEUE:
return new QueueId(uuid);
case TB_RESOURCE:
return new TbResourceId(uuid);
case NOTIFICATION_RULE:
return new NotificationRuleId(uuid);
case NOTIFICATION_TARGET:
return new NotificationTargetId(uuid);
case NOTIFICATION_TEMPLATE:
return new NotificationTemplateId(uuid);
case OAUTH2_CLIENT:
return new OAuth2ClientId(uuid);
case DOMAIN:
return new DomainId(uuid);
case CALCULATED_FIELD:
return new CalculatedFieldId(uuid);
}
throw new IllegalArgumentException("EdgeEventType " + edgeEventType + " is not supported!");
} }
} }

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

@ -20,10 +20,14 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityType;
import java.io.Serial;
import java.util.UUID; import java.util.UUID;
public class JobId extends UUIDBased implements EntityId { public class JobId extends UUIDBased implements EntityId {
@Serial
private static final long serialVersionUID = -2225072123132918395L;
@JsonCreator @JsonCreator
public JobId(@JsonProperty("id") UUID id) { public JobId(@JsonProperty("id") UUID id) {
super(id); super(id);

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

@ -23,6 +23,7 @@ import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.ConcurrentReferenceHashMap.ReferenceType; import org.springframework.util.ConcurrentReferenceHashMap.ReferenceType;
import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityType;
import java.io.Serial;
import java.util.UUID; import java.util.UUID;
public final class TenantId extends UUIDBased implements EntityId { public final class TenantId extends UUIDBased implements EntityId {
@ -33,6 +34,7 @@ public final class TenantId extends UUIDBased implements EntityId {
@JsonIgnore @JsonIgnore
public static final TenantId SYS_TENANT_ID = TenantId.fromUUID(EntityId.NULL_UUID); public static final TenantId SYS_TENANT_ID = TenantId.fromUUID(EntityId.NULL_UUID);
@Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@JsonCreator @JsonCreator

12
common/proto/src/main/java/org/thingsboard/server/common/util/ProtoUtils.java

@ -252,7 +252,7 @@ public class ProtoUtils {
public static EdgeEvent fromProto(TransportProtos.EdgeEventMsgProto proto) { public static EdgeEvent fromProto(TransportProtos.EdgeEventMsgProto proto) {
EdgeEvent edgeEvent = new EdgeEvent(); EdgeEvent edgeEvent = new EdgeEvent();
TenantId tenantId = new TenantId(new UUID(proto.getTenantIdMSB(), proto.getTenantIdLSB())); TenantId tenantId = TenantId.fromUUID(new UUID(proto.getTenantIdMSB(), proto.getTenantIdLSB()));
edgeEvent.setTenantId(tenantId); edgeEvent.setTenantId(tenantId);
edgeEvent.setType(EdgeEventType.valueOf(proto.getEntityType())); edgeEvent.setType(EdgeEventType.valueOf(proto.getEntityType()));
edgeEvent.setAction(EdgeEventActionType.valueOf(proto.getAction())); edgeEvent.setAction(EdgeEventActionType.valueOf(proto.getAction()));
@ -845,7 +845,7 @@ public class ProtoUtils {
public static Device fromProto(TransportProtos.DeviceProto proto) { public static Device fromProto(TransportProtos.DeviceProto proto) {
Device device = new Device(getEntityId(proto.getDeviceIdMSB(), proto.getDeviceIdLSB(), DeviceId::new)); Device device = new Device(getEntityId(proto.getDeviceIdMSB(), proto.getDeviceIdLSB(), DeviceId::new));
device.setCreatedTime(proto.getCreatedTime()); device.setCreatedTime(proto.getCreatedTime());
device.setTenantId(getEntityId(proto.getTenantIdMSB(), proto.getTenantIdLSB(), TenantId::new)); device.setTenantId(getEntityId(proto.getTenantIdMSB(), proto.getTenantIdLSB(), TenantId::fromUUID));
device.setName(proto.getDeviceName()); device.setName(proto.getDeviceName());
device.setType(proto.getDeviceType()); device.setType(proto.getDeviceType());
device.setDeviceProfileId(getEntityId(proto.getDeviceProfileIdMSB(), proto.getDeviceProfileIdLSB(), DeviceProfileId::new)); device.setDeviceProfileId(getEntityId(proto.getDeviceProfileIdMSB(), proto.getDeviceProfileIdLSB(), DeviceProfileId::new));
@ -937,7 +937,7 @@ public class ProtoUtils {
public static DeviceProfile fromProto(TransportProtos.DeviceProfileProto proto) { public static DeviceProfile fromProto(TransportProtos.DeviceProfileProto proto) {
DeviceProfile deviceProfile = new DeviceProfile(getEntityId(proto.getDeviceProfileIdMSB(), proto.getDeviceProfileIdLSB(), DeviceProfileId::new)); DeviceProfile deviceProfile = new DeviceProfile(getEntityId(proto.getDeviceProfileIdMSB(), proto.getDeviceProfileIdLSB(), DeviceProfileId::new));
deviceProfile.setCreatedTime(proto.getCreatedTime()); deviceProfile.setCreatedTime(proto.getCreatedTime());
deviceProfile.setTenantId(getEntityId(proto.getTenantIdMSB(), proto.getTenantIdLSB(), TenantId::new)); deviceProfile.setTenantId(getEntityId(proto.getTenantIdMSB(), proto.getTenantIdLSB(), TenantId::fromUUID));
deviceProfile.setName(proto.getName()); deviceProfile.setName(proto.getName());
deviceProfile.setDefault(proto.getIsDefault()); deviceProfile.setDefault(proto.getIsDefault());
deviceProfile.setType(DeviceProfileType.valueOf(proto.getType())); deviceProfile.setType(DeviceProfileType.valueOf(proto.getType()));
@ -1028,7 +1028,7 @@ public class ProtoUtils {
} }
public static Tenant fromProto(TransportProtos.TenantProto proto) { public static Tenant fromProto(TransportProtos.TenantProto proto) {
Tenant tenant = new Tenant(getEntityId(proto.getTenantIdMSB(), proto.getTenantIdLSB(), TenantId::new)); Tenant tenant = new Tenant(getEntityId(proto.getTenantIdMSB(), proto.getTenantIdLSB(), TenantId::fromUUID));
tenant.setCreatedTime(proto.getCreatedTime()); tenant.setCreatedTime(proto.getCreatedTime());
tenant.setTenantProfileId(getEntityId(proto.getTenantProfileIdMSB(), proto.getTenantProfileIdLSB(), TenantProfileId::new)); tenant.setTenantProfileId(getEntityId(proto.getTenantProfileIdMSB(), proto.getTenantProfileIdLSB(), TenantProfileId::new));
tenant.setTitle(proto.getTitle()); tenant.setTitle(proto.getTitle());
@ -1142,7 +1142,7 @@ public class ProtoUtils {
public static TbResource fromProto(TransportProtos.TbResourceProto proto) { public static TbResource fromProto(TransportProtos.TbResourceProto proto) {
TbResource resource = new TbResource(getEntityId(proto.getResourceIdMSB(), proto.getResourceIdLSB(), TbResourceId::new)); TbResource resource = new TbResource(getEntityId(proto.getResourceIdMSB(), proto.getResourceIdLSB(), TbResourceId::new));
resource.setTenantId(getEntityId(proto.getTenantIdMSB(), proto.getTenantIdLSB(), TenantId::new)); resource.setTenantId(getEntityId(proto.getTenantIdMSB(), proto.getTenantIdLSB(), TenantId::fromUUID));
resource.setCreatedTime(proto.getCreatedTime()); resource.setCreatedTime(proto.getCreatedTime());
resource.setTitle(proto.getTitle()); resource.setTitle(proto.getTitle());
resource.setResourceType(ResourceType.valueOf(proto.getResourceType())); resource.setResourceType(ResourceType.valueOf(proto.getResourceType()));
@ -1198,7 +1198,7 @@ public class ProtoUtils {
public static ApiUsageState fromProto(TransportProtos.ApiUsageStateProto proto) { public static ApiUsageState fromProto(TransportProtos.ApiUsageStateProto proto) {
ApiUsageState apiUsageState = new ApiUsageState(getEntityId(proto.getApiUsageStateIdMSB(), proto.getApiUsageStateIdLSB(), ApiUsageStateId::new)); ApiUsageState apiUsageState = new ApiUsageState(getEntityId(proto.getApiUsageStateIdMSB(), proto.getApiUsageStateIdLSB(), ApiUsageStateId::new));
apiUsageState.setTenantId(getEntityId(proto.getTenantProfileIdMSB(), proto.getTenantProfileIdLSB(), TenantId::new)); apiUsageState.setTenantId(getEntityId(proto.getTenantProfileIdMSB(), proto.getTenantProfileIdLSB(), TenantId::fromUUID));
apiUsageState.setCreatedTime(proto.getCreatedTime()); apiUsageState.setCreatedTime(proto.getCreatedTime());
apiUsageState.setEntityId(EntityIdFactory.getByTypeAndUuid(fromProto(proto.getEntityType()), new UUID(proto.getEntityIdMSB(), proto.getEntityIdLSB()))); apiUsageState.setEntityId(EntityIdFactory.getByTypeAndUuid(fromProto(proto.getEntityType()), new UUID(proto.getEntityIdMSB(), proto.getEntityIdLSB())));
apiUsageState.setTransportState(ApiUsageStateValue.valueOf(proto.getTransportState())); apiUsageState.setTransportState(ApiUsageStateValue.valueOf(proto.getTransportState()));

1
common/proto/src/main/proto/queue.proto

@ -64,6 +64,7 @@ enum EntityTypeProto {
CALCULATED_FIELD = 39; CALCULATED_FIELD = 39;
CALCULATED_FIELD_LINK = 40; CALCULATED_FIELD_LINK = 40;
JOB = 41; JOB = 41;
ADMIN_SETTINGS = 42;
} }
enum ApiUsageRecordKeyProto { enum ApiUsageRecordKeyProto {

10
dao/src/main/java/org/thingsboard/server/dao/oauth2/HybridClientRegistrationRepository.java

@ -29,6 +29,7 @@ import java.util.UUID;
@Component @Component
public class HybridClientRegistrationRepository implements ClientRegistrationRepository { public class HybridClientRegistrationRepository implements ClientRegistrationRepository {
private static final String defaultRedirectUriTemplate = "{baseUrl}/login/oauth2/code/{registrationId}"; private static final String defaultRedirectUriTemplate = "{baseUrl}/login/oauth2/code/{registrationId}";
@Autowired @Autowired
@ -37,11 +38,13 @@ public class HybridClientRegistrationRepository implements ClientRegistrationRep
@Override @Override
public ClientRegistration findByRegistrationId(String registrationId) { public ClientRegistration findByRegistrationId(String registrationId) {
OAuth2Client oAuth2Client = oAuth2ClientService.findOAuth2ClientById(TenantId.SYS_TENANT_ID, new OAuth2ClientId(UUID.fromString(registrationId))); OAuth2Client oAuth2Client = oAuth2ClientService.findOAuth2ClientById(TenantId.SYS_TENANT_ID, new OAuth2ClientId(UUID.fromString(registrationId)));
return oAuth2Client == null ? if (oAuth2Client == null) {
null : toSpringClientRegistration(oAuth2Client); return null;
}
return toSpringClientRegistration(oAuth2Client);
} }
private ClientRegistration toSpringClientRegistration(OAuth2Client oAuth2Client){ private ClientRegistration toSpringClientRegistration(OAuth2Client oAuth2Client) {
String registrationId = oAuth2Client.getUuidId().toString(); String registrationId = oAuth2Client.getUuidId().toString();
// NONE is used if we need pkce-based code challenge // NONE is used if we need pkce-based code challenge
@ -67,4 +70,5 @@ public class HybridClientRegistrationRepository implements ClientRegistrationRep
.redirectUri(defaultRedirectUriTemplate) .redirectUri(defaultRedirectUriTemplate)
.build(); .build();
} }
} }

14
dao/src/main/java/org/thingsboard/server/dao/settings/AdminSettingsDao.java

@ -23,20 +23,8 @@ import java.util.UUID;
public interface AdminSettingsDao extends Dao<AdminSettings> { public interface AdminSettingsDao extends Dao<AdminSettings> {
/**
* Save or update admin settings object
*
* @param adminSettings the admin settings object
* @return saved admin settings object
*/
AdminSettings save(TenantId tenantId, AdminSettings adminSettings); AdminSettings save(TenantId tenantId, AdminSettings adminSettings);
/**
* Find admin settings by key.
*
* @param key the key
* @return the admin settings object
*/
AdminSettings findByTenantIdAndKey(UUID tenantId, String key); AdminSettings findByTenantIdAndKey(UUID tenantId, String key);
boolean removeByTenantIdAndKey(UUID tenantId, String key); boolean removeByTenantIdAndKey(UUID tenantId, String key);

22
dao/src/main/java/org/thingsboard/server/dao/settings/AdminSettingsServiceImpl.java

@ -21,11 +21,16 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.AdminSettings; import org.thingsboard.server.common.data.AdminSettings;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.id.AdminSettingsId; import org.thingsboard.server.common.data.id.AdminSettingsId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.HasId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.service.DataValidator; import org.thingsboard.server.dao.service.DataValidator;
import org.thingsboard.server.dao.service.Validator; import org.thingsboard.server.dao.service.Validator;
import java.util.Optional;
@Service @Service
@Slf4j @Slf4j
public class AdminSettingsServiceImpl implements AdminSettingsService { public class AdminSettingsServiceImpl implements AdminSettingsService {
@ -87,10 +92,25 @@ public class AdminSettingsServiceImpl implements AdminSettingsService {
} }
@Override @Override
public void deleteAdminSettingsByTenantId(TenantId tenantId) { public void deleteByTenantId(TenantId tenantId) {
adminSettingsDao.removeByTenantId(tenantId.getId()); adminSettingsDao.removeByTenantId(tenantId.getId());
} }
@Override
public void deleteEntity(TenantId tenantId, EntityId id, boolean force) {
adminSettingsDao.removeById(tenantId, id.getId());
}
@Override
public Optional<HasId<?>> findEntity(TenantId tenantId, EntityId entityId) {
return Optional.ofNullable(adminSettingsDao.findById(tenantId, entityId.getId()));
}
@Override
public EntityType getEntityType() {
return EntityType.ADMIN_SETTINGS;
}
private void dropTokenIfProviderInfoChanged(JsonNode newJsonValue, JsonNode oldJsonValue) { private void dropTokenIfProviderInfoChanged(JsonNode newJsonValue, JsonNode oldJsonValue) {
if (newJsonValue.has("enableOauth2") && newJsonValue.get("enableOauth2").asBoolean()) { if (newJsonValue.has("enableOauth2") && newJsonValue.get("enableOauth2").asBoolean()) {
if (!newJsonValue.get("providerId").equals(oldJsonValue.get("providerId")) || if (!newJsonValue.get("providerId").equals(oldJsonValue.get("providerId")) ||

3
dao/src/main/java/org/thingsboard/server/dao/sql/settings/AdminSettingsRepository.java

@ -22,9 +22,6 @@ import org.thingsboard.server.dao.model.sql.AdminSettingsEntity;
import java.util.UUID; import java.util.UUID;
/**
* Created by Valerii Sosliuk on 5/6/2017.
*/
public interface AdminSettingsRepository extends JpaRepository<AdminSettingsEntity, UUID> { public interface AdminSettingsRepository extends JpaRepository<AdminSettingsEntity, UUID> {
AdminSettingsEntity findByTenantIdAndKey(UUID tenantId, String key); AdminSettingsEntity findByTenantIdAndKey(UUID tenantId, String key);

34
dao/src/main/java/org/thingsboard/server/dao/sql/settings/JpaAdminSettingsDao.java

@ -15,12 +15,12 @@
*/ */
package org.thingsboard.server.dao.sql.settings; package org.thingsboard.server.dao.sql.settings;
import lombok.extern.slf4j.Slf4j; import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.thingsboard.server.common.data.AdminSettings; import org.thingsboard.server.common.data.AdminSettings;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
@ -35,21 +35,10 @@ import java.util.UUID;
@Component @Component
@SqlDao @SqlDao
@Slf4j @RequiredArgsConstructor
public class JpaAdminSettingsDao extends JpaAbstractDao<AdminSettingsEntity, AdminSettings> implements AdminSettingsDao, TenantEntityDao<AdminSettings> { public class JpaAdminSettingsDao extends JpaAbstractDao<AdminSettingsEntity, AdminSettings> implements AdminSettingsDao, TenantEntityDao<AdminSettings> {
@Autowired private final AdminSettingsRepository adminSettingsRepository;
private AdminSettingsRepository adminSettingsRepository;
@Override
protected Class<AdminSettingsEntity> getEntityClass() {
return AdminSettingsEntity.class;
}
@Override
protected JpaRepository<AdminSettingsEntity, UUID> getRepository() {
return adminSettingsRepository;
}
@Override @Override
public AdminSettings findByTenantIdAndKey(UUID tenantId, String key) { public AdminSettings findByTenantIdAndKey(UUID tenantId, String key) {
@ -77,4 +66,19 @@ public class JpaAdminSettingsDao extends JpaAbstractDao<AdminSettingsEntity, Adm
return DaoUtil.toPageData(adminSettingsRepository.findByTenantId(tenantId.getId(), DaoUtil.toPageable(pageLink))); return DaoUtil.toPageData(adminSettingsRepository.findByTenantId(tenantId.getId(), DaoUtil.toPageable(pageLink)));
} }
@Override
protected Class<AdminSettingsEntity> getEntityClass() {
return AdminSettingsEntity.class;
}
@Override
protected JpaRepository<AdminSettingsEntity, UUID> getRepository() {
return adminSettingsRepository;
}
@Override
public EntityType getEntityType() {
return EntityType.ADMIN_SETTINGS;
}
} }

8
dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java

@ -43,7 +43,6 @@ import org.thingsboard.server.dao.notification.NotificationSettingsService;
import org.thingsboard.server.dao.service.PaginatedRemover; import org.thingsboard.server.dao.service.PaginatedRemover;
import org.thingsboard.server.dao.service.Validator; import org.thingsboard.server.dao.service.Validator;
import org.thingsboard.server.dao.service.validator.TenantDataValidator; import org.thingsboard.server.dao.service.validator.TenantDataValidator;
import org.thingsboard.server.dao.settings.AdminSettingsService;
import org.thingsboard.server.dao.trendz.TrendzSettingsService; import org.thingsboard.server.dao.trendz.TrendzSettingsService;
import org.thingsboard.server.dao.usagerecord.ApiUsageStateService; import org.thingsboard.server.dao.usagerecord.ApiUsageStateService;
import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.dao.user.UserService;
@ -76,8 +75,6 @@ public class TenantServiceImpl extends AbstractCachedEntityService<TenantId, Ten
@Autowired @Autowired
private ApiUsageStateService apiUsageStateService; private ApiUsageStateService apiUsageStateService;
@Autowired @Autowired
private AdminSettingsService adminSettingsService;
@Autowired
private NotificationSettingsService notificationSettingsService; private NotificationSettingsService notificationSettingsService;
@Autowired @Autowired
private QrCodeSettingService qrCodeSettingService; private QrCodeSettingService qrCodeSettingService;
@ -168,7 +165,6 @@ public class TenantServiceImpl extends AbstractCachedEntityService<TenantId, Ten
userService.deleteAllByTenantId(tenantId); userService.deleteAllByTenantId(tenantId);
notificationSettingsService.deleteNotificationSettings(tenantId); notificationSettingsService.deleteNotificationSettings(tenantId);
trendzSettingsService.deleteTrendzSettings(tenantId); trendzSettingsService.deleteTrendzSettings(tenantId);
adminSettingsService.deleteAdminSettingsByTenantId(tenantId);
qrCodeSettingService.deleteByTenantId(tenantId); qrCodeSettingService.deleteByTenantId(tenantId);
tenantDao.removeById(tenantId, tenantId.getId()); tenantDao.removeById(tenantId, tenantId.getId());
@ -176,7 +172,7 @@ public class TenantServiceImpl extends AbstractCachedEntityService<TenantId, Ten
eventPublisher.publishEvent(DeleteEntityEvent.builder().tenantId(tenantId).entityId(tenantId).entity(tenant).build()); eventPublisher.publishEvent(DeleteEntityEvent.builder().tenantId(tenantId).entityId(tenantId).entity(tenant).build());
cleanUpService.removeTenantEntities(tenantId, // don't forget to implement deleteEntity from EntityDaoService when adding entity type to this list cleanUpService.removeTenantEntities(tenantId, // don't forget to implement deleteEntity from EntityDaoService when adding entity type to this list
EntityType.JOB, EntityType.ENTITY_VIEW, EntityType.WIDGETS_BUNDLE, EntityType.WIDGET_TYPE, EntityType.ADMIN_SETTINGS, EntityType.JOB, EntityType.ENTITY_VIEW, EntityType.WIDGETS_BUNDLE, EntityType.WIDGET_TYPE,
EntityType.ASSET, EntityType.ASSET_PROFILE, EntityType.DEVICE, EntityType.DEVICE_PROFILE, EntityType.ASSET, EntityType.ASSET_PROFILE, EntityType.DEVICE, EntityType.DEVICE_PROFILE,
EntityType.DASHBOARD, EntityType.EDGE, EntityType.RULE_CHAIN, EntityType.API_USAGE_STATE, EntityType.DASHBOARD, EntityType.EDGE, EntityType.RULE_CHAIN, EntityType.API_USAGE_STATE,
EntityType.TB_RESOURCE, EntityType.OTA_PACKAGE, EntityType.RPC, EntityType.QUEUE, EntityType.TB_RESOURCE, EntityType.OTA_PACKAGE, EntityType.RPC, EntityType.QUEUE,
@ -230,7 +226,7 @@ public class TenantServiceImpl extends AbstractCachedEntityService<TenantId, Ten
return existsTenantCache.getAndPutInTransaction(tenantId, () -> tenantDao.existsById(tenantId, tenantId.getId()), false); return existsTenantCache.getAndPutInTransaction(tenantId, () -> tenantDao.existsById(tenantId, tenantId.getId()), false);
} }
private PaginatedRemover<TenantId, Tenant> tenantsRemover = new PaginatedRemover<>() { private final PaginatedRemover<TenantId, Tenant> tenantsRemover = new PaginatedRemover<>() {
@Override @Override
protected PageData<Tenant> findEntities(TenantId tenantId, TenantId id, PageLink pageLink) { protected PageData<Tenant> findEntities(TenantId tenantId, TenantId id, PageLink pageLink) {

1
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/TenantIdLoader.java

@ -146,6 +146,7 @@ public class TenantIdLoader {
tenantEntity = ctx.getNotificationRequestService().findNotificationRequestById(ctxTenantId, new NotificationRequestId(id)); tenantEntity = ctx.getNotificationRequestService().findNotificationRequestById(ctxTenantId, new NotificationRequestId(id));
break; break;
case NOTIFICATION: case NOTIFICATION:
case ADMIN_SETTINGS:
return ctxTenantId; return ctxTenantId;
case NOTIFICATION_RULE: case NOTIFICATION_RULE:
tenantEntity = ctx.getNotificationRuleService().findNotificationRuleById(ctxTenantId, new NotificationRuleId(id)); tenantEntity = ctx.getNotificationRuleService().findNotificationRuleById(ctxTenantId, new NotificationRuleId(id));

8
rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/TenantIdLoaderTest.java

@ -29,6 +29,7 @@ import org.thingsboard.rule.engine.api.RuleEngineAssetProfileCache;
import org.thingsboard.rule.engine.api.RuleEngineDeviceProfileCache; import org.thingsboard.rule.engine.api.RuleEngineDeviceProfileCache;
import org.thingsboard.rule.engine.api.RuleEngineRpcService; import org.thingsboard.rule.engine.api.RuleEngineRpcService;
import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbContext;
import org.thingsboard.server.common.data.AdminSettings;
import org.thingsboard.server.common.data.ApiUsageState; import org.thingsboard.server.common.data.ApiUsageState;
import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.Dashboard; import org.thingsboard.server.common.data.Dashboard;
@ -167,7 +168,6 @@ public class TenantIdLoaderTest {
private TenantId tenantId; private TenantId tenantId;
private TenantProfileId tenantProfileId; private TenantProfileId tenantProfileId;
private NotificationId notificationId;
private AbstractListeningExecutor dbExecutor; private AbstractListeningExecutor dbExecutor;
@BeforeEach @BeforeEach
@ -179,9 +179,8 @@ public class TenantIdLoaderTest {
} }
}; };
dbExecutor.init(); dbExecutor.init();
this.tenantId = new TenantId(UUID.randomUUID()); this.tenantId = TenantId.fromUUID(UUID.randomUUID());
this.tenantProfileId = new TenantProfileId(UUID.randomUUID()); this.tenantProfileId = new TenantProfileId(UUID.randomUUID());
this.notificationId = new NotificationId(UUID.randomUUID());
when(ctx.getTenantId()).thenReturn(tenantId); when(ctx.getTenantId()).thenReturn(tenantId);
@ -199,6 +198,7 @@ public class TenantIdLoaderTest {
switch (entityType) { switch (entityType) {
case TENANT: case TENANT:
case NOTIFICATION: case NOTIFICATION:
case ADMIN_SETTINGS:
break; break;
case CUSTOMER: case CUSTOMER:
Customer customer = new Customer(); Customer customer = new Customer();
@ -465,7 +465,7 @@ public class TenantIdLoaderTest {
@Test @Test
public void test_findEntityIdAsync_other_tenant() { public void test_findEntityIdAsync_other_tenant() {
checkTenant(new TenantId(UUID.randomUUID()), false); checkTenant(TenantId.fromUUID(UUID.randomUUID()), false);
} }
} }

Loading…
Cancel
Save