Browse Source

renamed oauth2_registration table to oauth2_client

pull/11231/head
dashevchenko 2 years ago
parent
commit
1429d6a97c
  1. 34
      application/src/main/data/upgrade/3.7.0/schema_update.sql
  2. 10
      application/src/main/java/org/thingsboard/server/controller/BaseController.java
  3. 19
      application/src/main/java/org/thingsboard/server/controller/DomainController.java
  4. 31
      application/src/main/java/org/thingsboard/server/controller/MobileAppController.java
  5. 41
      application/src/main/java/org/thingsboard/server/controller/OAuth2Controller.java
  6. 6
      application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java
  7. 6
      application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/oauth2/OAuth2MsgConstructor.java
  8. 6
      application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/OAuth2EdgeEventFetcher.java
  9. 10
      application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/oauth2/OAuth2EdgeProcessor.java
  10. 8
      application/src/main/java/org/thingsboard/server/service/entitiy/domain/DefaultTbDomainService.java
  11. 4
      application/src/main/java/org/thingsboard/server/service/entitiy/domain/TbDomainService.java
  12. 6
      application/src/main/java/org/thingsboard/server/service/entitiy/mobile/DefaultTbMobileAppService.java
  13. 4
      application/src/main/java/org/thingsboard/server/service/entitiy/mobile/TbMobileAppService.java
  14. 28
      application/src/main/java/org/thingsboard/server/service/entitiy/oauth2client/DefaultTbOauth2ClientService.java
  15. 10
      application/src/main/java/org/thingsboard/server/service/entitiy/oauth2client/TbOauth2ClientService.java
  16. 5
      application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AbstractOAuth2ClientMapper.java
  17. 4
      application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AppleOAuth2ClientMapper.java
  18. 4
      application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/BasicOAuth2ClientMapper.java
  19. 4
      application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/CustomOAuth2ClientMapper.java
  20. 4
      application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/GithubOAuth2ClientMapper.java
  21. 4
      application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/OAuth2ClientMapper.java
  22. 6
      application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationSuccessHandler.java
  23. 10
      application/src/test/java/org/thingsboard/server/controller/HomePageApiTest.java
  24. 10
      application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java
  25. 48
      application/src/test/java/org/thingsboard/server/edge/OAuth2EdgeTest.java
  26. 6
      common/dao-api/src/main/java/org/thingsboard/server/dao/domain/DomainService.java
  27. 5
      common/dao-api/src/main/java/org/thingsboard/server/dao/mobile/MobileAppService.java
  28. 24
      common/dao-api/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientService.java
  29. 3
      common/data/src/main/java/org/thingsboard/server/common/data/audit/ActionType.java
  30. 18
      common/data/src/main/java/org/thingsboard/server/common/data/domain/DomainInfo.java
  31. 6
      common/data/src/main/java/org/thingsboard/server/common/data/domain/DomainOauth2Client.java
  32. 2
      common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java
  33. 8
      common/data/src/main/java/org/thingsboard/server/common/data/id/OAuth2ClientId.java
  34. 12
      common/data/src/main/java/org/thingsboard/server/common/data/mobile/MobileAppInfo.java
  35. 6
      common/data/src/main/java/org/thingsboard/server/common/data/mobile/MobileAppOauth2Client.java
  36. 6
      common/data/src/main/java/org/thingsboard/server/common/data/oauth2/HasOauth2Clients.java
  37. 20
      common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2Client.java
  38. 43
      common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientInfo.java
  39. 39
      common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientLoginInfo.java
  40. 2
      common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2MapperConfig.java
  41. 49
      common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2RegistrationInfo.java
  42. 11
      dao/src/main/java/org/thingsboard/server/dao/domain/DomainDao.java
  43. 50
      dao/src/main/java/org/thingsboard/server/dao/domain/DomainServiceImpl.java
  44. 12
      dao/src/main/java/org/thingsboard/server/dao/mobile/MobileAppDao.java
  45. 50
      dao/src/main/java/org/thingsboard/server/dao/mobile/MobileAppServiceImpl.java
  46. 16
      dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java
  47. 4
      dao/src/main/java/org/thingsboard/server/dao/model/sql/DomainOauth2ClientCompositeKey.java
  48. 34
      dao/src/main/java/org/thingsboard/server/dao/model/sql/DomainOauth2ClientEntity.java
  49. 4
      dao/src/main/java/org/thingsboard/server/dao/model/sql/MobileAppOauth2ClientCompositeKey.java
  50. 36
      dao/src/main/java/org/thingsboard/server/dao/model/sql/MobileAppOauth2ClientEntity.java
  51. 18
      dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2ClientEntity.java
  52. 24
      dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2ClientInfoEntity.java
  53. 8
      dao/src/main/java/org/thingsboard/server/dao/oauth2/HybridClientRegistrationRepository.java
  54. 19
      dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientDao.java
  55. 96
      dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientServiceImpl.java
  56. 16
      dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2Utils.java
  57. 1
      dao/src/main/java/org/thingsboard/server/dao/service/validator/MobileAppDataValidator.java
  58. 42
      dao/src/main/java/org/thingsboard/server/dao/service/validator/Oauth2ClientDataValidator.java
  59. 12
      dao/src/main/java/org/thingsboard/server/dao/sql/domain/DomainOauth2ClientRepository.java
  60. 2
      dao/src/main/java/org/thingsboard/server/dao/sql/domain/DomainRepository.java
  61. 29
      dao/src/main/java/org/thingsboard/server/dao/sql/domain/JpaDomainDao.java
  62. 24
      dao/src/main/java/org/thingsboard/server/dao/sql/mobile/JpaMobileAppDao.java
  63. 10
      dao/src/main/java/org/thingsboard/server/dao/sql/mobile/MobileAppOauth2ClientRepository.java
  64. 45
      dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ClientDao.java
  65. 76
      dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2ClientRepository.java
  66. 76
      dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2RegistrationRepository.java
  67. 17
      dao/src/main/resources/sql/schema-entities.sql
  68. 43
      dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java
  69. 131
      dao/src/test/java/org/thingsboard/server/dao/service/DomainServiceTest.java
  70. 113
      dao/src/test/java/org/thingsboard/server/dao/service/MobileAppServiceTest.java
  71. 662
      dao/src/test/java/org/thingsboard/server/dao/service/OAuth2ClientServiceTest.java
  72. 6
      rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java

34
application/src/main/data/upgrade/3.7.0/schema_update.sql

@ -18,28 +18,29 @@
ALTER TABLE IF EXISTS oauth2_mobile RENAME TO mobile_app;
ALTER TABLE IF EXISTS oauth2_domain RENAME TO domain;
ALTER TABLE IF EXISTS oauth2_registration RENAME TO oauth2_client;
ALTER TABLE domain ADD COLUMN IF NOT EXISTS oauth2_enabled boolean,
ADD COLUMN IF NOT EXISTS propagate_to_edge boolean,
ADD COLUMN IF NOT EXISTS edge_enabled boolean,
ADD COLUMN IF NOT EXISTS tenant_id uuid DEFAULT '13814000-1dd2-11b2-8080-808080808080',
DROP COLUMN IF EXISTS domain_scheme;
ALTER TABLE mobile_app ADD COLUMN IF NOT EXISTS oauth2_enabled boolean,
ADD COLUMN IF NOT EXISTS tenant_id uuid DEFAULT '13814000-1dd2-11b2-8080-808080808080';
ALTER TABLE oauth2_registration ADD COLUMN IF NOT EXISTS tenant_id uuid DEFAULT '13814000-1dd2-11b2-8080-808080808080';
ALTER TABLE oauth2_registration ADD COLUMN IF NOT EXISTS title varchar(100);
ALTER TABLE oauth2_client ADD COLUMN IF NOT EXISTS tenant_id uuid DEFAULT '13814000-1dd2-11b2-8080-808080808080';
ALTER TABLE oauth2_client ADD COLUMN IF NOT EXISTS title varchar(100);
CREATE TABLE IF NOT EXISTS domain_oauth2_registration (
CREATE TABLE IF NOT EXISTS domain_oauth2_client (
domain_id uuid NOT NULL,
oauth2_registration_id uuid NOT NULL,
oauth2_client_id uuid NOT NULL,
CONSTRAINT fk_domain FOREIGN KEY (domain_id) REFERENCES domain(id) ON DELETE CASCADE,
CONSTRAINT fk_oauth2_registration FOREIGN KEY (oauth2_registration_id) REFERENCES oauth2_registration(id) ON DELETE CASCADE
CONSTRAINT fk_oauth2_client FOREIGN KEY (oauth2_client_id) REFERENCES oauth2_client(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS mobile_app_oauth2_registration (
CREATE TABLE IF NOT EXISTS mobile_app_oauth2_client (
mobile_app_id uuid NOT NULL,
oauth2_registration_id uuid NOT NULL,
oauth2_client_id uuid NOT NULL,
CONSTRAINT fk_domain FOREIGN KEY (mobile_app_id) REFERENCES mobile_app(id) ON DELETE CASCADE,
CONSTRAINT fk_oauth2_registration FOREIGN KEY (oauth2_registration_id) REFERENCES oauth2_registration(id) ON DELETE CASCADE
CONSTRAINT fk_oauth2_client FOREIGN KEY (oauth2_client_id) REFERENCES oauth2_client(id) ON DELETE CASCADE
);
DO
@ -50,27 +51,28 @@ $$
DELETE FROM domain d1 USING domain d2 WHERE d1.created_time < d2.created_time AND d1.domain_name = d2.domain_name;
UPDATE domain SET oauth2_enabled = p.enabled,
propagate_to_edge = p.edge_enabled
edge_enabled = p.edge_enabled
FROM oauth2_params p WHERE p.id = domain.oauth2_params_id;
UPDATE mobile_app SET oauth2_enabled = p.enabled
FROM oauth2_params p WHERE p.id = mobile_app.oauth2_params_id;
INSERT INTO domain_oauth2_registration(domain_id, oauth2_registration_id)
(SELECT d.id, r.id FROM domain d LEFT JOIN oauth2_registration r on d.oauth2_params_id = r.oauth2_params_id
INSERT INTO domain_oauth2_client(domain_id, oauth2_client_id)
(SELECT d.id, r.id FROM domain d LEFT JOIN oauth2_client r on d.oauth2_params_id = r.oauth2_params_id
WHERE r.platforms IS NULL OR r.platforms IN ('','WEB'));
INSERT INTO mobile_app_oauth2_registration(mobile_app_id, oauth2_registration_id)
(SELECT m.id, r.id FROM mobile_app m LEFT JOIN oauth2_registration r on m.oauth2_params_id = r.oauth2_params_id
INSERT INTO mobile_app_oauth2_client(mobile_app_id, oauth2_client_id)
(SELECT m.id, r.id FROM mobile_app m LEFT JOIN oauth2_client r on m.oauth2_params_id = r.oauth2_params_id
WHERE r.platforms IS NULL OR r.platforms IN ('','ANDROID','IOS'));
ALTER TABLE mobile_app RENAME CONSTRAINT oauth2_mobile_pkey TO mobile_app_pkey;
ALTER TABLE domain RENAME CONSTRAINT oauth2_domain_pkey TO domain_pkey;
UPDATE oauth2_registration SET title = additional_info::jsonb->>'providerName' WHERE additional_info IS NOT NULL;
ALTER TABLE oauth2_client RENAME CONSTRAINT oauth2_registration_pkey TO oauth2_client_pkey;
UPDATE oauth2_client SET title = additional_info::jsonb->>'providerName' WHERE additional_info IS NOT NULL;
ALTER TABLE domain DROP COLUMN oauth2_params_id;
ALTER TABLE mobile_app DROP COLUMN oauth2_params_id;
ALTER TABLE oauth2_registration DROP COLUMN oauth2_params_id;
ALTER TABLE oauth2_client DROP COLUMN oauth2_params_id;
ALTER TABLE mobile_app ADD CONSTRAINT mobile_app_unq_key UNIQUE (pkg_name);
ALTER TABLE domain ADD CONSTRAINT domain_unq_key UNIQUE (domain_name);

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

@ -82,7 +82,7 @@ import org.thingsboard.server.common.data.id.EntityIdFactory;
import org.thingsboard.server.common.data.id.EntityViewId;
import org.thingsboard.server.common.data.id.HasId;
import org.thingsboard.server.common.data.id.MobileAppId;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.data.id.QueueId;
import org.thingsboard.server.common.data.id.RpcId;
@ -96,7 +96,7 @@ import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.id.WidgetTypeId;
import org.thingsboard.server.common.data.id.WidgetsBundleId;
import org.thingsboard.server.common.data.mobile.MobileApp;
import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.page.SortOrder;
import org.thingsboard.server.common.data.page.TimePageLink;
@ -615,7 +615,7 @@ public abstract class BaseController {
checkQueueId(new QueueId(entityId.getId()), operation);
return;
case OAUTH2_CLIENT:
checkOauth2ClientId(new OAuth2RegistrationId(entityId.getId()), operation);
checkOauth2ClientId(new OAuth2ClientId(entityId.getId()), operation);
return;
case DOMAIN:
checkDomainId(new DomainId(entityId.getId()), operation);
@ -799,8 +799,8 @@ public abstract class BaseController {
return queue;
}
OAuth2Registration checkOauth2ClientId(OAuth2RegistrationId oAuth2RegistrationId, Operation operation) throws ThingsboardException {
return checkEntityId(oAuth2RegistrationId, oAuth2ClientService::findOAuth2ClientById, operation);
OAuth2Client checkOauth2ClientId(OAuth2ClientId oAuth2ClientId, Operation operation) throws ThingsboardException {
return checkEntityId(oAuth2ClientId, oAuth2ClientService::findOAuth2ClientById, operation);
}
Domain checkDomainId(DomainId domainId, Operation operation) throws ThingsboardException {

19
application/src/main/java/org/thingsboard/server/controller/DomainController.java

@ -34,7 +34,7 @@ import org.thingsboard.server.common.data.domain.Domain;
import org.thingsboard.server.common.data.domain.DomainInfo;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.DomainId;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import org.thingsboard.server.config.annotations.ApiOperation;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.entitiy.domain.TbDomainService;
@ -47,7 +47,6 @@ import java.util.Collections;
import java.util.List;
import java.util.UUID;
import static org.thingsboard.server.common.data.audit.ActionType.UPDATED_OAUTH2_CLIENTS;
import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_AUTHORITY_PARAGRAPH;
import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
import static org.thingsboard.server.controller.ControllerConstants.UUID_WIKI_LINK;
@ -77,9 +76,9 @@ public class DomainController extends BaseController {
List<String> oauth2ClientIds = ids != null ? Arrays.asList(ids) : Collections.emptyList();
domain.setTenantId(getCurrentUser().getTenantId());
checkEntity(domain.getId(), domain, Resource.DOMAIN);
List<OAuth2RegistrationId> oAuth2ClientIds = new ArrayList<>();
List<OAuth2ClientId> oAuth2ClientIds = new ArrayList<>();
for (String id : oauth2ClientIds) {
OAuth2RegistrationId oauth2ClientId = new OAuth2RegistrationId(toUUID(id));
OAuth2ClientId oauth2ClientId = new OAuth2ClientId(toUUID(id));
checkOauth2ClientId(oauth2ClientId, Operation.READ);
oAuth2ClientIds.add(oauth2ClientId);
}
@ -96,19 +95,19 @@ public class DomainController extends BaseController {
Domain domain = null;
try {
domain = checkDomainId(domainId, Operation.WRITE);
List<OAuth2RegistrationId> oAuth2ClientIds = new ArrayList<>();
List<OAuth2ClientId> oAuth2ClientIds = new ArrayList<>();
for (UUID outh2CLientId : oauth2ClientIds) {
OAuth2RegistrationId oAuth2RegistrationId = new OAuth2RegistrationId(outh2CLientId);
checkEntityId(oAuth2RegistrationId, Operation.READ);
oAuth2ClientIds.add(oAuth2RegistrationId);
OAuth2ClientId oAuth2ClientId = new OAuth2ClientId(outh2CLientId);
checkEntityId(oAuth2ClientId, Operation.READ);
oAuth2ClientIds.add(oAuth2ClientId);
}
domainService.updateOauth2Clients(getTenantId(), domainId, oAuth2ClientIds);
logEntityActionService.logEntityAction(domain.getTenantId(), domain.getId(), domain,
UPDATED_OAUTH2_CLIENTS, getCurrentUser(), oAuth2ClientIds.toString());
ActionType.UPDATED, getCurrentUser(), oAuth2ClientIds.toString());
} catch (Exception e) {
if (domain != null) {
logEntityActionService.logEntityAction(getTenantId(), domainId, domain,
ActionType.UPDATED_OAUTH2_CLIENTS, getCurrentUser(), e);
ActionType.UPDATED, getCurrentUser(), e);
}
throw e;
}

31
application/src/main/java/org/thingsboard/server/controller/MobileAppController.java

@ -30,11 +30,9 @@ 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.audit.ActionType;
import org.thingsboard.server.common.data.domain.Domain;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.DomainId;
import org.thingsboard.server.common.data.id.MobileAppId;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.mobile.MobileApp;
import org.thingsboard.server.common.data.mobile.MobileAppInfo;
@ -47,7 +45,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import static org.thingsboard.server.common.data.audit.ActionType.UPDATED_OAUTH2_CLIENTS;
import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_AUTHORITY_PARAGRAPH;
import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
import static org.thingsboard.server.controller.ControllerConstants.UUID_WIKI_LINK;
@ -73,41 +70,39 @@ public class MobileAppController extends BaseController {
@Parameter(description = "A JSON value representing the Domain.", required = true)
@RequestBody MobileApp mobileApp,
@Parameter(description = "A list of entity group ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")))
@RequestParam(name = "oauth2RegistrationIds", required = false) UUID[] oauth2RegistrationIds) throws Exception {
@RequestParam(name = "oauth2ClientIds", required = false) UUID[] oauth2ClientIds) throws Exception {
mobileApp.setTenantId(getCurrentUser().getTenantId());
List<OAuth2RegistrationId> oAuth2Registrations = new ArrayList<>();
for (UUID id : oauth2RegistrationIds) {
OAuth2RegistrationId oauth2ClientId = new OAuth2RegistrationId(id);
List<OAuth2ClientId> oAuth2Clients = new ArrayList<>();
for (UUID id : oauth2ClientIds) {
OAuth2ClientId oauth2ClientId = new OAuth2ClientId(id);
checkOauth2ClientId(oauth2ClientId, Operation.READ);
oAuth2Registrations.add(oauth2ClientId);
oAuth2Clients.add(oauth2ClientId);
}
return tbMobileAppService.save(mobileApp, oAuth2Registrations, getCurrentUser());
return tbMobileAppService.save(mobileApp, oAuth2Clients, getCurrentUser());
}
@ApiOperation(value = "Update oauth2 clients (updateOauth2Clients)",
notes = "Update oauth2 clients to the specified mobile app. ")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN')")
@PostMapping(value = "/mobileApp/{id}/updateOauth2Clients")
@PostMapping(value = "/mobileApp/{id}/oauth2Clients")
public void updateOauth2Clients(@PathVariable UUID id,
@RequestBody UUID[] oauth2ClientIds) throws ThingsboardException {
MobileAppId mobileAppId = new MobileAppId(id);
MobileApp mobileApp = null;
try {
mobileApp = checkMobileAppId(mobileAppId, Operation.WRITE);
List<OAuth2RegistrationId> oAuth2ClientIds = new ArrayList<>();
List<OAuth2ClientId> oAuth2ClientIds = new ArrayList<>();
for (UUID outh2CLientId : oauth2ClientIds) {
OAuth2RegistrationId oAuth2RegistrationId = new OAuth2RegistrationId(outh2CLientId);
checkEntityId(oAuth2RegistrationId, Operation.READ);
oAuth2ClientIds.add(oAuth2RegistrationId);
OAuth2ClientId oAuth2ClientId = new OAuth2ClientId(outh2CLientId);
checkEntityId(oAuth2ClientId, Operation.READ);
oAuth2ClientIds.add(oAuth2ClientId);
}
mobileAppService.updateOauth2Clients(getTenantId(), mobileAppId, oAuth2ClientIds);
logEntityActionService.logEntityAction(getTenantId(), mobileAppId, mobileApp,
UPDATED_OAUTH2_CLIENTS, getCurrentUser(), oAuth2ClientIds.toString());
} catch (Exception e) {
if (mobileApp != null) {
logEntityActionService.logEntityAction(getTenantId(), mobileAppId, mobileApp,
ActionType.UPDATED_OAUTH2_CLIENTS, getCurrentUser(), e);
ActionType.UPDATED, getCurrentUser(), e);
}
throw e;
}

41
application/src/main/java/org/thingsboard/server/controller/OAuth2Controller.java

@ -20,7 +20,6 @@ import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
@ -34,11 +33,11 @@ import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientLoginInfo;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo;
import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
import org.thingsboard.server.common.data.oauth2.OAuth2RegistrationInfo;
import org.thingsboard.server.common.data.oauth2.PlatformType;
import org.thingsboard.server.config.annotations.ApiOperation;
import org.thingsboard.server.dao.oauth2.OAuth2Configuration;
@ -71,11 +70,11 @@ public class OAuth2Controller extends BaseController {
"to log in with, available for such domain scheme (HTTP or HTTPS) (if x-forwarded-proto request header is present - " +
"the scheme is known from it) and domain name and port (port may be known from x-forwarded-port header)")
@PostMapping(value = "/noauth/oauth2Clients")
public List<OAuth2ClientInfo> getOAuth2Clients(HttpServletRequest request,
@Parameter(description = "Mobile application package name, to find OAuth2 clients " +
public List<OAuth2ClientLoginInfo> getOAuth2Clients(HttpServletRequest request,
@Parameter(description = "Mobile application package name, to find OAuth2 clients " +
"where there is configured mobile application with such package name")
@RequestParam(required = false) String pkgName,
@Parameter(description = "Platform type to search OAuth2 clients for which " +
@Parameter(description = "Platform type to search OAuth2 clients for which " +
"the usage with this platform type is allowed in the settings. " +
"If platform type is not one of allowable values - it will just be ignored",
schema = @Schema(allowableValues = {"WEB", "ANDROID", "IOS"}))
@ -96,35 +95,35 @@ public class OAuth2Controller extends BaseController {
}
}
if (StringUtils.isNotEmpty(pkgName)) {
return oAuth2ClientService.getMobileOAuth2Clients(pkgName, platformType);
return oAuth2ClientService.findOAuth2ClientLoginInfosByMobilePkgNameAndPlatformType(pkgName, platformType);
} else {
return oAuth2ClientService.getWebOAuth2Clients(MiscUtils.getDomainNameAndPort(request), platformType);
return oAuth2ClientService.findOAuth2ClientLoginInfosByDomainName(MiscUtils.getDomainNameAndPort(request));
}
}
@ApiOperation(value = "Save OAuth2 Client Registration (saveOAuth2Client)", notes = SYSTEM_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('SYS_ADMIN')")
@PostMapping(value = "/oauth2/client")
public OAuth2Registration saveOAuth2Client(@RequestBody OAuth2Registration oAuth2Registration) throws Exception {
public OAuth2Client saveOAuth2Client(@RequestBody OAuth2Client oAuth2Client) throws Exception {
TenantId tenantId = getTenantId();
oAuth2Registration.setTenantId(tenantId);
checkEntity(oAuth2Registration.getId(), oAuth2Registration, Resource.OAUTH2_CLIENT);
return tbOauth2ClientService.save(oAuth2Registration, getCurrentUser());
oAuth2Client.setTenantId(tenantId);
checkEntity(oAuth2Client.getId(), oAuth2Client, Resource.OAUTH2_CLIENT);
return tbOauth2ClientService.save(oAuth2Client, getCurrentUser());
}
@ApiOperation(value = "Get OAuth2 Client Registration infos (findTenantOAuth2ClientInfos)", notes = SYSTEM_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('SYS_ADMIN')")
@GetMapping(value = "/oauth2/client/infos")
public List<OAuth2RegistrationInfo> findTenantOAuth2ClientInfos() throws ThingsboardException {
return oAuth2ClientService.findOauth2ClientInfosByTenantId(getTenantId());
public List<OAuth2ClientInfo> findTenantOAuth2ClientInfos() throws ThingsboardException {
return oAuth2ClientService.findOAuth2ClientInfosByTenantId(getTenantId());
}
@ApiOperation(value = "Get OAuth2 Client Registration by id (getOAuth2ClientById)", notes = SYSTEM_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('SYS_ADMIN')")
@GetMapping(value = "/oauth2/client/{id}")
public OAuth2Registration getOAuth2ClientById(@PathVariable UUID id) throws ThingsboardException {
OAuth2RegistrationId oAuth2RegistrationId = new OAuth2RegistrationId(id);
return checkEntityId(oAuth2RegistrationId, oAuth2ClientService::findOAuth2ClientById, Operation.READ);
public OAuth2Client getOAuth2ClientById(@PathVariable UUID id) throws ThingsboardException {
OAuth2ClientId oAuth2ClientId = new OAuth2ClientId(id);
return checkEntityId(oAuth2ClientId, oAuth2ClientService::findOAuth2ClientById, Operation.READ);
}
@ApiOperation(value = "Delete oauth2 client (deleteAsset)",
@ -133,9 +132,9 @@ public class OAuth2Controller extends BaseController {
@RequestMapping(value = "/oauth2/client/{id}", method = RequestMethod.DELETE)
@ResponseStatus(value = HttpStatus.OK)
public void deleteOauth2Client(@PathVariable UUID id) throws Exception {
OAuth2RegistrationId oAuth2RegistrationId = new OAuth2RegistrationId(id);
OAuth2Registration oAuth2Registration = checkOauth2ClientId(oAuth2RegistrationId, Operation.DELETE);
tbOauth2ClientService.delete(oAuth2Registration, getCurrentUser());
OAuth2ClientId oAuth2ClientId = new OAuth2ClientId(id);
OAuth2Client oAuth2Client = checkOauth2ClientId(oAuth2ClientId, Operation.DELETE);
tbOauth2ClientService.delete(oAuth2Client, getCurrentUser());
}
@ApiOperation(value = "Get OAuth2 log in processing URL (getLoginProcessingUrl)", notes = "Returns the URL enclosed in " +

6
application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java

@ -34,7 +34,7 @@ import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
import org.thingsboard.server.common.data.edge.EdgeEventType;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
import org.thingsboard.server.common.data.rule.RuleChain;
@ -227,7 +227,7 @@ public class EdgeEventSourcingListener {
private EdgeEventType getEdgeEventTypeForEntityEvent(Object entity) {
if (entity instanceof AlarmComment) {
return EdgeEventType.ALARM_COMMENT;
} else if (entity instanceof OAuth2Registration) {
} else if (entity instanceof OAuth2Client) {
return EdgeEventType.OAUTH2_CLIENT;
}
return null;
@ -236,7 +236,7 @@ public class EdgeEventSourcingListener {
private String getBodyMsgForEntityEvent(Object entity) {
if (entity instanceof AlarmComment) {
return JacksonUtil.toString(entity);
} else if (entity instanceof OAuth2Registration) {
} else if (entity instanceof OAuth2Client) {
return JacksonUtil.toString(entity);
}
return null;

6
application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/oauth2/OAuth2MsgConstructor.java

@ -17,7 +17,7 @@ package org.thingsboard.server.service.edge.rpc.constructor.oauth2;
import org.springframework.stereotype.Component;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import org.thingsboard.server.gen.edge.v1.OAuth2UpdateMsg;
import org.thingsboard.server.queue.util.TbCoreComponent;
@ -25,8 +25,8 @@ import org.thingsboard.server.queue.util.TbCoreComponent;
@TbCoreComponent
public class OAuth2MsgConstructor {
public OAuth2UpdateMsg constructOAuth2UpdateMsg(OAuth2Registration oAuth2Registration) {
return OAuth2UpdateMsg.newBuilder().setEntity(JacksonUtil.toString(oAuth2Registration)).build();
public OAuth2UpdateMsg constructOAuth2UpdateMsg(OAuth2Client oAuth2Client) {
return OAuth2UpdateMsg.newBuilder().setEntity(JacksonUtil.toString(oAuth2Client)).build();
}
}

6
application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/OAuth2EdgeEventFetcher.java

@ -24,7 +24,7 @@ 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.TenantId;
import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.oauth2.OAuth2ClientService;
@ -46,9 +46,9 @@ public class OAuth2EdgeEventFetcher implements EdgeEventFetcher {
@Override
public PageData<EdgeEvent> fetchEdgeEvents(TenantId tenantId, Edge edge, PageLink pageLink) {
List<EdgeEvent> result = new ArrayList<>();
List<OAuth2Registration> oauth2Registrations = oAuth2ClientService.findOauth2ClientsByTenantId(TenantId.SYS_TENANT_ID);
List<OAuth2Client> oauth2Clients = oAuth2ClientService.findOAuth2ClientsByTenantId(TenantId.SYS_TENANT_ID);
result.add(EdgeUtils.constructEdgeEvent(tenantId, edge.getId(), EdgeEventType.OAUTH2_CLIENT,
EdgeEventActionType.ADDED, null, JacksonUtil.valueToTree(oauth2Registrations)));
EdgeEventActionType.ADDED, null, JacksonUtil.valueToTree(oauth2Clients)));
// returns PageData object to be in sync with other fetchers
return new PageData<>(result, 1, result.size(), false);
}

10
application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/oauth2/OAuth2EdgeProcessor.java

@ -25,7 +25,7 @@ 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.TenantId;
import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
import org.thingsboard.server.gen.edge.v1.OAuth2UpdateMsg;
import org.thingsboard.server.gen.transport.TransportProtos;
@ -39,9 +39,9 @@ public class OAuth2EdgeProcessor extends BaseEdgeProcessor {
public DownlinkMsg convertOAuth2ProviderEventToDownlink(EdgeEvent edgeEvent) {
DownlinkMsg downlinkMsg = null;
OAuth2Registration oAuth2Registration = JacksonUtil.convertValue(edgeEvent.getBody(), OAuth2Registration.class);
if (oAuth2Registration != null) {
OAuth2UpdateMsg oAuth2ProviderUpdateMsg = oAuth2MsgConstructor.constructOAuth2UpdateMsg(oAuth2Registration);
OAuth2Client oAuth2Client = JacksonUtil.convertValue(edgeEvent.getBody(), OAuth2Client.class);
if (oAuth2Client != null) {
OAuth2UpdateMsg oAuth2ProviderUpdateMsg = oAuth2MsgConstructor.constructOAuth2UpdateMsg(oAuth2Client);
downlinkMsg = DownlinkMsg.newBuilder()
.setDownlinkMsgId(EdgeUtils.nextPositiveInt())
.addOAuth2UpdateMsg(oAuth2ProviderUpdateMsg)
@ -51,7 +51,7 @@ public class OAuth2EdgeProcessor extends BaseEdgeProcessor {
}
public ListenableFuture<Void> processOAuth2Notification(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
OAuth2Registration oAuth2Info = JacksonUtil.fromString(edgeNotificationMsg.getBody(), OAuth2Registration.class);
OAuth2Client oAuth2Info = JacksonUtil.fromString(edgeNotificationMsg.getBody(), OAuth2Client.class);
if (oAuth2Info == null) {
return Futures.immediateFuture(null);
}

8
application/src/main/java/org/thingsboard/server/service/entitiy/domain/DefaultTbDomainService.java

@ -24,15 +24,13 @@ import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.domain.Domain;
import org.thingsboard.server.common.data.id.DomainId;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.domain.DomainService;
import org.thingsboard.server.service.entitiy.AbstractTbEntityService;
import java.util.List;
import static org.thingsboard.server.common.data.audit.ActionType.UPDATED_OAUTH2_CLIENTS;
@Service
@AllArgsConstructor
public class DefaultTbDomainService extends AbstractTbEntityService implements TbDomainService {
@ -40,7 +38,7 @@ public class DefaultTbDomainService extends AbstractTbEntityService implements T
private final DomainService domainService;
@Override
public Domain save(Domain domain, List<OAuth2RegistrationId> oAuth2Clients, User user) throws Exception {
public Domain save(Domain domain, List<OAuth2ClientId> oAuth2Clients, User user) throws Exception {
ActionType actionType = domain.getId() == null ? ActionType.ADDED : ActionType.UPDATED;
TenantId tenantId = domain.getTenantId();
try {
@ -48,8 +46,6 @@ public class DefaultTbDomainService extends AbstractTbEntityService implements T
logEntityActionService.logEntityAction(tenantId, savedDomain.getId(), domain, actionType, user);
if (!CollectionUtils.isEmpty(oAuth2Clients)) {
domainService.updateOauth2Clients(domain.getTenantId(), savedDomain.getId(), oAuth2Clients);
logEntityActionService.logEntityAction(domain.getTenantId(), savedDomain.getId(), savedDomain,
UPDATED_OAUTH2_CLIENTS, user, oAuth2Clients.toString());
}
return savedDomain;
} catch (Exception e) {

4
application/src/main/java/org/thingsboard/server/service/entitiy/domain/TbDomainService.java

@ -17,13 +17,13 @@ package org.thingsboard.server.service.entitiy.domain;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.domain.Domain;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import java.util.List;
public interface TbDomainService {
Domain save(Domain domain, List<OAuth2RegistrationId> oAuth2Clients, User user) throws Exception;
Domain save(Domain domain, List<OAuth2ClientId> oAuth2Clients, User user) throws Exception;
void delete(Domain domain, User user);

6
application/src/main/java/org/thingsboard/server/service/entitiy/mobile/DefaultTbMobileAppService.java

@ -23,7 +23,7 @@ import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.id.MobileAppId;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.mobile.MobileApp;
import org.thingsboard.server.dao.mobile.MobileAppService;
@ -38,7 +38,7 @@ public class DefaultTbMobileAppService extends AbstractTbEntityService implement
private final MobileAppService mobileAppService;
@Override
public MobileApp save(MobileApp mobileApp, List<OAuth2RegistrationId> oauth2Clients, User user) throws Exception {
public MobileApp save(MobileApp mobileApp, List<OAuth2ClientId> oauth2Clients, User user) throws Exception {
ActionType actionType = mobileApp.getId() == null ? ActionType.ADDED : ActionType.UPDATED;
TenantId tenantId = mobileApp.getTenantId();
try {
@ -46,8 +46,6 @@ public class DefaultTbMobileAppService extends AbstractTbEntityService implement
logEntityActionService.logEntityAction(tenantId, savedMobileApp.getId(), mobileApp, actionType, user);
if (!CollectionUtils.isEmpty(oauth2Clients)) {
mobileAppService.updateOauth2Clients(tenantId, savedMobileApp.getId(), oauth2Clients);
logEntityActionService.logEntityAction(tenantId, savedMobileApp.getId(), savedMobileApp,
ActionType.UPDATED_OAUTH2_CLIENTS, user, oauth2Clients.toString());
}
return savedMobileApp;
} catch (Exception e) {

4
application/src/main/java/org/thingsboard/server/service/entitiy/mobile/TbMobileAppService.java

@ -16,14 +16,14 @@
package org.thingsboard.server.service.entitiy.mobile;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import org.thingsboard.server.common.data.mobile.MobileApp;
import java.util.List;
public interface TbMobileAppService {
MobileApp save(MobileApp mobileApp, List<OAuth2RegistrationId> oauth2Clients, User user) throws Exception;
MobileApp save(MobileApp mobileApp, List<OAuth2ClientId> oauth2Clients, User user) throws Exception;
void delete(MobileApp mobileApp, User user);

28
application/src/main/java/org/thingsboard/server/service/entitiy/oauth2client/DefaultTbOauth2ClientService.java

@ -20,9 +20,9 @@ import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import org.thingsboard.server.dao.oauth2.OAuth2ClientService;
import org.thingsboard.server.service.entitiy.AbstractTbEntityService;
@ -33,30 +33,30 @@ public class DefaultTbOauth2ClientService extends AbstractTbEntityService implem
private final OAuth2ClientService oAuth2ClientService;
@Override
public OAuth2Registration save(OAuth2Registration oAuth2Registration, User user) throws Exception {
ActionType actionType = oAuth2Registration.getId() == null ? ActionType.ADDED : ActionType.UPDATED;
TenantId tenantId = oAuth2Registration.getTenantId();
public OAuth2Client save(OAuth2Client oAuth2Client, User user) throws Exception {
ActionType actionType = oAuth2Client.getId() == null ? ActionType.ADDED : ActionType.UPDATED;
TenantId tenantId = oAuth2Client.getTenantId();
try {
OAuth2Registration savedRegistration = checkNotNull(oAuth2ClientService.saveOAuth2Client(tenantId, oAuth2Registration));
logEntityActionService.logEntityAction(tenantId, savedRegistration.getId(), oAuth2Registration, actionType, user);
OAuth2Client savedRegistration = checkNotNull(oAuth2ClientService.saveOAuth2Client(tenantId, oAuth2Client));
logEntityActionService.logEntityAction(tenantId, savedRegistration.getId(), oAuth2Client, actionType, user);
return savedRegistration;
} catch (Exception e) {
logEntityActionService.logEntityAction(tenantId, emptyId(EntityType.OAUTH2_CLIENT), oAuth2Registration, actionType, user, e);
logEntityActionService.logEntityAction(tenantId, emptyId(EntityType.OAUTH2_CLIENT), oAuth2Client, actionType, user, e);
throw e;
}
}
@Override
public void delete(OAuth2Registration oAuth2Registration, User user) {
public void delete(OAuth2Client oAuth2Client, User user) {
ActionType actionType = ActionType.DELETED;
TenantId tenantId = oAuth2Registration.getTenantId();
OAuth2RegistrationId oAuth2RegistrationId = oAuth2Registration.getId();
TenantId tenantId = oAuth2Client.getTenantId();
OAuth2ClientId oAuth2ClientId = oAuth2Client.getId();
try {
oAuth2ClientService.deleteById(tenantId, oAuth2RegistrationId);
logEntityActionService.logEntityAction(tenantId, oAuth2RegistrationId, oAuth2Registration, actionType, user, oAuth2Registration.getName());
oAuth2ClientService.deleteOAuth2ClientById(tenantId, oAuth2ClientId);
logEntityActionService.logEntityAction(tenantId, oAuth2ClientId, oAuth2Client, actionType, user, oAuth2Client.getName());
} catch (Exception e) {
logEntityActionService.logEntityAction(tenantId, emptyId(EntityType.OAUTH2_CLIENT), actionType, user, e,
oAuth2RegistrationId.toString());
oAuth2ClientId.toString());
throw e;
}
}

10
application/src/main/java/org/thingsboard/server/service/entitiy/oauth2client/TbOauth2ClientService.java

@ -16,16 +16,12 @@
package org.thingsboard.server.service.entitiy.oauth2client;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.domain.Domain;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
import java.util.List;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
public interface TbOauth2ClientService {
OAuth2Registration save(OAuth2Registration oAuth2Registration, User user) throws Exception;
OAuth2Client save(OAuth2Client oAuth2Client, User user) throws Exception;
void delete(OAuth2Registration oAuth2Registration, User user);
void delete(OAuth2Client oAuth2Client, User user);
}

5
application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AbstractOAuth2ClientMapper.java

@ -35,14 +35,13 @@ import org.thingsboard.server.common.data.id.DashboardId;
import org.thingsboard.server.common.data.id.IdBased;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig;
import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.common.data.security.UserCredentials;
import org.thingsboard.server.dao.customer.CustomerService;
import org.thingsboard.server.dao.dashboard.DashboardService;
import org.thingsboard.server.dao.eventsourcing.SaveEntityEvent;
import org.thingsboard.server.dao.oauth2.OAuth2User;
import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
import org.thingsboard.server.dao.tenant.TenantService;
@ -98,7 +97,7 @@ public abstract class AbstractOAuth2ClientMapper {
private final Lock userCreationLock = new ReentrantLock();
protected SecurityUser getOrCreateSecurityUserFromOAuth2User(OAuth2User oauth2User, OAuth2Registration registration) {
protected SecurityUser getOrCreateSecurityUserFromOAuth2User(OAuth2User oauth2User, OAuth2Client registration) {
OAuth2MapperConfig config = registration.getMapperConfig();

4
application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AppleOAuth2ClientMapper.java

@ -24,7 +24,7 @@ import org.springframework.util.MultiValueMap;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig;
import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import org.thingsboard.server.dao.oauth2.OAuth2User;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.security.model.SecurityUser;
@ -45,7 +45,7 @@ public class AppleOAuth2ClientMapper extends AbstractOAuth2ClientMapper implemen
private static final String EMAIL = "email";
@Override
public SecurityUser getOrCreateUserByClientPrincipal(HttpServletRequest request, OAuth2AuthenticationToken token, String providerAccessToken, OAuth2Registration registration) {
public SecurityUser getOrCreateUserByClientPrincipal(HttpServletRequest request, OAuth2AuthenticationToken token, String providerAccessToken, OAuth2Client registration) {
OAuth2MapperConfig config = registration.getMapperConfig();
Map<String, Object> attributes = updateAttributesFromRequestParams(request, token.getPrincipal().getAttributes());
String email = BasicMapperUtils.getStringAttributeByKey(attributes, config.getBasic().getEmailAttributeKey());

4
application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/BasicOAuth2ClientMapper.java

@ -19,7 +19,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig;
import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import org.thingsboard.server.dao.oauth2.OAuth2User;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.security.model.SecurityUser;
@ -33,7 +33,7 @@ import java.util.Map;
public class BasicOAuth2ClientMapper extends AbstractOAuth2ClientMapper implements OAuth2ClientMapper {
@Override
public SecurityUser getOrCreateUserByClientPrincipal(HttpServletRequest request, OAuth2AuthenticationToken token, String providerAccessToken, OAuth2Registration registration) {
public SecurityUser getOrCreateUserByClientPrincipal(HttpServletRequest request, OAuth2AuthenticationToken token, String providerAccessToken, OAuth2Client registration) {
OAuth2MapperConfig config = registration.getMapperConfig();
Map<String, Object> attributes = token.getPrincipal().getAttributes();
String email = BasicMapperUtils.getStringAttributeByKey(attributes, config.getBasic().getEmailAttributeKey());

4
application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/CustomOAuth2ClientMapper.java

@ -25,7 +25,7 @@ import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.oauth2.OAuth2CustomMapperConfig;
import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig;
import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import org.thingsboard.server.dao.oauth2.OAuth2User;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.security.model.SecurityUser;
@ -42,7 +42,7 @@ public class CustomOAuth2ClientMapper extends AbstractOAuth2ClientMapper impleme
private RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder();
@Override
public SecurityUser getOrCreateUserByClientPrincipal(HttpServletRequest request, OAuth2AuthenticationToken token, String providerAccessToken, OAuth2Registration registration) {
public SecurityUser getOrCreateUserByClientPrincipal(HttpServletRequest request, OAuth2AuthenticationToken token, String providerAccessToken, OAuth2Client registration) {
OAuth2MapperConfig config = registration.getMapperConfig();
OAuth2User oauth2User = getOAuth2User(token, providerAccessToken, config.getCustom());
return getOrCreateSecurityUserFromOAuth2User(oauth2User, registration);

4
application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/GithubOAuth2ClientMapper.java

@ -24,7 +24,7 @@ import org.springframework.security.oauth2.client.authentication.OAuth2Authentic
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig;
import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import org.thingsboard.server.dao.oauth2.OAuth2Configuration;
import org.thingsboard.server.dao.oauth2.OAuth2User;
import org.thingsboard.server.queue.util.TbCoreComponent;
@ -49,7 +49,7 @@ public class GithubOAuth2ClientMapper extends AbstractOAuth2ClientMapper impleme
private OAuth2Configuration oAuth2Configuration;
@Override
public SecurityUser getOrCreateUserByClientPrincipal(HttpServletRequest request, OAuth2AuthenticationToken token, String providerAccessToken, OAuth2Registration registration) {
public SecurityUser getOrCreateUserByClientPrincipal(HttpServletRequest request, OAuth2AuthenticationToken token, String providerAccessToken, OAuth2Client registration) {
OAuth2MapperConfig config = registration.getMapperConfig();
Map<String, String> githubMapperConfig = oAuth2Configuration.getGithubMapper();
String email = getEmail(githubMapperConfig.get(EMAIL_URL_KEY), providerAccessToken);

4
application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/OAuth2ClientMapper.java

@ -16,11 +16,11 @@
package org.thingsboard.server.service.security.auth.oauth2;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import org.thingsboard.server.service.security.model.SecurityUser;
import jakarta.servlet.http.HttpServletRequest;
public interface OAuth2ClientMapper {
SecurityUser getOrCreateUserByClientPrincipal(HttpServletRequest request, OAuth2AuthenticationToken token, String providerAccessToken, OAuth2Registration registration);
SecurityUser getOrCreateUserByClientPrincipal(HttpServletRequest request, OAuth2AuthenticationToken token, String providerAccessToken, OAuth2Client registration);
}

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

@ -28,9 +28,9 @@ import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import org.thingsboard.server.common.data.security.model.JwtPair;
import org.thingsboard.server.dao.oauth2.OAuth2ClientService;
import org.thingsboard.server.queue.util.TbCoreComponent;
@ -97,7 +97,7 @@ public class Oauth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationS
try {
OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) authentication;
OAuth2Registration registration = oAuth2ClientService.findOAuth2ClientById(TenantId.SYS_TENANT_ID, new OAuth2RegistrationId(UUID.fromString(token.getAuthorizedClientRegistrationId())));
OAuth2Client registration = oAuth2ClientService.findOAuth2ClientById(TenantId.SYS_TENANT_ID, new OAuth2ClientId(UUID.fromString(token.getAuthorizedClientRegistrationId())));
OAuth2AuthorizedClient oAuth2AuthorizedClient = oAuth2AuthorizedClientService.loadAuthorizedClient(
token.getAuthorizedClientRegistrationId(),
token.getPrincipal().getName());

10
application/src/test/java/org/thingsboard/server/controller/HomePageApiTest.java

@ -40,7 +40,7 @@ import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.domain.Domain;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.query.ApiUsageStateFilter;
import org.thingsboard.server.common.data.query.EntityCountQuery;
@ -492,9 +492,9 @@ public class HomePageApiTest extends AbstractControllerTest {
return domain;
}
private OAuth2Registration validRegistration() {
OAuth2Registration oAuth2Registration = new OAuth2Registration();
oAuth2Registration.setClientId(UUID.randomUUID().toString());
private OAuth2Client validRegistration() {
OAuth2Client oAuth2Client = new OAuth2Client();
oAuth2Client.setClientId(UUID.randomUUID().toString());
// .clientSecret(UUID.randomUUID().toString())
// .authorizationUri(UUID.randomUUID().toString())
// .accessTokenUri(UUID.randomUUID().toString())
@ -516,6 +516,6 @@ public class HomePageApiTest extends AbstractControllerTest {
// .build()
// )
// .build();
return oAuth2Registration;
return oAuth2Client;
}
}

10
application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java

@ -63,7 +63,7 @@ import org.thingsboard.server.common.data.id.DeviceProfileId;
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.oauth2.OAuth2Registration;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import org.thingsboard.server.common.data.ota.ChecksumAlgorithm;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.page.PageData;
@ -545,11 +545,11 @@ abstract public class AbstractEdgeTest extends AbstractControllerTest {
Optional<OAuth2UpdateMsg> oAuth2UpdateMsgOpt = edgeImitator.findMessageByType(OAuth2UpdateMsg.class);
Assert.assertTrue(oAuth2UpdateMsgOpt.isPresent());
OAuth2UpdateMsg oAuth2ProviderUpdateMsg = oAuth2UpdateMsgOpt.get();
OAuth2Registration oAuth2Registration = JacksonUtil.fromString(oAuth2ProviderUpdateMsg.getEntity(), OAuth2Registration.class, true);
Assert.assertNotNull(oAuth2Registration);
OAuth2Registration auth2Info = doGet("/api/oauth2/config", OAuth2Registration.class);
OAuth2Client oAuth2Client = JacksonUtil.fromString(oAuth2ProviderUpdateMsg.getEntity(), OAuth2Client.class, true);
Assert.assertNotNull(oAuth2Client);
OAuth2Client auth2Info = doGet("/api/oauth2/config", OAuth2Client.class);
Assert.assertNotNull(auth2Info);
Assert.assertEquals(oAuth2Registration, auth2Info);
Assert.assertEquals(oAuth2Client, auth2Info);
testAutoGeneratedCodeByProtobuf(oAuth2ProviderUpdateMsg);
}

48
application/src/test/java/org/thingsboard/server/edge/OAuth2EdgeTest.java

@ -22,7 +22,7 @@ import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.oauth2.MapperType;
import org.thingsboard.server.common.data.oauth2.OAuth2CustomMapperConfig;
import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig;
import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import org.thingsboard.server.dao.service.DaoSqlTest;
import org.thingsboard.server.gen.edge.v1.OAuth2UpdateMsg;
@ -40,47 +40,47 @@ public class OAuth2EdgeTest extends AbstractEdgeTest {
// enable oauth
edgeImitator.allowIgnoredTypes();
edgeImitator.expectMessageAmount(1);
OAuth2Registration oAuth2Registration = createDefaultOAuth2Info();
oAuth2Registration = doPost("/api/oauth2/config", oAuth2Registration, OAuth2Registration.class);
OAuth2Client oAuth2Client = createDefaultOAuth2Info();
oAuth2Client = doPost("/api/oauth2/config", oAuth2Client, OAuth2Client.class);
Assert.assertTrue(edgeImitator.waitForMessages());
AbstractMessage latestMessage = edgeImitator.getLatestMessage();
Assert.assertTrue(latestMessage instanceof OAuth2UpdateMsg);
OAuth2UpdateMsg oAuth2ProviderUpdateMsg = (OAuth2UpdateMsg) latestMessage;
OAuth2Registration result = JacksonUtil.fromString(oAuth2ProviderUpdateMsg.getEntity(), OAuth2Registration.class, true);
Assert.assertEquals(oAuth2Registration, result);
OAuth2Client result = JacksonUtil.fromString(oAuth2ProviderUpdateMsg.getEntity(), OAuth2Client.class, true);
Assert.assertEquals(oAuth2Client, result);
// disable oauth support
edgeImitator.expectMessageAmount(1);
doPost("/api/oauth2/config", oAuth2Registration, OAuth2Registration.class);
doPost("/api/oauth2/config", oAuth2Client, OAuth2Client.class);
Assert.assertTrue(edgeImitator.waitForMessages());
latestMessage = edgeImitator.getLatestMessage();
Assert.assertTrue(latestMessage instanceof OAuth2UpdateMsg);
oAuth2ProviderUpdateMsg = (OAuth2UpdateMsg) latestMessage;
result = JacksonUtil.fromString(oAuth2ProviderUpdateMsg.getEntity(), OAuth2Registration.class, true);
Assert.assertEquals(oAuth2Registration, result);
result = JacksonUtil.fromString(oAuth2ProviderUpdateMsg.getEntity(), OAuth2Client.class, true);
Assert.assertEquals(oAuth2Client, result);
edgeImitator.ignoreType(OAuth2UpdateMsg.class);
loginTenantAdmin();
}
private OAuth2Registration createDefaultOAuth2Info() {
private OAuth2Client createDefaultOAuth2Info() {
return validRegistrationInfo();
}
private OAuth2Registration validRegistrationInfo() {
OAuth2Registration oAuth2Registration = new OAuth2Registration();
oAuth2Registration.setClientId(UUID.randomUUID().toString());
oAuth2Registration.setClientSecret(UUID.randomUUID().toString());
oAuth2Registration.setAuthorizationUri(UUID.randomUUID().toString());
oAuth2Registration.setAccessTokenUri(UUID.randomUUID().toString());
oAuth2Registration.setScope(Arrays.asList(UUID.randomUUID().toString(), UUID.randomUUID().toString()));
oAuth2Registration.setPlatforms(Collections.emptyList());
oAuth2Registration.setUserInfoUri(UUID.randomUUID().toString());
oAuth2Registration.setUserNameAttributeName(UUID.randomUUID().toString());
oAuth2Registration.setJwkSetUri(UUID.randomUUID().toString());
oAuth2Registration.setClientAuthenticationMethod(UUID.randomUUID().toString());
oAuth2Registration.setLoginButtonLabel(UUID.randomUUID().toString());
oAuth2Registration.setMapperConfig(
private OAuth2Client validRegistrationInfo() {
OAuth2Client oAuth2Client = new OAuth2Client();
oAuth2Client.setClientId(UUID.randomUUID().toString());
oAuth2Client.setClientSecret(UUID.randomUUID().toString());
oAuth2Client.setAuthorizationUri(UUID.randomUUID().toString());
oAuth2Client.setAccessTokenUri(UUID.randomUUID().toString());
oAuth2Client.setScope(Arrays.asList(UUID.randomUUID().toString(), UUID.randomUUID().toString()));
oAuth2Client.setPlatforms(Collections.emptyList());
oAuth2Client.setUserInfoUri(UUID.randomUUID().toString());
oAuth2Client.setUserNameAttributeName(UUID.randomUUID().toString());
oAuth2Client.setJwkSetUri(UUID.randomUUID().toString());
oAuth2Client.setClientAuthenticationMethod(UUID.randomUUID().toString());
oAuth2Client.setLoginButtonLabel(UUID.randomUUID().toString());
oAuth2Client.setMapperConfig(
OAuth2MapperConfig.builder()
.type(MapperType.CUSTOM)
.custom(
@ -89,7 +89,7 @@ public class OAuth2EdgeTest extends AbstractEdgeTest {
.build()
)
.build());
return oAuth2Registration;
return oAuth2Client;
}
}

6
common/dao-api/src/main/java/org/thingsboard/server/dao/domain/DomainService.java

@ -18,12 +18,11 @@ package org.thingsboard.server.dao.domain;
import org.thingsboard.server.common.data.domain.Domain;
import org.thingsboard.server.common.data.domain.DomainInfo;
import org.thingsboard.server.common.data.id.DomainId;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.entity.EntityDaoService;
import java.util.List;
import java.util.UUID;
public interface DomainService extends EntityDaoService {
@ -39,6 +38,7 @@ public interface DomainService extends EntityDaoService {
boolean isOauth2Enabled(TenantId tenantId);
void updateOauth2Clients(TenantId tenantId, DomainId domainId, List<OAuth2RegistrationId> oAuth2ClientIds);
void updateOauth2Clients(TenantId tenantId, DomainId domainId, List<OAuth2ClientId> oAuth2ClientIds);
void deleteDomainsByTenantId(TenantId tenantId);
}

5
common/dao-api/src/main/java/org/thingsboard/server/dao/mobile/MobileAppService.java

@ -16,7 +16,7 @@
package org.thingsboard.server.dao.mobile;
import org.thingsboard.server.common.data.id.MobileAppId;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.mobile.MobileApp;
import org.thingsboard.server.common.data.mobile.MobileAppInfo;
@ -36,6 +36,7 @@ public interface MobileAppService extends EntityDaoService {
MobileAppInfo findMobileAppInfoById(TenantId tenantId, MobileAppId mobileAppId);
void updateOauth2Clients(TenantId tenantId, MobileAppId mobileAppId, List<OAuth2RegistrationId> oAuth2ClientIds);
void updateOauth2Clients(TenantId tenantId, MobileAppId mobileAppId, List<OAuth2ClientId> oAuth2ClientIds);
void deleteMobileAppsByTenantId(TenantId tenantId);
}

24
common/dao-api/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientService.java

@ -15,11 +15,11 @@
*/
package org.thingsboard.server.dao.oauth2;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientLoginInfo;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo;
import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
import org.thingsboard.server.common.data.oauth2.OAuth2RegistrationInfo;
import org.thingsboard.server.common.data.oauth2.PlatformType;
import org.thingsboard.server.dao.entity.EntityDaoService;
@ -28,19 +28,21 @@ import java.util.UUID;
public interface OAuth2ClientService extends EntityDaoService {
List<OAuth2ClientInfo> getWebOAuth2Clients(String domainName, PlatformType platformType);
List<OAuth2ClientLoginInfo> findOAuth2ClientLoginInfosByDomainName(String domainName);
List<OAuth2ClientInfo> getMobileOAuth2Clients(String pkgName, PlatformType platformType);
List<OAuth2ClientLoginInfo> findOAuth2ClientLoginInfosByMobilePkgNameAndPlatformType(String pkgName, PlatformType platformType);
List<OAuth2RegistrationInfo> findOauth2ClientInfosByTenantId(TenantId tenantId);
List<OAuth2Client> findOAuth2ClientsByTenantId(TenantId tenantId);
List<OAuth2Registration> findOauth2ClientsByTenantId(TenantId tenantId);
OAuth2Client saveOAuth2Client(TenantId tenantId, OAuth2Client oAuth2Client);
OAuth2Registration saveOAuth2Client(TenantId tenantId, OAuth2Registration oAuth2Registration);
OAuth2Registration findOAuth2ClientById(TenantId tenantId, OAuth2RegistrationId providerId);
OAuth2Client findOAuth2ClientById(TenantId tenantId, OAuth2ClientId providerId);
String findAppSecret(UUID registrationId, String pkgName);
void deleteById(TenantId tenantId, OAuth2RegistrationId oAuth2RegistrationId);
void deleteOAuth2ClientById(TenantId tenantId, OAuth2ClientId oAuth2ClientId);
void deleteOauth2ClientsByTenantId(TenantId tenantId);
List<OAuth2ClientInfo> findOAuth2ClientInfosByTenantId(TenantId tenantId);
}

3
common/data/src/main/java/org/thingsboard/server/common/data/audit/ActionType.java

@ -57,8 +57,7 @@ public enum ActionType {
ADDED_COMMENT(false, TbMsgType.COMMENT_CREATED),
UPDATED_COMMENT(false, TbMsgType.COMMENT_UPDATED),
DELETED_COMMENT(false, null),
SMS_SENT(false, null),
UPDATED_OAUTH2_CLIENTS(false, null);
SMS_SENT(false, null);
@Getter
private final boolean isRead;

18
common/data/src/main/java/org/thingsboard/server/common/data/domain/DomainInfo.java

@ -16,29 +16,23 @@
package org.thingsboard.server.common.data.domain;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.thingsboard.server.common.data.oauth2.HasOauth2Registrations;
import org.thingsboard.server.common.data.oauth2.OAuth2RegistrationInfo;
import org.thingsboard.server.common.data.oauth2.HasOauth2Clients;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo;
import java.util.List;
@EqualsAndHashCode(callSuper = true)
@Data
@ToString
@AllArgsConstructor
@Builder
@Schema
public class DomainInfo extends Domain implements HasOauth2Registrations {
public class DomainInfo extends Domain implements HasOauth2Clients {
@Schema(description = "List of available oauth2 client registration")
private List<OAuth2RegistrationInfo> oauth2RegistrationInfos;
private List<OAuth2ClientInfo> oauth2ClientInfos;
public DomainInfo(Domain domain, List<OAuth2RegistrationInfo> oauth2RegistrationInfos) {
public DomainInfo(Domain domain, List<OAuth2ClientInfo> oauth2ClientInfos) {
super(domain);
this.oauth2RegistrationInfos = oauth2RegistrationInfos;
this.oauth2ClientInfos = oauth2ClientInfos;
}
}

6
common/data/src/main/java/org/thingsboard/server/common/data/domain/DomainOauth2Registration.java → common/data/src/main/java/org/thingsboard/server/common/data/domain/DomainOauth2Client.java

@ -19,14 +19,14 @@ import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.thingsboard.server.common.data.id.DomainId;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DomainOauth2Registration {
public class DomainOauth2Client {
private DomainId domainId;
private OAuth2RegistrationId oAuth2RegistrationId;
private OAuth2ClientId oAuth2ClientId;
}

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

@ -106,7 +106,7 @@ public class EntityIdFactory {
case QUEUE_STATS:
return new QueueStatsId(uuid);
case OAUTH2_CLIENT:
return new OAuth2RegistrationId(uuid);
return new OAuth2ClientId(uuid);
case MOBILE_APP:
return new MobileAppId(uuid);
case DOMAIN:

8
common/data/src/main/java/org/thingsboard/server/common/data/id/OAuth2RegistrationId.java → common/data/src/main/java/org/thingsboard/server/common/data/id/OAuth2ClientId.java

@ -21,15 +21,15 @@ import org.thingsboard.server.common.data.EntityType;
import java.util.UUID;
public class OAuth2RegistrationId extends UUIDBased implements EntityId {
public class OAuth2ClientId extends UUIDBased implements EntityId {
@JsonCreator
public OAuth2RegistrationId(@JsonProperty("id") UUID id) {
public OAuth2ClientId(@JsonProperty("id") UUID id) {
super(id);
}
public static OAuth2RegistrationId fromString(String oauth2RegistrationId) {
return new OAuth2RegistrationId(UUID.fromString(oauth2RegistrationId));
public static OAuth2ClientId fromString(String oauth2ClientId) {
return new OAuth2ClientId(UUID.fromString(oauth2ClientId));
}
@Override

12
common/data/src/main/java/org/thingsboard/server/common/data/mobile/MobileAppInfo.java

@ -22,8 +22,8 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.thingsboard.server.common.data.oauth2.HasOauth2Registrations;
import org.thingsboard.server.common.data.oauth2.OAuth2RegistrationInfo;
import org.thingsboard.server.common.data.oauth2.HasOauth2Clients;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo;
import java.util.List;
@ -34,14 +34,14 @@ import java.util.List;
@AllArgsConstructor
@Builder
@Schema
public class MobileAppInfo extends MobileApp implements HasOauth2Registrations {
public class MobileAppInfo extends MobileApp implements HasOauth2Clients {
@Schema(description = "List of available oauth2 client registrations")
private List<OAuth2RegistrationInfo> oauth2RegistrationInfos;
private List<OAuth2ClientInfo> oauth2ClientInfos;
public MobileAppInfo(MobileApp mobileApp, List<OAuth2RegistrationInfo> oauth2RegistrationInfos) {
public MobileAppInfo(MobileApp mobileApp, List<OAuth2ClientInfo> oauth2ClientInfos) {
super(mobileApp);
this.oauth2RegistrationInfos = oauth2RegistrationInfos;
this.oauth2ClientInfos = oauth2ClientInfos;
}
}

6
common/data/src/main/java/org/thingsboard/server/common/data/mobile/MobileAppOauth2Registration.java → common/data/src/main/java/org/thingsboard/server/common/data/mobile/MobileAppOauth2Client.java

@ -19,14 +19,14 @@ import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.thingsboard.server.common.data.id.MobileAppId;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MobileAppOauth2Registration {
public class MobileAppOauth2Client {
private MobileAppId mobileAppId;
private OAuth2RegistrationId oAuth2RegistrationId;
private OAuth2ClientId oAuth2ClientId;
}

6
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/HasOauth2Registrations.java → common/data/src/main/java/org/thingsboard/server/common/data/oauth2/HasOauth2Clients.java

@ -16,13 +16,11 @@
package org.thingsboard.server.common.data.oauth2;
import org.thingsboard.server.common.data.EntityInfo;
import java.io.Serializable;
import java.util.List;
public interface HasOauth2Registrations extends Serializable {
public interface HasOauth2Clients extends Serializable {
List<OAuth2RegistrationInfo> getOauth2RegistrationInfos();
List<OAuth2ClientInfo> getOauth2ClientInfos();
}

20
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2Registration.java → common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2Client.java

@ -18,6 +18,9 @@ package org.thingsboard.server.common.data.oauth2;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
@ -25,7 +28,7 @@ import lombok.ToString;
import org.thingsboard.server.common.data.BaseDataWithAdditionalInfo;
import org.thingsboard.server.common.data.HasName;
import org.thingsboard.server.common.data.HasTenantId;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import org.thingsboard.server.common.data.id.TenantId;
import java.util.List;
@ -34,33 +37,43 @@ import java.util.List;
@Data
@ToString(exclude = {"clientSecret"})
@NoArgsConstructor
public class OAuth2Registration extends BaseDataWithAdditionalInfo<OAuth2RegistrationId> implements HasName, HasTenantId {
public class OAuth2Client extends BaseDataWithAdditionalInfo<OAuth2ClientId> implements HasName, HasTenantId {
@Schema(description = "JSON object with Tenant Id")
private TenantId tenantId;
@Schema(description = "Oauth2 client title")
@NotBlank
private String title;
@Schema(description = "Config for mapping OAuth2 log in response to platform entities", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull
private OAuth2MapperConfig mapperConfig;
@Schema(description = "OAuth2 client ID. Cannot be empty", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank
private String clientId;
@Schema(description = "OAuth2 client secret. Cannot be empty", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank
private String clientSecret;
@Schema(description = "Authorization URI of the OAuth2 provider. Cannot be empty", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank
private String authorizationUri;
@Schema(description = "Access token URI of the OAuth2 provider. Cannot be empty", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank
private String accessTokenUri;
@Schema(description = "OAuth scopes that will be requested from OAuth2 platform. Cannot be empty", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty
private List<String> scope;
@Schema(description = "User info URI of the OAuth2 provider")
private String userInfoUri;
@Schema(description = "Name of the username attribute in OAuth2 provider response. Cannot be empty")
@NotBlank
private String userNameAttributeName;
@Schema(description = "JSON Web Key URI of the OAuth2 provider")
private String jwkSetUri;
@Schema(description = "Client authentication method to use: 'BASIC' or 'POST'. Cannot be empty", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank
private String clientAuthenticationMethod;
@Schema(description = "OAuth2 provider label. Cannot be empty", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank
private String loginButtonLabel;
@Schema(description = "Log in button icon for OAuth2 provider")
private String loginButtonIcon;
@ -69,9 +82,10 @@ public class OAuth2Registration extends BaseDataWithAdditionalInfo<OAuth2Registr
@Schema(description = "Additional info of OAuth2 client (e.g. providerName)", requiredMode = Schema.RequiredMode.REQUIRED)
private JsonNode additionalInfo;
public OAuth2Registration(OAuth2Registration registration) {
public OAuth2Client(OAuth2Client registration) {
super(registration);
this.tenantId = registration.tenantId;
this.title = registration.title;
this.mapperConfig = registration.mapperConfig;
this.clientId = registration.clientId;
this.clientSecret = registration.clientSecret;

43
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientInfo.java

@ -16,30 +16,35 @@
package org.thingsboard.server.common.data.oauth2;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.thingsboard.server.common.data.BaseData;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import java.util.List;
@EqualsAndHashCode
@Data
@NoArgsConstructor
@AllArgsConstructor
@Schema
public class OAuth2ClientInfo {
@Schema(description = "OAuth2 client name", example = "GitHub")
private String name;
@Schema(description = "Name of the icon, displayed on OAuth2 log in button", example = "github-logo")
private String icon;
@Schema(description = "URI for OAuth2 log in. On HTTP GET request to this URI, it redirects to the OAuth2 provider page",
example = "/oauth2/authorization/8352f191-2b4d-11ec-9ed1-cbf57c026ecc")
private String url;
public OAuth2ClientInfo(OAuth2ClientInfo oauth2ClientInfo) {
this.name = oauth2ClientInfo.getName();
this.icon = oauth2ClientInfo.getIcon();
this.url = oauth2ClientInfo.getUrl();
@EqualsAndHashCode(callSuper = true)
public class OAuth2ClientInfo extends BaseData<OAuth2ClientId> {
@Schema(description = "Oauth2 client registration title (e.g. Google)")
private String title;
@Schema(description = "List of platforms for which usage of the OAuth2 client is allowed (empty for all allowed)")
private List<PlatformType> platforms;
public OAuth2ClientInfo() {
super();
}
public OAuth2ClientInfo(OAuth2ClientId id) {
super(id);
}
public OAuth2ClientInfo(OAuth2Client oAuth2Client) {
super(oAuth2Client);
this.title = oAuth2Client.getTitle();
this.platforms = oAuth2Client.getPlatforms();
}
}

39
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientLoginInfo.java

@ -0,0 +1,39 @@
/**
* Copyright © 2016-2024 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.common.data.oauth2;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
@EqualsAndHashCode
@Data
@NoArgsConstructor
@AllArgsConstructor
@Schema
public class OAuth2ClientLoginInfo {
@Schema(description = "OAuth2 client name", example = "GitHub")
private String name;
@Schema(description = "Name of the icon, displayed on OAuth2 log in button", example = "github-logo")
private String icon;
@Schema(description = "URI for OAuth2 log in. On HTTP GET request to this URI, it redirects to the OAuth2 provider page",
example = "/oauth2/authorization/8352f191-2b4d-11ec-9ed1-cbf57c026ecc")
private String url;
}

2
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2MapperConfig.java

@ -16,6 +16,7 @@
package org.thingsboard.server.common.data.oauth2;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -33,6 +34,7 @@ public class OAuth2MapperConfig {
@Schema(description = "Whether user credentials should be activated when user is created after successful authentication")
private boolean activateUser;
@Schema(description = "Type of OAuth2 mapper. Depending on this param, different mapper config fields must be specified", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull
private MapperType type;
@Valid
@Schema(description = "Mapper config for BASIC and GITHUB mapper types")

49
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2RegistrationInfo.java

@ -1,49 +0,0 @@
/**
* Copyright © 2016-2024 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.common.data.oauth2;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.BaseData;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import java.util.List;
@Data
@Schema
@EqualsAndHashCode(callSuper = true)
public class OAuth2RegistrationInfo extends BaseData<OAuth2RegistrationId> {
@Schema(description = "Oauth2 client registration title (e.g. Google)")
private String title;
@Schema(description = "List of platforms for which usage of the OAuth2 client is allowed (empty for all allowed)")
private List<PlatformType> platforms;
public OAuth2RegistrationInfo() {
super();
}
public OAuth2RegistrationInfo(OAuth2RegistrationId id) {
super(id);
}
public OAuth2RegistrationInfo(OAuth2RegistrationId id, String title, List<PlatformType> platforms) {
super(id);
this.title = title;
this.platforms = platforms;
}
}

11
dao/src/main/java/org/thingsboard/server/dao/domain/DomainDao.java

@ -16,9 +16,9 @@
package org.thingsboard.server.dao.domain;
import org.thingsboard.server.common.data.domain.Domain;
import org.thingsboard.server.common.data.domain.DomainOauth2Registration;
import org.thingsboard.server.common.data.domain.DomainOauth2Client;
import org.thingsboard.server.common.data.id.DomainId;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.Dao;
@ -30,10 +30,11 @@ public interface DomainDao extends Dao<Domain> {
int countDomainByTenantIdAndOauth2Enabled(TenantId tenantId, boolean oauth2Enabled);
List<DomainOauth2Registration> findOauth2ClientsByDomainId(TenantId tenantId, DomainId domainId);
List<DomainOauth2Client> findOauth2ClientsByDomainId(TenantId tenantId, DomainId domainId);
void saveOauth2Clients(DomainOauth2Registration domainOauth2Registration);
void saveOauth2Clients(DomainOauth2Client domainOauth2Client);
void removeOauth2Clients(DomainId domainId, OAuth2RegistrationId oAuth2RegistrationId);
void removeOauth2Clients(DomainId domainId, OAuth2ClientId oAuth2ClientId);
void deleteByTenantId(TenantId tenantId);
}

50
dao/src/main/java/org/thingsboard/server/dao/domain/DomainServiceImpl.java

@ -24,17 +24,18 @@ import org.thingsboard.server.common.data.BaseData;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.domain.Domain;
import org.thingsboard.server.common.data.domain.DomainInfo;
import org.thingsboard.server.common.data.domain.DomainOauth2Registration;
import org.thingsboard.server.common.data.domain.DomainOauth2Client;
import org.thingsboard.server.common.data.id.DomainId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.HasId;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.entity.AbstractEntityService;
import org.thingsboard.server.dao.eventsourcing.DeleteEntityEvent;
import org.thingsboard.server.dao.eventsourcing.SaveEntityEvent;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.oauth2.OAuth2RegistrationDao;
import org.thingsboard.server.dao.oauth2.OAuth2ClientDao;
import org.thingsboard.server.dao.oauth2.OAuth2Utils;
import org.thingsboard.server.dao.service.DataValidator;
import org.thingsboard.server.dao.service.Validator;
@ -42,6 +43,7 @@ import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import static org.thingsboard.server.dao.service.Validator.validateIds;
@ -53,7 +55,7 @@ public class DomainServiceImpl extends AbstractEntityService implements DomainSe
public static final String INCORRECT_DOMAIN_ID = "Incorrect domainId ";
@Autowired
private OAuth2RegistrationDao oauth2RegistrationDao;
private OAuth2ClientDao oauth2ClientDao;
@Autowired
private DomainDao domainDao;
@Autowired
@ -78,7 +80,7 @@ public class DomainServiceImpl extends AbstractEntityService implements DomainSe
}
@Override
public void updateOauth2Clients(TenantId tenantId, DomainId domainId, List<OAuth2RegistrationId> oAuth2ClientIds) {
public void updateOauth2Clients(TenantId tenantId, DomainId domainId, List<OAuth2ClientId> oAuth2ClientIds) {
log.trace("Executing addOauth2Clients, domainId [{}], oAuth2ClientIds [{}]", domainId, oAuth2ClientIds);
Validator.validateId(tenantId, id -> INCORRECT_TENANT_ID + id);
Validator.validateId(domainId, id -> INCORRECT_DOMAIN_ID + id);
@ -86,20 +88,20 @@ public class DomainServiceImpl extends AbstractEntityService implements DomainSe
if (!oAuth2ClientIds.isEmpty()) {
validateIds(oAuth2ClientIds, ids -> "Incorrect oAuth2ClientIds " + ids);
}
List<DomainOauth2Registration> oauth2Clients = new ArrayList<>();
for (OAuth2RegistrationId oAuth2RegistrationId: oAuth2ClientIds) {
oauth2Clients.add(new DomainOauth2Registration(domainId, oAuth2RegistrationId));
List<DomainOauth2Client> oauth2Clients = new ArrayList<>();
for (OAuth2ClientId oAuth2ClientId : oAuth2ClientIds) {
oauth2Clients.add(new DomainOauth2Client(domainId, oAuth2ClientId));
}
List<DomainOauth2Registration> existingClients = domainDao.findOauth2ClientsByDomainId(tenantId, domainId);
List<OAuth2RegistrationId> toRemove = existingClients.stream()
.map(DomainOauth2Registration::getOAuth2RegistrationId)
List<DomainOauth2Client> existingClients = domainDao.findOauth2ClientsByDomainId(tenantId, domainId);
List<OAuth2ClientId> toRemove = existingClients.stream()
.map(DomainOauth2Client::getOAuth2ClientId)
.filter(clientId -> oAuth2ClientIds.stream().noneMatch(oauth2ClientId ->
oauth2ClientId.equals(clientId))).toList();
for (OAuth2RegistrationId clientId : toRemove) {
for (OAuth2ClientId clientId : toRemove) {
domainDao.removeOauth2Clients(domainId, clientId);
}
for (DomainOauth2Registration domainOauth2Registration : oauth2Clients) {
domainDao.saveOauth2Clients(domainOauth2Registration);
for (DomainOauth2Client domainOauth2Client : oauth2Clients) {
domainDao.saveOauth2Clients(domainOauth2Client);
}
eventPublisher.publishEvent(SaveEntityEvent.builder().tenantId(tenantId)
.entityId(domainId).created(false).build());
@ -124,7 +126,9 @@ public class DomainServiceImpl extends AbstractEntityService implements DomainSe
List<Domain> domains = domainDao.findByTenantId(tenantId);
List<DomainInfo> domainInfos = new ArrayList<>();
domains.stream().sorted(Comparator.comparing(BaseData::getUuidId)).forEach(domain -> {
domainInfos.add(new DomainInfo(domain, oauth2RegistrationDao.findInfosByDomainId(domain.getUuidId())));
domainInfos.add(new DomainInfo(domain, oauth2ClientDao.findByDomainId(domain.getUuidId()).stream()
.map(OAuth2Utils::toClientInfo)
.collect(Collectors.toList())));
});
return domainInfos;
}
@ -136,7 +140,9 @@ public class DomainServiceImpl extends AbstractEntityService implements DomainSe
if (domain == null) {
return null;
}
return new DomainInfo(domain, oauth2RegistrationDao.findInfosByDomainId(domain.getUuidId()));
return new DomainInfo(domain, oauth2ClientDao.findByDomainId(domain.getUuidId()).stream()
.map(OAuth2Utils::toClientInfo)
.collect(Collectors.toList()));
}
@Override
@ -145,6 +151,18 @@ public class DomainServiceImpl extends AbstractEntityService implements DomainSe
return domainDao.countDomainByTenantIdAndOauth2Enabled(tenantId, true) > 0;
}
@Override
public void deleteDomainsByTenantId(TenantId tenantId) {
log.trace("Executing deleteDomainsByTenantId, tenantId [{}]", tenantId);
Validator.validateId(tenantId, id -> INCORRECT_TENANT_ID + id);
domainDao.deleteByTenantId(tenantId);
}
@Override
public void deleteByTenantId(TenantId tenantId) {
deleteDomainsByTenantId(tenantId);
}
@Override
public Optional<HasId<?>> findEntity(TenantId tenantId, EntityId entityId) {
return Optional.ofNullable(findDomainById(tenantId, new DomainId(entityId.getId())));

12
dao/src/main/java/org/thingsboard/server/dao/mobile/MobileAppDao.java

@ -16,10 +16,10 @@
package org.thingsboard.server.dao.mobile;
import org.thingsboard.server.common.data.id.MobileAppId;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.mobile.MobileApp;
import org.thingsboard.server.common.data.mobile.MobileAppOauth2Registration;
import org.thingsboard.server.common.data.mobile.MobileAppOauth2Client;
import org.thingsboard.server.dao.Dao;
import java.util.List;
@ -28,9 +28,11 @@ public interface MobileAppDao extends Dao<MobileApp> {
List<MobileApp> findByTenantId(TenantId tenantId);
List<MobileAppOauth2Registration> findOauth2ClientsByMobileAppId(TenantId tenantId, MobileAppId mobileAppId);
List<MobileAppOauth2Client> findOauth2ClientsByMobileAppId(TenantId tenantId, MobileAppId mobileAppId);
void saveOauth2Clients(MobileAppOauth2Registration mobileAppOauth2Registration);
void saveOauth2Clients(MobileAppOauth2Client mobileAppOauth2Client);
void removeOauth2Clients(MobileAppId mobileAppId, OAuth2RegistrationId oAuth2RegistrationId);
void removeOauth2Clients(MobileAppId mobileAppId, OAuth2ClientId oAuth2ClientId);
void deleteByTenantId(TenantId tenantId);
}

50
dao/src/main/java/org/thingsboard/server/dao/mobile/MobileAppServiceImpl.java

@ -25,17 +25,17 @@ import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.HasId;
import org.thingsboard.server.common.data.id.MobileAppId;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.mobile.MobileApp;
import org.thingsboard.server.common.data.mobile.MobileAppInfo;
import org.thingsboard.server.common.data.mobile.MobileAppOauth2Registration;
import org.thingsboard.server.common.data.oauth2.OAuth2RegistrationInfo;
import org.thingsboard.server.common.data.mobile.MobileAppOauth2Client;
import org.thingsboard.server.dao.entity.AbstractEntityService;
import org.thingsboard.server.dao.eventsourcing.DeleteEntityEvent;
import org.thingsboard.server.dao.eventsourcing.SaveEntityEvent;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.oauth2.OAuth2RegistrationDao;
import org.thingsboard.server.dao.oauth2.OAuth2ClientDao;
import org.thingsboard.server.dao.oauth2.OAuth2Utils;
import org.thingsboard.server.dao.service.DataValidator;
import org.thingsboard.server.dao.service.Validator;
@ -55,7 +55,7 @@ public class MobileAppServiceImpl extends AbstractEntityService implements Mobil
public static final String INCORRECT_MOBILE_APP_ID = "Incorrect mobileApppId ";
@Autowired
private OAuth2RegistrationDao oauth2RegistrationDao;
private OAuth2ClientDao oauth2ClientDao;
@Autowired
private MobileAppDao mobileAppDao;
@Autowired
@ -98,7 +98,9 @@ public class MobileAppServiceImpl extends AbstractEntityService implements Mobil
List<MobileApp> mobileApps = mobileAppDao.findByTenantId(tenantId);
List<MobileAppInfo> mobileAppInfos = new ArrayList<>();
mobileApps.stream().sorted(Comparator.comparing(BaseData::getUuidId)).forEach(mobileApp -> {
mobileAppInfos.add(new MobileAppInfo(mobileApp, oauth2RegistrationDao.findInfosByMobileAppId(mobileApp.getUuidId())));
mobileAppInfos.add(new MobileAppInfo(mobileApp, oauth2ClientDao.findByMobileAppId(mobileApp.getUuidId()).stream()
.map(OAuth2Utils::toClientInfo)
.collect(Collectors.toList())));
});
return mobileAppInfos;
}
@ -110,11 +112,13 @@ public class MobileAppServiceImpl extends AbstractEntityService implements Mobil
if (mobileApp == null) {
return null;
}
return new MobileAppInfo(mobileApp, oauth2RegistrationDao.findInfosByMobileAppId(mobileApp.getUuidId()));
return new MobileAppInfo(mobileApp, oauth2ClientDao.findByMobileAppId(mobileApp.getUuidId()).stream()
.map(OAuth2Utils::toClientInfo)
.collect(Collectors.toList()));
}
@Override
public void updateOauth2Clients(TenantId tenantId, MobileAppId mobileAppId, List<OAuth2RegistrationId> oAuth2ClientIds) {
public void updateOauth2Clients(TenantId tenantId, MobileAppId mobileAppId, List<OAuth2ClientId> oAuth2ClientIds) {
log.trace("Executing updateOauth2Clients, mobileAppId [{}], oAuth2ClientIds [{}]", mobileAppId, oAuth2ClientIds);
Validator.validateId(tenantId, id -> INCORRECT_TENANT_ID + id);
Validator.validateId(mobileAppId, id -> INCORRECT_MOBILE_APP_ID + id);
@ -122,20 +126,20 @@ public class MobileAppServiceImpl extends AbstractEntityService implements Mobil
if (!oAuth2ClientIds.isEmpty()) {
validateIds(oAuth2ClientIds, ids -> "Incorrect oAuth2ClientIds " + ids);
}
List<MobileAppOauth2Registration> oauth2Clients = new ArrayList<>();
for (OAuth2RegistrationId oAuth2RegistrationId: oAuth2ClientIds) {
oauth2Clients.add(new MobileAppOauth2Registration(mobileAppId, oAuth2RegistrationId));
List<MobileAppOauth2Client> oauth2Clients = new ArrayList<>();
for (OAuth2ClientId oAuth2ClientId : oAuth2ClientIds) {
oauth2Clients.add(new MobileAppOauth2Client(mobileAppId, oAuth2ClientId));
}
List<MobileAppOauth2Registration> existingClients = mobileAppDao.findOauth2ClientsByMobileAppId(tenantId, mobileAppId);
List<OAuth2RegistrationId> toRemove = existingClients.stream()
.map(MobileAppOauth2Registration::getOAuth2RegistrationId)
List<MobileAppOauth2Client> existingClients = mobileAppDao.findOauth2ClientsByMobileAppId(tenantId, mobileAppId);
List<OAuth2ClientId> toRemove = existingClients.stream()
.map(MobileAppOauth2Client::getOAuth2ClientId)
.filter(clientId -> oAuth2ClientIds.stream().noneMatch(oauth2ClientId ->
oauth2ClientId.equals(clientId))).toList();
for (OAuth2RegistrationId clientId : toRemove) {
for (OAuth2ClientId clientId : toRemove) {
mobileAppDao.removeOauth2Clients(mobileAppId, clientId);
}
for (MobileAppOauth2Registration mobileAppOauth2Registration : oauth2Clients) {
mobileAppDao.saveOauth2Clients(mobileAppOauth2Registration);
for (MobileAppOauth2Client mobileAppOauth2Client : oauth2Clients) {
mobileAppDao.saveOauth2Clients(mobileAppOauth2Client);
}
eventPublisher.publishEvent(SaveEntityEvent.builder().tenantId(tenantId)
.entityId(mobileAppId).created(false).build());
@ -160,4 +164,16 @@ public class MobileAppServiceImpl extends AbstractEntityService implements Mobil
}
deleteMobileAppById(tenantId, mobileApp.getId());
}
@Override
public void deleteMobileAppsByTenantId(TenantId tenantId) {
log.trace("Executing deleteDomainsByTenantId, tenantId [{}]", tenantId);
Validator.validateId(tenantId, id -> INCORRECT_TENANT_ID + id);
mobileAppDao.deleteByTenantId(tenantId);
}
@Override
public void deleteByTenantId(TenantId tenantId) {
deleteMobileAppsByTenantId(tenantId);
}
}

16
dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java

@ -429,11 +429,11 @@ public class ModelConstants {
public static final String DOMAIN_TABLE_NAME = "domain";
public static final String DOMAIN_DOMAIN_NAME_PROPERTY = "domain_name";
public static final String DOMAIN_OAUTH2_ENABLED_PROPERTY = "oauth2_enabled";
public static final String DOMAIN_PROPAGATE_TO_EDGE_PROPERTY = "propagate_to_edge";
public static final String DOMAIN_PROPAGATE_TO_EDGE_PROPERTY = "edge_enabled";
public static final String DOMAIN_OAUTH2_REGISTRATION_TABLE_NAME = "domain_oauth2_registration";
public static final String DOMAIN_OAUTH2_PROVIDER_PROVIDER_ID_PROPERTY = "oauth2_registration_id";
public static final String DOMAIN_OAUTH2_PROVIDER_DOMAIN_ID_PROPERTY = "domain_id";
public static final String DOMAIN_OAUTH2_CLIENT_TABLE_NAME = "domain_oauth2_client";
public static final String DOMAIN_OAUTH2_CLIENT_CLIENT_ID_PROPERTY = "oauth2_client_id";
public static final String DOMAIN_OAUTH2_CLIENT_DOMAIN_ID_PROPERTY = "domain_id";
/**
* Mobile application constants.
@ -443,15 +443,15 @@ public class ModelConstants {
public static final String MOBILE_APP_APP_SECRET_PROPERTY = "app_secret";
public static final String MOBILE_APP_OAUTH2_ENABLED_PROPERTY = "oauth2_enabled";
public static final String MOBILE_APP_OAUTH2_REGISTRATION_TABLE_NAME = "mobile_app_oauth2_registration";
public static final String MOBILE_APP_OAUTH2_REGISTRATION_REGISTRATION_ID_PROPERTY = "oauth2_registration_id";
public static final String MOBILE_APP_OAUTH2_REGISTRATION_MOBILE_APP_ID_PROPERTY = "mobile_app_id";
public static final String MOBILE_APP_OAUTH2_CLIENT_TABLE_NAME = "mobile_app_oauth2_client";
public static final String MOBILE_APP_OAUTH2_CLIENT_CLIENT_ID_PROPERTY = "oauth2_client_id";
public static final String MOBILE_APP_OAUTH2_CLIENT_MOBILE_APP_ID_PROPERTY = "mobile_app_id";
/**
* OAuth2 client registration constants.
*/
public static final String OAUTH2_REGISTRATION_TABLE_NAME = "oauth2_registration";
public static final String OAUTH2_CLIENT_TABLE_NAME = "oauth2_client";
public static final String OAUTH2_CLIENT_REGISTRATION_TEMPLATE_TABLE_NAME = "oauth2_client_registration_template";
public static final String OAUTH2_TEMPLATE_PROVIDER_ID_PROPERTY = "provider_id";
public static final String OAUTH2_CLIENT_TITLE_PROPERTY = "title";

4
dao/src/main/java/org/thingsboard/server/dao/model/sql/DomainOauth2RegistrationCompositeKey.java → dao/src/main/java/org/thingsboard/server/dao/model/sql/DomainOauth2ClientCompositeKey.java

@ -26,12 +26,12 @@ import java.util.UUID;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class DomainOauth2RegistrationCompositeKey implements Serializable {
public class DomainOauth2ClientCompositeKey implements Serializable {
@Transient
private static final long serialVersionUID = -245388185894468455L;
private UUID domainId;
private UUID oauth2RegistrationId;
private UUID oauth2ClientId;
}

34
dao/src/main/java/org/thingsboard/server/dao/model/sql/DomainOauth2RegistrationEntity.java → dao/src/main/java/org/thingsboard/server/dao/model/sql/DomainOauth2ClientEntity.java

@ -21,46 +21,46 @@ import jakarta.persistence.Id;
import jakarta.persistence.IdClass;
import jakarta.persistence.Table;
import lombok.Data;
import org.thingsboard.server.common.data.domain.DomainOauth2Registration;
import org.thingsboard.server.common.data.domain.DomainOauth2Client;
import org.thingsboard.server.common.data.id.DomainId;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.dao.model.ToData;
import java.util.UUID;
import static org.thingsboard.server.dao.model.ModelConstants.DOMAIN_OAUTH2_PROVIDER_DOMAIN_ID_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.DOMAIN_OAUTH2_REGISTRATION_TABLE_NAME;
import static org.thingsboard.server.dao.model.ModelConstants.DOMAIN_OAUTH2_CLIENT_DOMAIN_ID_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.DOMAIN_OAUTH2_CLIENT_TABLE_NAME;
@Data
@Entity
@Table(name = DOMAIN_OAUTH2_REGISTRATION_TABLE_NAME)
@IdClass(DomainOauth2RegistrationCompositeKey.class)
public final class DomainOauth2RegistrationEntity implements ToData<DomainOauth2Registration> {
@Table(name = DOMAIN_OAUTH2_CLIENT_TABLE_NAME)
@IdClass(DomainOauth2ClientCompositeKey.class)
public final class DomainOauth2ClientEntity implements ToData<DomainOauth2Client> {
@Id
@Column(name = DOMAIN_OAUTH2_PROVIDER_DOMAIN_ID_PROPERTY, columnDefinition = "uuid")
@Column(name = DOMAIN_OAUTH2_CLIENT_DOMAIN_ID_PROPERTY, columnDefinition = "uuid")
private UUID domainId;
@Id
@Column(name = ModelConstants.DOMAIN_OAUTH2_PROVIDER_PROVIDER_ID_PROPERTY, columnDefinition = "uuid")
private UUID oauth2RegistrationId;
@Column(name = ModelConstants.DOMAIN_OAUTH2_CLIENT_CLIENT_ID_PROPERTY, columnDefinition = "uuid")
private UUID oauth2ClientId;
public DomainOauth2RegistrationEntity() {
public DomainOauth2ClientEntity() {
super();
}
public DomainOauth2RegistrationEntity(DomainOauth2Registration domainOauth2Registration) {
domainId = domainOauth2Registration.getDomainId().getId();
oauth2RegistrationId = domainOauth2Registration.getOAuth2RegistrationId().getId();
public DomainOauth2ClientEntity(DomainOauth2Client domainOauth2Client) {
domainId = domainOauth2Client.getDomainId().getId();
oauth2ClientId = domainOauth2Client.getOAuth2ClientId().getId();
}
@Override
public DomainOauth2Registration toData() {
DomainOauth2Registration result = new DomainOauth2Registration();
public DomainOauth2Client toData() {
DomainOauth2Client result = new DomainOauth2Client();
result.setDomainId(new DomainId(domainId));
result.setOAuth2RegistrationId(new OAuth2RegistrationId(oauth2RegistrationId));
result.setOAuth2ClientId(new OAuth2ClientId(oauth2ClientId));
return result;
}
}

4
dao/src/main/java/org/thingsboard/server/dao/model/sql/MobileAppOauth2RegistrationCompositeKey.java → dao/src/main/java/org/thingsboard/server/dao/model/sql/MobileAppOauth2ClientCompositeKey.java

@ -26,12 +26,12 @@ import java.util.UUID;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class MobileAppOauth2RegistrationCompositeKey implements Serializable {
public class MobileAppOauth2ClientCompositeKey implements Serializable {
@Transient
private static final long serialVersionUID = -245388185894468455L;
private UUID mobileAppId;
private UUID oauth2RegistrationId;
private UUID oauth2ClientId;
}

36
dao/src/main/java/org/thingsboard/server/dao/model/sql/MobileAppOauth2RegistrationEntity.java → dao/src/main/java/org/thingsboard/server/dao/model/sql/MobileAppOauth2ClientEntity.java

@ -22,46 +22,44 @@ import jakarta.persistence.IdClass;
import jakarta.persistence.Table;
import lombok.Data;
import org.thingsboard.server.common.data.id.MobileAppId;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.mobile.MobileAppOauth2Registration;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import org.thingsboard.server.common.data.mobile.MobileAppOauth2Client;
import org.thingsboard.server.dao.model.ToData;
import java.util.UUID;
import static org.thingsboard.server.dao.model.ModelConstants.MOBILE_APP_OAUTH2_REGISTRATION_MOBILE_APP_ID_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.MOBILE_APP_OAUTH2_REGISTRATION_REGISTRATION_ID_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.MOBILE_APP_OAUTH2_REGISTRATION_TABLE_NAME;
import static org.thingsboard.server.dao.model.ModelConstants.MOBILE_APP_OAUTH2_CLIENT_MOBILE_APP_ID_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.MOBILE_APP_OAUTH2_CLIENT_CLIENT_ID_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.MOBILE_APP_OAUTH2_CLIENT_TABLE_NAME;
@Data
@Entity
@Table(name = MOBILE_APP_OAUTH2_REGISTRATION_TABLE_NAME)
@IdClass(MobileAppOauth2RegistrationCompositeKey.class)
public final class MobileAppOauth2RegistrationEntity implements ToData<MobileAppOauth2Registration> {
@Table(name = MOBILE_APP_OAUTH2_CLIENT_TABLE_NAME)
@IdClass(MobileAppOauth2ClientCompositeKey.class)
public final class MobileAppOauth2ClientEntity implements ToData<MobileAppOauth2Client> {
@Id
@Column(name = MOBILE_APP_OAUTH2_REGISTRATION_MOBILE_APP_ID_PROPERTY, columnDefinition = "uuid")
@Column(name = MOBILE_APP_OAUTH2_CLIENT_MOBILE_APP_ID_PROPERTY, columnDefinition = "uuid")
private UUID mobileAppId;
@Id
@Column(name = MOBILE_APP_OAUTH2_REGISTRATION_REGISTRATION_ID_PROPERTY, columnDefinition = "uuid")
private UUID oauth2RegistrationId;
@Column(name = MOBILE_APP_OAUTH2_CLIENT_CLIENT_ID_PROPERTY, columnDefinition = "uuid")
private UUID oauth2ClientId;
public MobileAppOauth2RegistrationEntity() {
public MobileAppOauth2ClientEntity() {
super();
}
public MobileAppOauth2RegistrationEntity(MobileAppOauth2Registration domainOauth2Provider) {
public MobileAppOauth2ClientEntity(MobileAppOauth2Client domainOauth2Provider) {
mobileAppId = domainOauth2Provider.getMobileAppId().getId();
oauth2RegistrationId = domainOauth2Provider.getOAuth2RegistrationId().getId();
oauth2ClientId = domainOauth2Provider.getOAuth2ClientId().getId();
}
@Override
public MobileAppOauth2Registration toData() {
MobileAppOauth2Registration result = new MobileAppOauth2Registration();
public MobileAppOauth2Client toData() {
MobileAppOauth2Client result = new MobileAppOauth2Client();
result.setMobileAppId(new MobileAppId(mobileAppId));
result.setOAuth2RegistrationId(new OAuth2RegistrationId(oauth2RegistrationId));
result.setOAuth2ClientId(new OAuth2ClientId(oauth2ClientId));
return result;
}
}

18
dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2RegistrationEntity.java → dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2ClientEntity.java

@ -25,13 +25,13 @@ import jakarta.persistence.Table;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.oauth2.MapperType;
import org.thingsboard.server.common.data.oauth2.OAuth2BasicMapperConfig;
import org.thingsboard.server.common.data.oauth2.OAuth2CustomMapperConfig;
import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig;
import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import org.thingsboard.server.common.data.oauth2.PlatformType;
import org.thingsboard.server.common.data.oauth2.TenantNameStrategyType;
import org.thingsboard.server.dao.model.BaseSqlEntity;
@ -46,8 +46,8 @@ import java.util.stream.Collectors;
@Data
@EqualsAndHashCode(callSuper = true)
@Entity
@Table(name = ModelConstants.OAUTH2_REGISTRATION_TABLE_NAME)
public class OAuth2RegistrationEntity extends BaseSqlEntity<OAuth2Registration> {
@Table(name = ModelConstants.OAUTH2_CLIENT_TABLE_NAME)
public class OAuth2ClientEntity extends BaseSqlEntity<OAuth2Client> {
@Column(name = ModelConstants.TENANT_ID_COLUMN)
private UUID tenantId;
@ -114,11 +114,11 @@ public class OAuth2RegistrationEntity extends BaseSqlEntity<OAuth2Registration>
@Column(name = ModelConstants.OAUTH2_ADDITIONAL_INFO_PROPERTY)
private JsonNode additionalInfo;
public OAuth2RegistrationEntity() {
public OAuth2ClientEntity() {
super();
}
public OAuth2RegistrationEntity(OAuth2Registration registration) {
public OAuth2ClientEntity(OAuth2Client registration) {
if (registration.getId() != null) {
this.setUuid(registration.getId().getId());
}
@ -167,9 +167,9 @@ public class OAuth2RegistrationEntity extends BaseSqlEntity<OAuth2Registration>
}
@Override
public OAuth2Registration toData() {
OAuth2Registration registration = new OAuth2Registration();
registration.setId(new OAuth2RegistrationId(id));
public OAuth2Client toData() {
OAuth2Client registration = new OAuth2Client();
registration.setId(new OAuth2ClientId(id));
registration.setCreatedTime(createdTime);
registration.setTenantId(new TenantId(tenantId));
registration.setTitle(title);

24
dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2RegistrationInfoEntity.java → dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2ClientInfoEntity.java

@ -19,8 +19,8 @@ import jakarta.persistence.Entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.oauth2.OAuth2RegistrationInfo;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo;
import org.thingsboard.server.common.data.oauth2.PlatformType;
import org.thingsboard.server.dao.model.BaseSqlEntity;
@ -32,16 +32,16 @@ import java.util.stream.Collectors;
@Data
@EqualsAndHashCode(callSuper = true)
@Entity
public class OAuth2RegistrationInfoEntity extends BaseSqlEntity<OAuth2RegistrationInfo> {
public class OAuth2ClientInfoEntity extends BaseSqlEntity<OAuth2ClientInfo> {
private String platforms;
private String title;
public OAuth2RegistrationInfoEntity() {
public OAuth2ClientInfoEntity() {
super();
}
public OAuth2RegistrationInfoEntity(UUID id, long createdTime, String platforms, String title) {
public OAuth2ClientInfoEntity(UUID id, long createdTime, String platforms, String title) {
this.id = id;
this.createdTime = createdTime;
this.platforms = platforms;
@ -49,13 +49,13 @@ public class OAuth2RegistrationInfoEntity extends BaseSqlEntity<OAuth2Registrati
}
@Override
public OAuth2RegistrationInfo toData() {
OAuth2RegistrationInfo oAuth2RegistrationInfo = new OAuth2RegistrationInfo();
oAuth2RegistrationInfo.setId(new OAuth2RegistrationId(id));
oAuth2RegistrationInfo.setCreatedTime(createdTime);
oAuth2RegistrationInfo.setTitle(title);
oAuth2RegistrationInfo.setPlatforms(StringUtils.isNotEmpty(platforms) ? Arrays.stream(platforms.split(","))
public OAuth2ClientInfo toData() {
OAuth2ClientInfo oAuth2ClientInfo = new OAuth2ClientInfo();
oAuth2ClientInfo.setId(new OAuth2ClientId(id));
oAuth2ClientInfo.setCreatedTime(createdTime);
oAuth2ClientInfo.setTitle(title);
oAuth2ClientInfo.setPlatforms(StringUtils.isNotEmpty(platforms) ? Arrays.stream(platforms.split(","))
.map(str -> PlatformType.valueOf(str)).collect(Collectors.toList()) : Collections.emptyList());
return oAuth2RegistrationInfo;
return oAuth2ClientInfo;
}
}

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

@ -21,9 +21,9 @@ import org.springframework.security.oauth2.client.registration.ClientRegistratio
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import java.util.UUID;
@ -36,12 +36,12 @@ public class HybridClientRegistrationRepository implements ClientRegistrationRep
@Override
public ClientRegistration findByRegistrationId(String registrationId) {
OAuth2Registration registration = oAuth2ClientService.findOAuth2ClientById(TenantId.SYS_TENANT_ID, new OAuth2RegistrationId(UUID.fromString(registrationId)));
OAuth2Client registration = oAuth2ClientService.findOAuth2ClientById(TenantId.SYS_TENANT_ID, new OAuth2ClientId(UUID.fromString(registrationId)));
return registration == null ?
null : toSpringClientRegistration(registration);
}
private ClientRegistration toSpringClientRegistration(OAuth2Registration registration){
private ClientRegistration toSpringClientRegistration(OAuth2Client registration){
String registrationId = registration.getUuidId().toString();
return ClientRegistration.withRegistrationId(registrationId)
.clientName(registration.getName())

19
dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2RegistrationDao.java → dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientDao.java

@ -15,28 +15,27 @@
*/
package org.thingsboard.server.dao.oauth2;
import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
import org.thingsboard.server.common.data.oauth2.OAuth2RegistrationInfo;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import org.thingsboard.server.common.data.oauth2.PlatformType;
import org.thingsboard.server.dao.Dao;
import java.util.List;
import java.util.UUID;
public interface OAuth2RegistrationDao extends Dao<OAuth2Registration> {
public interface OAuth2ClientDao extends Dao<OAuth2Client> {
List<OAuth2RegistrationInfo> findInfosByTenantId(UUID tenantId);
List<OAuth2Client> findByTenantId(UUID tenantId);
List<OAuth2Registration> findByTenantId(UUID tenantId);
List<OAuth2Client> findEnabledByDomainName(String domainName);
List<OAuth2Registration> findEnabledByDomainNameAndPlatformType(String domainName, PlatformType platformType);
List<OAuth2Client> findEnabledByPckNameAndPlatformType(String pkgName, PlatformType platformType);
List<OAuth2Registration> findEnabledByPckNameAndPlatformType(String pkgName, PlatformType platformType);
List<OAuth2Client> findByDomainId(UUID domainId);
List<OAuth2RegistrationInfo> findInfosByDomainId(UUID domainId);
List<OAuth2RegistrationInfo> findInfosByMobileAppId(UUID domainId);
List<OAuth2Client> findByMobileAppId(UUID domainId);
String findAppSecret(UUID id, String pkgName);
void deleteByTenantId(TenantId tenantId);
}

96
dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientServiceImpl.java

@ -22,16 +22,17 @@ import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.HasId;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientLoginInfo;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo;
import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
import org.thingsboard.server.common.data.oauth2.OAuth2RegistrationInfo;
import org.thingsboard.server.common.data.oauth2.PlatformType;
import org.thingsboard.server.dao.entity.AbstractEntityService;
import org.thingsboard.server.dao.eventsourcing.DeleteEntityEvent;
import org.thingsboard.server.dao.eventsourcing.SaveEntityEvent;
import org.thingsboard.server.dao.service.DataValidator;
import org.thingsboard.server.dao.service.Validator;
import java.util.List;
import java.util.Optional;
@ -42,7 +43,7 @@ import static org.thingsboard.server.dao.service.Validator.validateId;
import static org.thingsboard.server.dao.service.Validator.validateString;
@Slf4j
@Service
@Service("OAuth2ClientService")
public class OAuth2ClientServiceImpl extends AbstractEntityService implements OAuth2ClientService {
public static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
@ -50,56 +51,50 @@ public class OAuth2ClientServiceImpl extends AbstractEntityService implements OA
public static final String INCORRECT_DOMAIN_NAME = "Incorrect domainName ";
@Autowired
private OAuth2RegistrationDao oauth2RegistrationDao;
private OAuth2ClientDao oauth2ClientDao;
@Autowired
private DataValidator<OAuth2Registration> oAuth2RegistrationDataValidator;
private DataValidator<OAuth2Client> oAuth2ClientDataValidator;
@Override
public List<OAuth2ClientInfo> getWebOAuth2Clients(String domainName, PlatformType platformType) {
public List<OAuth2ClientLoginInfo> findOAuth2ClientLoginInfosByDomainName(String domainName) {
log.trace("Executing getOAuth2Clients [{}] ", domainName);
validateString(domainName, dn -> INCORRECT_DOMAIN_NAME + dn);
return oauth2RegistrationDao.findEnabledByDomainNameAndPlatformType(domainName, platformType)
return oauth2ClientDao.findEnabledByDomainName(domainName)
.stream()
.map(OAuth2Utils::toClientInfo)
.map(OAuth2Utils::toClientLoginInfo)
.collect(Collectors.toList());
}
@Override
public List<OAuth2ClientInfo> getMobileOAuth2Clients(String pkgName, PlatformType platformType) {
public List<OAuth2ClientLoginInfo> findOAuth2ClientLoginInfosByMobilePkgNameAndPlatformType(String pkgName, PlatformType platformType) {
log.trace("Executing getOAuth2Clients pkgName=[{}] platformType=[{}]",pkgName, platformType);
return oauth2RegistrationDao.findEnabledByPckNameAndPlatformType(pkgName, platformType)
return oauth2ClientDao.findEnabledByPckNameAndPlatformType(pkgName, platformType)
.stream()
.map(OAuth2Utils::toClientInfo)
.map(OAuth2Utils::toClientLoginInfo)
.collect(Collectors.toList());
}
@Override
@Transactional
public OAuth2Registration saveOAuth2Client(TenantId tenantId, OAuth2Registration oAuth2Registration) {
log.trace("Executing saveOAuth2Client [{}]", oAuth2Registration);
oAuth2RegistrationDataValidator.validate(oAuth2Registration, OAuth2Registration::getTenantId);
OAuth2Registration savedOauth2Registration = oauth2RegistrationDao.save(tenantId, oAuth2Registration);
eventPublisher.publishEvent(SaveEntityEvent.builder().tenantId(TenantId.SYS_TENANT_ID).entity(oAuth2Registration).build());
return savedOauth2Registration;
}
@Override
public OAuth2Registration findOAuth2ClientById(TenantId tenantId, OAuth2RegistrationId oAuth2RegistrationId) {
log.trace("Executing findOAuth2ClientById [{}]", oAuth2RegistrationId);
validateId(oAuth2RegistrationId, uuid -> INCORRECT_CLIENT_REGISTRATION_ID + uuid);
return oauth2RegistrationDao.findById(tenantId, oAuth2RegistrationId.getId());
public OAuth2Client saveOAuth2Client(TenantId tenantId, OAuth2Client oAuth2Client) {
log.trace("Executing saveOAuth2Client [{}]", oAuth2Client);
oAuth2ClientDataValidator.validate(oAuth2Client, OAuth2Client::getTenantId);
OAuth2Client savedOauth2Client = oauth2ClientDao.save(tenantId, oAuth2Client);
eventPublisher.publishEvent(SaveEntityEvent.builder().tenantId(TenantId.SYS_TENANT_ID).entity(oAuth2Client).build());
return savedOauth2Client;
}
@Override
public List<OAuth2RegistrationInfo> findOauth2ClientInfosByTenantId(TenantId tenantId) {
log.trace("Executing findOauth2ClientInfosByTenantId");
return oauth2RegistrationDao.findInfosByTenantId(tenantId.getId());
public OAuth2Client findOAuth2ClientById(TenantId tenantId, OAuth2ClientId oAuth2ClientId) {
log.trace("Executing findOAuth2ClientById [{}]", oAuth2ClientId);
validateId(oAuth2ClientId, uuid -> INCORRECT_CLIENT_REGISTRATION_ID + uuid);
return oauth2ClientDao.findById(tenantId, oAuth2ClientId.getId());
}
@Override
public List<OAuth2Registration> findOauth2ClientsByTenantId(TenantId tenantId) {
log.trace("Executing findOauth2ClientsByTenantId [{}]", tenantId);
return oauth2RegistrationDao.findByTenantId(tenantId.getId());
public List<OAuth2Client> findOAuth2ClientsByTenantId(TenantId tenantId) {
log.trace("Executing findOAuth2ClientsByTenantId [{}]", tenantId);
return oauth2ClientDao.findByTenantId(tenantId.getId());
}
@Override
@ -107,34 +102,55 @@ public class OAuth2ClientServiceImpl extends AbstractEntityService implements OA
log.trace("Executing findAppSecret [{}][{}]", id, pkgName);
validateId(id, uuid -> INCORRECT_CLIENT_REGISTRATION_ID + uuid);
validateString(pkgName, "Incorrect package name");
return oauth2RegistrationDao.findAppSecret(id, pkgName);
return oauth2ClientDao.findAppSecret(id, pkgName);
}
@Override
@Transactional
public void deleteById(TenantId tenantId, OAuth2RegistrationId oAuth2RegistrationId) {
log.trace("[{}][{}] Executing deleteById [{}]", tenantId, oAuth2RegistrationId);
oauth2RegistrationDao.removeById(tenantId, oAuth2RegistrationId.getId());
public void deleteOAuth2ClientById(TenantId tenantId, OAuth2ClientId oAuth2ClientId) {
log.trace("[{}][{}] Executing deleteOAuth2ClientById [{}]", tenantId, oAuth2ClientId);
oauth2ClientDao.removeById(tenantId, oAuth2ClientId.getId());
eventPublisher.publishEvent(DeleteEntityEvent.builder()
.tenantId(tenantId)
.entityId(oAuth2RegistrationId)
.entityId(oAuth2ClientId)
.build());
}
@Override
public void deleteOauth2ClientsByTenantId(TenantId tenantId) {
log.trace("Executing deleteOauth2ClientsByTenantId, tenantId [{}]", tenantId);
Validator.validateId(tenantId, id -> INCORRECT_TENANT_ID + id);
oauth2ClientDao.deleteByTenantId(tenantId);
}
@Override
public List<OAuth2ClientInfo> findOAuth2ClientInfosByTenantId(TenantId tenantId) {
log.trace("Executing findOAuth2ClientInfosByTenantId tenantId=[{}]", tenantId);
return oauth2ClientDao.findByTenantId(tenantId.getId())
.stream()
.map(OAuth2Utils::toClientInfo)
.collect(Collectors.toList());
}
@Override
public void deleteByTenantId(TenantId tenantId) {
deleteOauth2ClientsByTenantId(tenantId);
}
@Override
public Optional<HasId<?>> findEntity(TenantId tenantId, EntityId entityId) {
return Optional.ofNullable(findOAuth2ClientById(tenantId, new OAuth2RegistrationId(entityId.getId())));
return Optional.ofNullable(findOAuth2ClientById(tenantId, new OAuth2ClientId(entityId.getId())));
}
@Override
@Transactional
public void deleteEntity(TenantId tenantId, EntityId id, boolean force) {
OAuth2Registration oAuth2Registration = oauth2RegistrationDao.findById(tenantId, id.getId());
if (oAuth2Registration == null) {
OAuth2Client oAuth2Client = oauth2ClientDao.findById(tenantId, id.getId());
if (oAuth2Client == null) {
return;
}
deleteById(tenantId, oAuth2Registration.getId());
deleteOAuth2ClientById(tenantId, oAuth2Client.getId());
}
@Override

16
dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2Utils.java

@ -16,17 +16,27 @@
package org.thingsboard.server.dao.oauth2;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo;
import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientLoginInfo;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
public class OAuth2Utils {
public static final String OAUTH2_AUTHORIZATION_PATH_TEMPLATE = "/oauth2/authorization/%s";
public static OAuth2ClientInfo toClientInfo(OAuth2Registration registration) {
OAuth2ClientInfo client = new OAuth2ClientInfo();
public static OAuth2ClientLoginInfo toClientLoginInfo(OAuth2Client registration) {
OAuth2ClientLoginInfo client = new OAuth2ClientLoginInfo();
client.setName(registration.getLoginButtonLabel());
client.setUrl(String.format(OAUTH2_AUTHORIZATION_PATH_TEMPLATE, registration.getUuidId().toString()));
client.setIcon(registration.getLoginButtonIcon());
return client;
}
public static OAuth2ClientInfo toClientInfo(OAuth2Client oAuth2Client) {
OAuth2ClientInfo client = new OAuth2ClientInfo();
client.setId(oAuth2Client.getId());
client.setCreatedTime(oAuth2Client.getCreatedTime());
client.setTitle(oAuth2Client.getTitle());
client.setPlatforms(oAuth2Client.getPlatforms());
return client;
}
}

1
dao/src/main/java/org/thingsboard/server/dao/service/validator/MobileAppDataValidator.java

@ -18,7 +18,6 @@ package org.thingsboard.server.dao.service.validator;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.domain.Domain;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.mobile.MobileApp;
import org.thingsboard.server.dao.exception.DataValidationException;

42
dao/src/main/java/org/thingsboard/server/dao/service/validator/Oauth2RegistrationDataValidator.java → dao/src/main/java/org/thingsboard/server/dao/service/validator/Oauth2ClientDataValidator.java

@ -16,7 +16,6 @@
package org.thingsboard.server.dao.service.validator;
import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.id.TenantId;
@ -24,51 +23,18 @@ import org.thingsboard.server.common.data.oauth2.MapperType;
import org.thingsboard.server.common.data.oauth2.OAuth2BasicMapperConfig;
import org.thingsboard.server.common.data.oauth2.OAuth2CustomMapperConfig;
import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig;
import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import org.thingsboard.server.common.data.oauth2.TenantNameStrategyType;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.service.DataValidator;
@Component
@AllArgsConstructor
public class Oauth2RegistrationDataValidator extends DataValidator<OAuth2Registration> {
public class Oauth2ClientDataValidator extends DataValidator<OAuth2Client> {
@Override
protected void validateDataImpl(TenantId tenantId, OAuth2Registration oAuth2Registration) {
if (StringUtils.isEmpty(oAuth2Registration.getClientId())) {
throw new DataValidationException("Client ID should be specified!");
}
if (StringUtils.isEmpty(oAuth2Registration.getClientId())) {
throw new DataValidationException("Client ID should be specified!");
}
if (StringUtils.isEmpty(oAuth2Registration.getClientSecret())) {
throw new DataValidationException("Client secret should be specified!");
}
if (StringUtils.isEmpty(oAuth2Registration.getAuthorizationUri())) {
throw new DataValidationException("Authorization uri should be specified!");
}
if (StringUtils.isEmpty(oAuth2Registration.getAccessTokenUri())) {
throw new DataValidationException("Token uri should be specified!");
}
if (CollectionUtils.isEmpty(oAuth2Registration.getScope())) {
throw new DataValidationException("Scope should be specified!");
}
if (StringUtils.isEmpty(oAuth2Registration.getUserNameAttributeName())) {
throw new DataValidationException("User name attribute name should be specified!");
}
if (StringUtils.isEmpty(oAuth2Registration.getClientAuthenticationMethod())) {
throw new DataValidationException("Client authentication method should be specified!");
}
if (StringUtils.isEmpty(oAuth2Registration.getLoginButtonLabel())) {
throw new DataValidationException("Login button label should be specified!");
}
OAuth2MapperConfig mapperConfig = oAuth2Registration.getMapperConfig();
if (mapperConfig == null) {
throw new DataValidationException("Mapper config should be specified!");
}
if (mapperConfig.getType() == null) {
throw new DataValidationException("Mapper config type should be specified!");
}
protected void validateDataImpl(TenantId tenantId, OAuth2Client oAuth2Client) {
OAuth2MapperConfig mapperConfig = oAuth2Client.getMapperConfig();
if (mapperConfig.getType() == MapperType.BASIC) {
OAuth2BasicMapperConfig basicConfig = mapperConfig.getBasic();
if (basicConfig == null) {

12
dao/src/main/java/org/thingsboard/server/dao/sql/domain/DomainOauth2RegistrationRepository.java → dao/src/main/java/org/thingsboard/server/dao/sql/domain/DomainOauth2ClientRepository.java

@ -16,19 +16,15 @@
package org.thingsboard.server.dao.sql.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;
import org.thingsboard.server.dao.model.sql.DomainOauth2RegistrationCompositeKey;
import org.thingsboard.server.dao.model.sql.DomainOauth2RegistrationEntity;
import org.thingsboard.server.dao.model.sql.OAuth2RegistrationEntity;
import org.thingsboard.server.dao.model.sql.DomainOauth2ClientCompositeKey;
import org.thingsboard.server.dao.model.sql.DomainOauth2ClientEntity;
import java.util.List;
import java.util.UUID;
public interface DomainOauth2RegistrationRepository extends JpaRepository<DomainOauth2RegistrationEntity, DomainOauth2RegistrationCompositeKey> {
public interface DomainOauth2ClientRepository extends JpaRepository<DomainOauth2ClientEntity, DomainOauth2ClientCompositeKey> {
List<DomainOauth2RegistrationEntity> findAllByDomainId(@Param("domainId") UUID domainId);
List<DomainOauth2ClientEntity> findAllByDomainId(@Param("domainId") UUID domainId);
}

2
dao/src/main/java/org/thingsboard/server/dao/sql/domain/DomainRepository.java

@ -31,7 +31,7 @@ public interface DomainRepository extends JpaRepository<DomainEntity, UUID> {
@Transactional
@Modifying
@Query("DELETE FROM MobileAppEntity r WHERE r.tenantId = :tenantId")
@Query("DELETE FROM DomainEntity r WHERE r.tenantId = :tenantId")
void deleteByTenantId(@Param("tenantId") UUID tenantId);
int countByTenantIdAndOauth2Enabled(@Param("tenantId") UUID tenantId, @Param("oauth2Enabled") boolean oauth2Enabled);

29
dao/src/main/java/org/thingsboard/server/dao/sql/domain/JpaDomainDao.java

@ -19,20 +19,18 @@ import lombok.RequiredArgsConstructor;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.domain.Domain;
import org.thingsboard.server.common.data.domain.DomainOauth2Registration;
import org.thingsboard.server.common.data.domain.DomainOauth2Client;
import org.thingsboard.server.common.data.id.DomainId;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.domain.DomainDao;
import org.thingsboard.server.dao.model.sql.DomainEntity;
import org.thingsboard.server.dao.model.sql.DomainOauth2RegistrationCompositeKey;
import org.thingsboard.server.dao.model.sql.DomainOauth2RegistrationEntity;
import org.thingsboard.server.dao.model.sql.WidgetsBundleWidgetEntity;
import org.thingsboard.server.dao.model.sql.DomainOauth2ClientCompositeKey;
import org.thingsboard.server.dao.model.sql.DomainOauth2ClientEntity;
import org.thingsboard.server.dao.sql.JpaAbstractDao;
import org.thingsboard.server.dao.util.SqlDao;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@ -42,7 +40,7 @@ import java.util.UUID;
public class JpaDomainDao extends JpaAbstractDao<DomainEntity, Domain> implements DomainDao {
private final DomainRepository domainRepository;
private final DomainOauth2RegistrationRepository domainOauth2RegistrationRepository;
private final DomainOauth2ClientRepository domainOauth2ClientRepository;
@Override
protected Class<DomainEntity> getEntityClass() {
@ -65,18 +63,23 @@ public class JpaDomainDao extends JpaAbstractDao<DomainEntity, Domain> implement
}
@Override
public List<DomainOauth2Registration> findOauth2ClientsByDomainId(TenantId tenantId, DomainId domainId) {
return DaoUtil.convertDataList(domainOauth2RegistrationRepository.findAllByDomainId(domainId.getId()));
public List<DomainOauth2Client> findOauth2ClientsByDomainId(TenantId tenantId, DomainId domainId) {
return DaoUtil.convertDataList(domainOauth2ClientRepository.findAllByDomainId(domainId.getId()));
}
@Override
public void saveOauth2Clients(DomainOauth2Registration domainOauth2Registration) {
domainOauth2RegistrationRepository.save(new DomainOauth2RegistrationEntity(domainOauth2Registration));
public void saveOauth2Clients(DomainOauth2Client domainOauth2Client) {
domainOauth2ClientRepository.save(new DomainOauth2ClientEntity(domainOauth2Client));
}
@Override
public void removeOauth2Clients(DomainId domainId, OAuth2RegistrationId oAuth2RegistrationId) {
domainOauth2RegistrationRepository.deleteById(new DomainOauth2RegistrationCompositeKey(domainId.getId(), oAuth2RegistrationId.getId()));
public void removeOauth2Clients(DomainId domainId, OAuth2ClientId oAuth2ClientId) {
domainOauth2ClientRepository.deleteById(new DomainOauth2ClientCompositeKey(domainId.getId(), oAuth2ClientId.getId()));
}
@Override
public void deleteByTenantId(TenantId tenantId) {
domainRepository.deleteByTenantId(tenantId.getId());
}
}

24
dao/src/main/java/org/thingsboard/server/dao/sql/mobile/JpaMobileAppDao.java

@ -19,15 +19,15 @@ import lombok.RequiredArgsConstructor;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.id.MobileAppId;
import org.thingsboard.server.common.data.id.OAuth2RegistrationId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.mobile.MobileApp;
import org.thingsboard.server.common.data.mobile.MobileAppOauth2Registration;
import org.thingsboard.server.common.data.mobile.MobileAppOauth2Client;
import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.mobile.MobileAppDao;
import org.thingsboard.server.dao.model.sql.MobileAppEntity;
import org.thingsboard.server.dao.model.sql.MobileAppOauth2RegistrationCompositeKey;
import org.thingsboard.server.dao.model.sql.MobileAppOauth2RegistrationEntity;
import org.thingsboard.server.dao.model.sql.MobileAppOauth2ClientCompositeKey;
import org.thingsboard.server.dao.model.sql.MobileAppOauth2ClientEntity;
import org.thingsboard.server.dao.sql.JpaAbstractDao;
import org.thingsboard.server.dao.util.SqlDao;
@ -40,7 +40,7 @@ import java.util.UUID;
public class JpaMobileAppDao extends JpaAbstractDao<MobileAppEntity, MobileApp> implements MobileAppDao {
private final MobileAppRepository repository;
private final MobileAppOauth2RegistrationRepository mobileOauth2ProviderRepository;
private final MobileAppOauth2ClientRepository mobileOauth2ProviderRepository;
@Override
protected Class<MobileAppEntity> getEntityClass() {
@ -58,19 +58,23 @@ public class JpaMobileAppDao extends JpaAbstractDao<MobileAppEntity, MobileApp>
}
@Override
public List<MobileAppOauth2Registration> findOauth2ClientsByMobileAppId(TenantId tenantId, MobileAppId mobileAppId) {
public List<MobileAppOauth2Client> findOauth2ClientsByMobileAppId(TenantId tenantId, MobileAppId mobileAppId) {
return DaoUtil.convertDataList(mobileOauth2ProviderRepository.findAllByMobileAppId(mobileAppId.getId()));
}
@Override
public void saveOauth2Clients(MobileAppOauth2Registration mobileAppOauth2Registration) {
mobileOauth2ProviderRepository.save(new MobileAppOauth2RegistrationEntity(mobileAppOauth2Registration));
public void saveOauth2Clients(MobileAppOauth2Client mobileAppOauth2Client) {
mobileOauth2ProviderRepository.save(new MobileAppOauth2ClientEntity(mobileAppOauth2Client));
}
@Override
public void removeOauth2Clients(MobileAppId mobileAppId, OAuth2RegistrationId oAuth2RegistrationId) {
mobileOauth2ProviderRepository.deleteById(new MobileAppOauth2RegistrationCompositeKey(mobileAppId.getId(), oAuth2RegistrationId.getId()));
public void removeOauth2Clients(MobileAppId mobileAppId, OAuth2ClientId oAuth2ClientId) {
mobileOauth2ProviderRepository.deleteById(new MobileAppOauth2ClientCompositeKey(mobileAppId.getId(), oAuth2ClientId.getId()));
}
@Override
public void deleteByTenantId(TenantId tenantId) {
repository.deleteByTenantId(tenantId.getId());
}
}

10
dao/src/main/java/org/thingsboard/server/dao/sql/mobile/MobileAppOauth2RegistrationRepository.java → dao/src/main/java/org/thingsboard/server/dao/sql/mobile/MobileAppOauth2ClientRepository.java

@ -17,16 +17,14 @@ package org.thingsboard.server.dao.sql.mobile;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.query.Param;
import org.thingsboard.server.common.data.mobile.MobileAppOauth2Registration;
import org.thingsboard.server.dao.model.sql.DomainOauth2RegistrationEntity;
import org.thingsboard.server.dao.model.sql.MobileAppOauth2RegistrationCompositeKey;
import org.thingsboard.server.dao.model.sql.MobileAppOauth2RegistrationEntity;
import org.thingsboard.server.dao.model.sql.MobileAppOauth2ClientCompositeKey;
import org.thingsboard.server.dao.model.sql.MobileAppOauth2ClientEntity;
import java.util.List;
import java.util.UUID;
public interface MobileAppOauth2RegistrationRepository extends JpaRepository<MobileAppOauth2RegistrationEntity, MobileAppOauth2RegistrationCompositeKey> {
public interface MobileAppOauth2ClientRepository extends JpaRepository<MobileAppOauth2ClientEntity, MobileAppOauth2ClientCompositeKey> {
List<MobileAppOauth2RegistrationEntity> findAllByMobileAppId(@Param("mobileAppId") UUID mobileAppId);
List<MobileAppOauth2ClientEntity> findAllByMobileAppId(@Param("mobileAppId") UUID mobileAppId);
}

45
dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2RegistrationDao.java → dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ClientDao.java

@ -18,12 +18,12 @@ package org.thingsboard.server.dao.sql.oauth2;
import lombok.RequiredArgsConstructor;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
import org.thingsboard.server.common.data.oauth2.OAuth2RegistrationInfo;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import org.thingsboard.server.common.data.oauth2.PlatformType;
import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.model.sql.OAuth2RegistrationEntity;
import org.thingsboard.server.dao.oauth2.OAuth2RegistrationDao;
import org.thingsboard.server.dao.model.sql.OAuth2ClientEntity;
import org.thingsboard.server.dao.oauth2.OAuth2ClientDao;
import org.thingsboard.server.dao.sql.JpaAbstractDao;
import org.thingsboard.server.dao.util.SqlDao;
@ -33,50 +33,44 @@ import java.util.UUID;
@Component
@RequiredArgsConstructor
@SqlDao
public class JpaOAuth2RegistrationDao extends JpaAbstractDao<OAuth2RegistrationEntity, OAuth2Registration> implements OAuth2RegistrationDao {
public class JpaOAuth2ClientDao extends JpaAbstractDao<OAuth2ClientEntity, OAuth2Client> implements OAuth2ClientDao {
private final OAuth2RegistrationRepository repository;
private final OAuth2ClientRepository repository;
@Override
protected Class<OAuth2RegistrationEntity> getEntityClass() {
return OAuth2RegistrationEntity.class;
protected Class<OAuth2ClientEntity> getEntityClass() {
return OAuth2ClientEntity.class;
}
@Override
protected JpaRepository<OAuth2RegistrationEntity, UUID> getRepository() {
protected JpaRepository<OAuth2ClientEntity, UUID> getRepository() {
return repository;
}
@Override
public List<OAuth2RegistrationInfo> findInfosByTenantId(UUID tenantId) {
return DaoUtil.convertDataList(repository.findInfosByTenantId(tenantId));
}
@Override
public List<OAuth2Registration> findByTenantId(UUID tenantId) {
public List<OAuth2Client> findByTenantId(UUID tenantId) {
return DaoUtil.convertDataList(repository.findByTenantId(tenantId));
}
@Override
public List<OAuth2Registration> findEnabledByDomainNameAndPlatformType(String domainName, PlatformType platformType) {
return DaoUtil.convertDataList(repository.findEnabledByDomainNameAndPlatformType(domainName,
platformType != null ? "%" + platformType.name() + "%" : null));
public List<OAuth2Client> findEnabledByDomainName(String domainName) {
return DaoUtil.convertDataList(repository.findEnabledByDomainNameAndPlatformType(domainName, PlatformType.WEB.name()));
}
@Override
public List<OAuth2Registration> findEnabledByPckNameAndPlatformType(String pkgName, PlatformType platformType) {
public List<OAuth2Client> findEnabledByPckNameAndPlatformType(String pkgName, PlatformType platformType) {
return DaoUtil.convertDataList(repository.findEnabledByPkgNameAndPlatformType(pkgName,
platformType != null ? "%" + platformType.name() + "%" : null));
}
@Override
public List<OAuth2RegistrationInfo> findInfosByDomainId(UUID oauth2ParamsId) {
return DaoUtil.convertDataList(repository.findInfosByDomainId(oauth2ParamsId));
public List<OAuth2Client> findByDomainId(UUID oauth2ParamsId) {
return DaoUtil.convertDataList(repository.findByDomainId(oauth2ParamsId));
}
@Override
public List<OAuth2RegistrationInfo> findInfosByMobileAppId(UUID mobileAppId) {
return DaoUtil.convertDataList(repository.findInfosByMobileAppId(mobileAppId));
public List<OAuth2Client> findByMobileAppId(UUID mobileAppId) {
return DaoUtil.convertDataList(repository.findByMobileAppId(mobileAppId));
}
@Override
@ -84,4 +78,9 @@ public class JpaOAuth2RegistrationDao extends JpaAbstractDao<OAuth2RegistrationE
return repository.findAppSecret(id, pkgName);
}
@Override
public void deleteByTenantId(TenantId tenantId) {
repository.deleteByTenantId(tenantId.getId());
}
}

76
dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2ClientRepository.java

@ -0,0 +1,76 @@
/**
* Copyright © 2016-2024 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.dao.sql.oauth2;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;
import org.thingsboard.server.dao.model.sql.OAuth2ClientEntity;
import java.util.List;
import java.util.UUID;
public interface OAuth2ClientRepository extends JpaRepository<OAuth2ClientEntity, UUID> {
List<OAuth2ClientEntity> findByTenantId(@Param("tenantId") UUID tenantId);
@Query("SELECT c " +
"FROM OAuth2ClientEntity c " +
"LEFT JOIN DomainOauth2ClientEntity dc on c.id = dc.oauth2ClientId " +
"LEFT JOIN DomainEntity domain on dc.domainId = domain.id " +
"AND domain.name = :domainName " +
"AND (:platformFilter IS NULL OR c.platforms IS NULL OR c.platforms = '' OR c.platforms LIKE :platformFilter)")
List<OAuth2ClientEntity> findEnabledByDomainNameAndPlatformType(@Param("domainName") String domainName,
@Param("platformFilter") String platformFilter);
@Query("SELECT c " +
"FROM OAuth2ClientEntity c " +
"LEFT JOIN MobileAppOauth2ClientEntity mc on c.id = mc.oauth2ClientId " +
"LEFT JOIN MobileAppEntity app on mc.mobileAppId = app.id " +
"AND app.pkgName = :pkgName " +
"AND (:platformFilter IS NULL OR c.platforms IS NULL OR c.platforms = '' OR c.platforms LIKE :platformFilter)")
List<OAuth2ClientEntity> findEnabledByPkgNameAndPlatformType(@Param("pkgName") String pkgName,
@Param("platformFilter") String platformFilter);
@Query("SELECT c " +
"FROM OAuth2ClientEntity c " +
"LEFT JOIN DomainOauth2ClientEntity dc on dc.oauth2ClientId = c.id " +
"WHERE dc.domainId = :domainId ")
List<OAuth2ClientEntity> findByDomainId(UUID domainId);
@Query("SELECT c " +
"FROM OAuth2ClientEntity c " +
"LEFT JOIN MobileAppOauth2ClientEntity mc on mc.oauth2ClientId = c.id " +
"WHERE mc.mobileAppId = :mobileAppId ")
List<OAuth2ClientEntity> findByMobileAppId(UUID mobileAppId);
@Query("SELECT m.appSecret " +
"FROM MobileAppEntity m " +
"LEFT JOIN MobileAppOauth2ClientEntity mp on m.id = mp.mobileAppId " +
"LEFT JOIN OAuth2ClientEntity p on mp.oauth2ClientId = p.id " +
"WHERE p.id = :clientId " +
"AND m.pkgName = :pkgName")
String findAppSecret(@Param("clientId") UUID id,
@Param("pkgName") String pkgName);
@Transactional
@Modifying
@Query("DELETE FROM OAuth2ClientEntity t WHERE t.tenantId = :tenantId")
void deleteByTenantId(@Param("tenantId") UUID tenantId);
}

76
dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2RegistrationRepository.java

@ -1,76 +0,0 @@
/**
* Copyright © 2016-2024 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.dao.sql.oauth2;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.thingsboard.server.dao.model.sql.OAuth2RegistrationEntity;
import org.thingsboard.server.dao.model.sql.OAuth2RegistrationInfoEntity;
import java.util.List;
import java.util.UUID;
public interface OAuth2RegistrationRepository extends JpaRepository<OAuth2RegistrationEntity, UUID> {
List<OAuth2RegistrationEntity> findByTenantId(@Param("tenantId") UUID tenantId);
@Query("SELECT new org.thingsboard.server.dao.model.sql.OAuth2RegistrationInfoEntity(r.id, r.createdTime, r.platforms, r.title) " +
"FROM OAuth2RegistrationEntity r " +
"WHERE r.tenantId = :tenantId")
List<OAuth2RegistrationInfoEntity> findInfosByTenantId(@Param("tenantId") UUID tenantId);
@Query(value = "SELECT r " +
"FROM oauth2_registration r " +
"LEFT JOIN domain_oauth2_registration dr on dr.oauth2_registration_id = r.id " +
"LEFT JOIN domain d on dr.domain_id = d.id " +
"WHERE d.oauth2_enabled = true " +
"AND d.domain_name = :domainName " +
"AND (:platformFilter IS NULL OR r.platforms IS NULL OR r.platforms = '' OR r.platforms LIKE :platformFilter)", nativeQuery = true)
List<OAuth2RegistrationEntity> findEnabledByDomainNameAndPlatformType(@Param("domainName") String domainName,
@Param("platformFilter") String platformFilter);
@Query(value = "SELECT r " +
"FROM oauth2_registration r " +
"LEFT JOIN mobile_app_oauth2_registration mr on mr.oauth2_registration_id = r.id " +
"LEFT JOIN mobile_app m on mr.mobile_app_id = m.id " +
"WHERE m.oauth2_enabled = true " +
"AND m.pck_name = :pkgName " +
"AND (:platformFilter IS NULL OR r.platforms IS NULL OR r.platforms = '' OR r.platforms LIKE :platformFilter)", nativeQuery = true)
List<OAuth2RegistrationEntity> findEnabledByPkgNameAndPlatformType(@Param("pkgName") String pkgName,
@Param("platformFilter") String platformFilter);
@Query("SELECT new org.thingsboard.server.dao.model.sql.OAuth2RegistrationInfoEntity(r.id, r.createdTime, r.platforms, r.title) " +
"FROM OAuth2RegistrationEntity r " +
"LEFT JOIN DomainOauth2RegistrationEntity dr on dr.oauth2RegistrationId = r.id " +
"WHERE dr.domainId = :domainId ")
List<OAuth2RegistrationInfoEntity> findInfosByDomainId(UUID domainId);
@Query("SELECT new org.thingsboard.server.dao.model.sql.OAuth2RegistrationInfoEntity(r.id, r.createdTime, r.platforms, r.title) " +
"FROM OAuth2RegistrationEntity r " +
"LEFT JOIN MobileAppOauth2RegistrationEntity mr on mr.oauth2RegistrationId = r.id " +
"WHERE mr.mobileAppId = :mobileAppId ")
List<OAuth2RegistrationInfoEntity> findInfosByMobileAppId(UUID mobileAppId);
@Query("SELECT m.appSecret " +
"FROM MobileAppEntity m " +
"LEFT JOIN MobileAppOauth2RegistrationEntity mp on m.id = mp.mobileAppId " +
"LEFT JOIN OAuth2RegistrationEntity p on mp.oauth2RegistrationId = p.id " +
"WHERE p.id = :registrationId " +
"AND m.pkgName = :pkgName")
String findAppSecret(@Param("registrationId") UUID id,
@Param("pkgName") String pkgName);
}

17
dao/src/main/resources/sql/schema-entities.sql

@ -558,9 +558,10 @@ CREATE TABLE IF NOT EXISTS key_dictionary
CONSTRAINT key_dictionary_id_pkey PRIMARY KEY (key)
);
CREATE TABLE IF NOT EXISTS oauth2_registration (
id uuid NOT NULL CONSTRAINT oauth2_registration_pkey PRIMARY KEY,
CREATE TABLE IF NOT EXISTS oauth2_client (
id uuid NOT NULL CONSTRAINT oauth2_client_pkey PRIMARY KEY,
tenant_id uuid NOT NULL,
title varchar(100) NOT NULL,
created_time bigint NOT NULL,
additional_info varchar,
client_id varchar(255),
@ -612,18 +613,18 @@ CREATE TABLE IF NOT EXISTS mobile_app (
CONSTRAINT mobile_app_unq_key UNIQUE (pkg_name)
);
CREATE TABLE IF NOT EXISTS domain_oauth2_registration (
CREATE TABLE IF NOT EXISTS domain_oauth2_client (
domain_id uuid NOT NULL,
oauth2_registration_id uuid NOT NULL,
oauth2_client_id uuid NOT NULL,
CONSTRAINT fk_domain FOREIGN KEY (domain_id) REFERENCES domain(id) ON DELETE CASCADE,
CONSTRAINT fk_oauth2_registration FOREIGN KEY (oauth2_registration_id) REFERENCES oauth2_registration(id) ON DELETE CASCADE
CONSTRAINT fk_oauth2_client FOREIGN KEY (oauth2_client_id) REFERENCES oauth2_client(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS mobile_app_oauth2_registration (
CREATE TABLE IF NOT EXISTS mobile_app_oauth2_client (
mobile_app_id uuid NOT NULL,
oauth2_registration_id uuid NOT NULL,
oauth2_client_id uuid NOT NULL,
CONSTRAINT fk_domain FOREIGN KEY (mobile_app_id) REFERENCES mobile_app(id) ON DELETE CASCADE,
CONSTRAINT fk_oauth2_registration FOREIGN KEY (oauth2_registration_id) REFERENCES oauth2_registration(id) ON DELETE CASCADE
CONSTRAINT fk_oauth2_client FOREIGN KEY (oauth2_client_id) REFERENCES oauth2_client(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS oauth2_client_registration_template (

43
dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java

@ -48,6 +48,11 @@ import org.thingsboard.server.common.data.id.DeviceProfileId;
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.oauth2.MapperType;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import org.thingsboard.server.common.data.oauth2.OAuth2CustomMapperConfig;
import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig;
import org.thingsboard.server.common.data.oauth2.PlatformType;
import org.thingsboard.server.common.data.ota.ChecksumAlgorithm;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.dao.audit.AuditLogLevelFilter;
@ -61,8 +66,11 @@ import org.thingsboard.server.dao.tenant.TenantService;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
@ -211,4 +219,39 @@ public abstract class AbstractServiceTest {
return firmware;
}
protected OAuth2Client validClientInfo(TenantId tenantId, String title) {
return validClientInfo(tenantId, title, null);
}
protected OAuth2Client validClientInfo(TenantId tenantId, String title, List<PlatformType> platforms) {
OAuth2Client oAuth2Client = new OAuth2Client();
oAuth2Client.setTenantId(tenantId);
oAuth2Client.setTitle(title);
oAuth2Client.setClientId(UUID.randomUUID().toString());
oAuth2Client.setClientSecret(UUID.randomUUID().toString());
oAuth2Client.setAuthorizationUri(UUID.randomUUID().toString());
oAuth2Client.setAccessTokenUri(UUID.randomUUID().toString());
oAuth2Client.setScope(Arrays.asList(UUID.randomUUID().toString(), UUID.randomUUID().toString()));
oAuth2Client.setPlatforms(platforms == null ? Collections.emptyList() : platforms);
oAuth2Client.setUserInfoUri(UUID.randomUUID().toString());
oAuth2Client.setUserNameAttributeName(UUID.randomUUID().toString());
oAuth2Client.setJwkSetUri(UUID.randomUUID().toString());
oAuth2Client.setClientAuthenticationMethod(UUID.randomUUID().toString());
oAuth2Client.setLoginButtonLabel(UUID.randomUUID().toString());
oAuth2Client.setLoginButtonIcon(UUID.randomUUID().toString());
oAuth2Client.setAdditionalInfo(JacksonUtil.newObjectNode().put(UUID.randomUUID().toString(), UUID.randomUUID().toString()));
oAuth2Client.setMapperConfig(
OAuth2MapperConfig.builder()
.allowUserCreation(true)
.activateUser(true)
.type(MapperType.CUSTOM)
.custom(
OAuth2CustomMapperConfig.builder()
.url(UUID.randomUUID().toString())
.build()
)
.build());
return oAuth2Client;
}
}

131
dao/src/test/java/org/thingsboard/server/dao/service/DomainServiceTest.java

@ -0,0 +1,131 @@
/**
* Copyright © 2016-2024 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.dao.service;
import org.junit.After;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.domain.Domain;
import org.thingsboard.server.common.data.domain.DomainInfo;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientLoginInfo;
import org.thingsboard.server.dao.domain.DomainService;
import org.thingsboard.server.dao.oauth2.OAuth2ClientService;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.thingsboard.server.dao.oauth2.OAuth2Utils.OAUTH2_AUTHORIZATION_PATH_TEMPLATE;
@DaoSqlTest
public class DomainServiceTest extends AbstractServiceTest {
@Autowired
protected DomainService domainService;
@Autowired
protected OAuth2ClientService oAuth2ClientService;
@After
public void after() {
domainService.deleteByTenantId(TenantId.SYS_TENANT_ID);
}
@Test
public void testSaveDomain() {
Domain domain = validDomain(TenantId.SYS_TENANT_ID, "test.domain.com", true, true);
Domain savedDomain = domainService.saveDomain(SYSTEM_TENANT_ID, domain);
Domain retrievedDomain = domainService.findDomainById(savedDomain.getTenantId(), savedDomain.getId());
assertThat(retrievedDomain).isEqualTo(savedDomain);
// update domain name
savedDomain.setName("test.domain2.com");
Domain updatedDomain = domainService.saveDomain(SYSTEM_TENANT_ID, savedDomain);
Domain retrievedDomain2 = domainService.findDomainById(savedDomain.getTenantId(), savedDomain.getId());
assertThat(retrievedDomain2).isEqualTo(updatedDomain);
// check domain info
DomainInfo retrievedInfo = domainService.findDomainInfoById(SYSTEM_TENANT_ID, savedDomain.getId());
assertThat(retrievedInfo).isEqualTo(new DomainInfo(updatedDomain, Collections.emptyList()));
boolean oauth2Enabled = domainService.isOauth2Enabled(SYSTEM_TENANT_ID);
assertThat(oauth2Enabled).isTrue();
// update domain oauth2 enabled to false
updatedDomain.setOauth2Enabled(false);
domainService.saveDomain(SYSTEM_TENANT_ID, updatedDomain);
boolean oauth2Enabled2 = domainService.isOauth2Enabled(SYSTEM_TENANT_ID);
assertThat(oauth2Enabled2).isFalse();
//delete domain
domainService.deleteDomainById(SYSTEM_TENANT_ID, savedDomain.getId());
assertThat(domainService.findDomainById(SYSTEM_TENANT_ID, savedDomain.getId())).isNull();
}
@Test
public void testGetTenantDomains() {
List<Domain> domains = new ArrayList<>();
for (int i = 0; i < 5; i++) {
Domain oAuth2Client = validDomain(TenantId.SYS_TENANT_ID, StringUtils.randomAlphabetic(5), true, false);
Domain savedOauth2Client = domainService.saveDomain(SYSTEM_TENANT_ID, oAuth2Client);
domains.add(savedOauth2Client);
}
List<DomainInfo> retrieved = domainService.findDomainInfosByTenantId(TenantId.SYS_TENANT_ID);
List<DomainInfo> domainInfos = domains.stream().map(domain -> new DomainInfo(domain, Collections.emptyList())).toList();
assertThat(retrieved).containsOnlyOnceElementsOf(domainInfos);
}
@Test
public void tesGetDomainInfo() {
OAuth2Client oAuth2Client = validClientInfo(TenantId.SYS_TENANT_ID, "Test google client");
OAuth2Client savedOauth2Client = oAuth2ClientService.saveOAuth2Client(SYSTEM_TENANT_ID, oAuth2Client);
List<OAuth2ClientInfo> infos = oAuth2ClientService.findOAuth2ClientInfosByTenantId(TenantId.SYS_TENANT_ID);
Domain domain = validDomain(TenantId.SYS_TENANT_ID, "test.domain.com", true, true);
Domain savedDomain = domainService.saveDomain(SYSTEM_TENANT_ID, domain);
domainService.updateOauth2Clients(TenantId.SYS_TENANT_ID, savedDomain.getId(), List.of(savedOauth2Client.getId()));
// check domain info
DomainInfo retrievedInfo = domainService.findDomainInfoById(SYSTEM_TENANT_ID, savedDomain.getId());
assertThat(retrievedInfo).isEqualTo(new DomainInfo(savedDomain, infos));
//find clients by domain name
List<OAuth2ClientLoginInfo> oauth2LoginInfo = oAuth2ClientService.findOAuth2ClientLoginInfosByDomainName(savedDomain.getName());
assertThat(oauth2LoginInfo).containsOnly(new OAuth2ClientLoginInfo(savedOauth2Client.getName(), savedOauth2Client.getLoginButtonIcon(), String.format(OAUTH2_AUTHORIZATION_PATH_TEMPLATE, savedOauth2Client.getUuidId().toString())));
}
private Domain validDomain(TenantId tenantId, String domainName, boolean oauth2Enabled, boolean propagateToEdge) {
Domain domain = new Domain();
domain.setTenantId(tenantId);
domain.setName(domainName);
domain.setOauth2Enabled(oauth2Enabled);
domain.setPropagateToEdge(propagateToEdge);
return domain;
}
}

113
dao/src/test/java/org/thingsboard/server/dao/service/MobileAppServiceTest.java

@ -0,0 +1,113 @@
/**
* Copyright © 2016-2024 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.dao.service;
import org.junit.After;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.mobile.MobileApp;
import org.thingsboard.server.common.data.mobile.MobileAppInfo;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientLoginInfo;
import org.thingsboard.server.dao.mobile.MobileAppService;
import org.thingsboard.server.dao.oauth2.OAuth2ClientService;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.thingsboard.server.dao.oauth2.OAuth2Utils.OAUTH2_AUTHORIZATION_PATH_TEMPLATE;
@DaoSqlTest
public class MobileAppServiceTest extends AbstractServiceTest {
@Autowired
protected MobileAppService mobileAppService;
@Autowired
protected OAuth2ClientService oAuth2ClientService;
@After
public void after() {
mobileAppService.deleteByTenantId(TenantId.SYS_TENANT_ID);
}
@Test
public void testSaveMobileApp() {
MobileApp MobileApp = validMobileApp(TenantId.SYS_TENANT_ID, "mobileApp.ce", true);
MobileApp savedMobileApp = mobileAppService.saveMobileApp(SYSTEM_TENANT_ID, MobileApp);
MobileApp retrievedMobileApp = mobileAppService.findMobileAppById(savedMobileApp.getTenantId(), savedMobileApp.getId());
assertThat(retrievedMobileApp).isEqualTo(savedMobileApp);
// update MobileApp name
savedMobileApp.setPkgName("mobileApp.pe");
MobileApp updatedMobileApp = mobileAppService.saveMobileApp(SYSTEM_TENANT_ID, savedMobileApp);
MobileApp retrievedMobileApp2 = mobileAppService.findMobileAppById(savedMobileApp.getTenantId(), savedMobileApp.getId());
assertThat(retrievedMobileApp2).isEqualTo(updatedMobileApp);
//delete MobileApp
mobileAppService.deleteMobileAppById(SYSTEM_TENANT_ID, savedMobileApp.getId());
assertThat(mobileAppService.findMobileAppById(SYSTEM_TENANT_ID, savedMobileApp.getId())).isNull();
}
@Test
public void testGetTenantMobileApps() {
List<MobileApp> MobileApps = new ArrayList<>();
for (int i = 0; i < 5; i++) {
MobileApp oAuth2Client = validMobileApp(TenantId.SYS_TENANT_ID, StringUtils.randomAlphabetic(5), true);
MobileApp savedOauth2Client = mobileAppService.saveMobileApp(SYSTEM_TENANT_ID, oAuth2Client);
MobileApps.add(savedOauth2Client);
}
List<MobileAppInfo> retrieved = mobileAppService.findMobileAppInfosByTenantId(TenantId.SYS_TENANT_ID);
List<MobileAppInfo> MobileAppInfos = MobileApps.stream().map(MobileApp -> new MobileAppInfo(MobileApp, Collections.emptyList())).toList();
assertThat(retrieved).containsOnlyOnceElementsOf(MobileAppInfos);
}
@Test
public void tesGetMobileAppInfo() {
OAuth2Client oAuth2Client = validClientInfo(TenantId.SYS_TENANT_ID, "Test google client");
OAuth2Client savedOauth2Client = oAuth2ClientService.saveOAuth2Client(SYSTEM_TENANT_ID, oAuth2Client);
List<OAuth2ClientInfo> infos = oAuth2ClientService.findOAuth2ClientInfosByTenantId(TenantId.SYS_TENANT_ID);
MobileApp MobileApp = validMobileApp(TenantId.SYS_TENANT_ID, "my.app", true);
MobileApp savedMobileApp = mobileAppService.saveMobileApp(SYSTEM_TENANT_ID, MobileApp);
mobileAppService.updateOauth2Clients(TenantId.SYS_TENANT_ID, savedMobileApp.getId(), List.of(savedOauth2Client.getId()));
// check MobileApp info
MobileAppInfo retrievedInfo = mobileAppService.findMobileAppInfoById(SYSTEM_TENANT_ID, savedMobileApp.getId());
assertThat(retrievedInfo).isEqualTo(new MobileAppInfo(savedMobileApp, infos));
//find clients by MobileApp name
List<OAuth2ClientLoginInfo> oauth2LoginInfo = oAuth2ClientService.findOAuth2ClientLoginInfosByMobilePkgNameAndPlatformType(savedMobileApp.getName(), null);
assertThat(oauth2LoginInfo).containsOnly(new OAuth2ClientLoginInfo(savedOauth2Client.getName(), savedOauth2Client.getLoginButtonIcon(), String.format(OAUTH2_AUTHORIZATION_PATH_TEMPLATE, savedOauth2Client.getUuidId().toString())));
}
private MobileApp validMobileApp(TenantId tenantId, String mobileAppName, boolean oauth2Enabled) {
MobileApp MobileApp = new MobileApp();
MobileApp.setTenantId(tenantId);
MobileApp.setPkgName(mobileAppName);
MobileApp.setAppSecret(StringUtils.randomAlphanumeric(24));
MobileApp.setOauth2Enabled(oauth2Enabled);
return MobileApp;
}
}

662
dao/src/test/java/org/thingsboard/server/dao/service/OAuth2ClientServiceTest.java

@ -15,627 +15,63 @@
*/
package org.thingsboard.server.dao.service;
import org.junit.After;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo;
import org.thingsboard.server.common.data.oauth2.PlatformType;
import org.thingsboard.server.dao.oauth2.OAuth2ClientService;
import org.thingsboard.server.dao.oauth2.OAuth2Utils;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import static org.assertj.core.api.Assertions.assertThat;
@DaoSqlTest
public class OAuth2ClientServiceTest extends AbstractServiceTest {
// private static final OAuth2Info EMPTY_PARAMS = new OAuth2Info(false, false, Collections.emptyList());
@Autowired
protected OAuth2ClientService oAuth2ClientService;
// @Before
// public void beforeRun() {
// Assert.assertTrue(oAuth2Service.findOauth2ProvidersByTenantId().isEmpty());
// }
//
// @After
// public void after() {
// oAuth2Service.saveOAuth2Info(EMPTY_PARAMS);
// Assert.assertTrue(oAuth2Service.findOauth2ProvidersByTenantId().isEmpty());
// Assert.assertTrue(oAuth2Service.findOAuth2Info().getOauth2ParamsInfos().isEmpty());
// }
//
// @Test
// public void testSaveHttpAndMixedDomainsTogether() {
// OAuth2Info oAuth2Info = new OAuth2Info(true, false, Lists.newArrayList(
// OAuth2ParamsInfo.builder()
// .domainInfos(Lists.newArrayList(
// OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
// OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.MIXED).build(),
// OAuth2DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
// ))
// .clientRegistrations(Lists.newArrayList(
// validRegistrationInfo(),
// validRegistrationInfo(),
// validRegistrationInfo()
// ))
// .build()
// ));
// Assertions.assertThrows(DataValidationException.class, () -> {
// oAuth2Service.saveOAuth2Info(oAuth2Info);
// });
// }
//
// @Test
// public void testSaveHttpsAndMixedDomainsTogether() {
// OAuth2Info oAuth2Info = new OAuth2Info(true, false, Lists.newArrayList(
// OAuth2ParamsInfo.builder()
// .domainInfos(Lists.newArrayList(
// OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTPS).build(),
// OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.MIXED).build(),
// OAuth2DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
// ))
// .clientRegistrations(Lists.newArrayList(
// validRegistrationInfo(),
// validRegistrationInfo(),
// validRegistrationInfo()
// ))
// .build()
// ));
// Assertions.assertThrows(DataValidationException.class, () -> {
// oAuth2Service.saveOAuth2Info(oAuth2Info);
// });
// }
//
// @Test
// public void testCreateAndFindParams() {
// OAuth2Info oAuth2Info = createDefaultOAuth2Info();
// oAuth2Service.saveOAuth2Info(oAuth2Info);
// OAuth2Info foundOAuth2Info = oAuth2Service.findOAuth2Info();
// Assert.assertNotNull(foundOAuth2Info);
// // TODO ask if it's safe to check equality on AdditionalProperties
// Assert.assertEquals(oAuth2Info, foundOAuth2Info);
// }
//
// @Test
// public void testDisableParams() {
// OAuth2Info oAuth2Info = createDefaultOAuth2Info();
// oAuth2Info.setEnabled(true);
// oAuth2Service.saveOAuth2Info(oAuth2Info);
// OAuth2Info foundOAuth2Info = oAuth2Service.findOAuth2Info();
// Assert.assertNotNull(foundOAuth2Info);
// Assert.assertEquals(oAuth2Info, foundOAuth2Info);
//
// oAuth2Info.setEnabled(false);
// oAuth2Service.saveOAuth2Info(oAuth2Info);
// OAuth2Info foundDisabledOAuth2Info = oAuth2Service.findOAuth2Info();
// Assert.assertEquals(oAuth2Info, foundDisabledOAuth2Info);
// }
//
// @Test
// public void testClearDomainParams() {
// OAuth2Info oAuth2Info = createDefaultOAuth2Info();
// oAuth2Service.saveOAuth2Info(oAuth2Info);
// OAuth2Info foundOAuth2Info = oAuth2Service.findOAuth2Info();
// Assert.assertNotNull(foundOAuth2Info);
// Assert.assertEquals(oAuth2Info, foundOAuth2Info);
//
// oAuth2Service.saveOAuth2Info(EMPTY_PARAMS);
// OAuth2Info foundAfterClearClientsParams = oAuth2Service.findOAuth2Info();
// Assert.assertNotNull(foundAfterClearClientsParams);
// Assert.assertEquals(EMPTY_PARAMS, foundAfterClearClientsParams);
// }
//
// @Test
// public void testUpdateClientsParams() {
// OAuth2Info oAuth2Info = createDefaultOAuth2Info();
// oAuth2Service.saveOAuth2Info(oAuth2Info);
// OAuth2Info foundOAuth2Info = oAuth2Service.findOAuth2Info();
// Assert.assertNotNull(foundOAuth2Info);
// Assert.assertEquals(oAuth2Info, foundOAuth2Info);
//
// OAuth2Info newOAuth2Info = new OAuth2Info(true, false, Lists.newArrayList(
// OAuth2ParamsInfo.builder()
// .domainInfos(Lists.newArrayList(
// OAuth2DomainInfo.builder().name("another-domain").scheme(SchemeType.HTTPS).build()
// ))
// .mobileInfos(Collections.emptyList())
// .clientRegistrations(Lists.newArrayList(
// validRegistrationInfo()
// ))
// .build(),
// OAuth2ParamsInfo.builder()
// .domainInfos(Lists.newArrayList(
// OAuth2DomainInfo.builder().name("test-domain").scheme(SchemeType.MIXED).build()
// ))
// .mobileInfos(Collections.emptyList())
// .clientRegistrations(Lists.newArrayList(
// validRegistrationInfo()
// ))
// .build()
// ));
// oAuth2Service.saveOAuth2Info(newOAuth2Info);
// OAuth2Info foundAfterUpdateOAuth2Info = oAuth2Service.findOAuth2Info();
// Assert.assertNotNull(foundAfterUpdateOAuth2Info);
// Assert.assertEquals(newOAuth2Info, foundAfterUpdateOAuth2Info);
// }
//
// @Test
// public void testGetOAuth2Clients() {
// List<OAuth2RegistrationInfo> firstGroup = Lists.newArrayList(
// validRegistrationInfo(),
// validRegistrationInfo(),
// validRegistrationInfo(),
// validRegistrationInfo()
// );
// List<OAuth2RegistrationInfo> secondGroup = Lists.newArrayList(
// validRegistrationInfo(),
// validRegistrationInfo()
// );
// List<OAuth2RegistrationInfo> thirdGroup = Lists.newArrayList(
// validRegistrationInfo()
// );
// OAuth2Info oAuth2Info = new OAuth2Info(true, false, Lists.newArrayList(
// OAuth2ParamsInfo.builder()
// .domainInfos(Lists.newArrayList(
// OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
// OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
// OAuth2DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
// ))
// .mobileInfos(Collections.emptyList())
// .clientRegistrations(firstGroup)
// .build(),
// OAuth2ParamsInfo.builder()
// .domainInfos(Lists.newArrayList(
// OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),
// OAuth2DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
// ))
// .mobileInfos(Collections.emptyList())
// .clientRegistrations(secondGroup)
// .build(),
// OAuth2ParamsInfo.builder()
// .domainInfos(Lists.newArrayList(
// OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTPS).build(),
// OAuth2DomainInfo.builder().name("fifth-domain").scheme(SchemeType.HTTP).build()
// ))
// .mobileInfos(Collections.emptyList())
// .clientRegistrations(thirdGroup)
// .build()
// ));
//
// oAuth2Service.saveOAuth2Info(oAuth2Info);
// OAuth2Info foundOAuth2Info = oAuth2Service.findOAuth2Info();
// Assert.assertNotNull(foundOAuth2Info);
// Assert.assertEquals(oAuth2Info, foundOAuth2Info);
//
// List<OAuth2ClientInfo> firstGroupClientInfos = firstGroup.stream()
// .map(registrationInfo -> new OAuth2ClientInfo(
// registrationInfo.getLoginButtonLabel(), registrationInfo.getLoginButtonIcon(), null))
// .collect(Collectors.toList());
// List<OAuth2ClientInfo> secondGroupClientInfos = secondGroup.stream()
// .map(registrationInfo -> new OAuth2ClientInfo(
// registrationInfo.getLoginButtonLabel(), registrationInfo.getLoginButtonIcon(), null))
// .collect(Collectors.toList());
// List<OAuth2ClientInfo> thirdGroupClientInfos = thirdGroup.stream()
// .map(registrationInfo -> new OAuth2ClientInfo(
// registrationInfo.getLoginButtonLabel(), registrationInfo.getLoginButtonIcon(), null))
// .collect(Collectors.toList());
//
// List<OAuth2ClientInfo> nonExistentDomainClients = oAuth2Service.getOAuth2Clients("http", "non-existent-domain", null, null);
// Assert.assertTrue(nonExistentDomainClients.isEmpty());
//
// List<OAuth2ClientInfo> firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain", null, null);
// Assert.assertEquals(firstGroupClientInfos.size(), firstDomainHttpClients.size());
// firstGroupClientInfos.forEach(firstGroupClientInfo -> {
// Assert.assertTrue(
// firstDomainHttpClients.stream().anyMatch(clientInfo ->
// clientInfo.getIcon().equals(firstGroupClientInfo.getIcon())
// && clientInfo.getName().equals(firstGroupClientInfo.getName()))
// );
// });
//
// List<OAuth2ClientInfo> firstDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "first-domain", null, null);
// Assert.assertTrue(firstDomainHttpsClients.isEmpty());
//
// List<OAuth2ClientInfo> fourthDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "fourth-domain", null, null);
// Assert.assertEquals(secondGroupClientInfos.size(), fourthDomainHttpClients.size());
// secondGroupClientInfos.forEach(secondGroupClientInfo -> {
// Assert.assertTrue(
// fourthDomainHttpClients.stream().anyMatch(clientInfo ->
// clientInfo.getIcon().equals(secondGroupClientInfo.getIcon())
// && clientInfo.getName().equals(secondGroupClientInfo.getName()))
// );
// });
// List<OAuth2ClientInfo> fourthDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "fourth-domain", null, null);
// Assert.assertEquals(secondGroupClientInfos.size(), fourthDomainHttpsClients.size());
// secondGroupClientInfos.forEach(secondGroupClientInfo -> {
// Assert.assertTrue(
// fourthDomainHttpsClients.stream().anyMatch(clientInfo ->
// clientInfo.getIcon().equals(secondGroupClientInfo.getIcon())
// && clientInfo.getName().equals(secondGroupClientInfo.getName()))
// );
// });
//
// List<OAuth2ClientInfo> secondDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "second-domain", null, null);
// Assert.assertEquals(firstGroupClientInfos.size() + secondGroupClientInfos.size(), secondDomainHttpClients.size());
// firstGroupClientInfos.forEach(firstGroupClientInfo -> {
// Assert.assertTrue(
// secondDomainHttpClients.stream().anyMatch(clientInfo ->
// clientInfo.getIcon().equals(firstGroupClientInfo.getIcon())
// && clientInfo.getName().equals(firstGroupClientInfo.getName()))
// );
// });
// secondGroupClientInfos.forEach(secondGroupClientInfo -> {
// Assert.assertTrue(
// secondDomainHttpClients.stream().anyMatch(clientInfo ->
// clientInfo.getIcon().equals(secondGroupClientInfo.getIcon())
// && clientInfo.getName().equals(secondGroupClientInfo.getName()))
// );
// });
//
// List<OAuth2ClientInfo> secondDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "second-domain", null, null);
// Assert.assertEquals(firstGroupClientInfos.size() + thirdGroupClientInfos.size(), secondDomainHttpsClients.size());
// firstGroupClientInfos.forEach(firstGroupClientInfo -> {
// Assert.assertTrue(
// secondDomainHttpsClients.stream().anyMatch(clientInfo ->
// clientInfo.getIcon().equals(firstGroupClientInfo.getIcon())
// && clientInfo.getName().equals(firstGroupClientInfo.getName()))
// );
// });
// thirdGroupClientInfos.forEach(thirdGroupClientInfo -> {
// Assert.assertTrue(
// secondDomainHttpsClients.stream().anyMatch(clientInfo ->
// clientInfo.getIcon().equals(thirdGroupClientInfo.getIcon())
// && clientInfo.getName().equals(thirdGroupClientInfo.getName()))
// );
// });
// }
//
// @Test
// public void testGetOAuth2ClientsForHttpAndHttps() {
// List<OAuth2RegistrationInfo> firstGroup = Lists.newArrayList(
// validRegistrationInfo(),
// validRegistrationInfo(),
// validRegistrationInfo(),
// validRegistrationInfo()
// );
// OAuth2Info oAuth2Info = new OAuth2Info(true, false, Lists.newArrayList(
// OAuth2ParamsInfo.builder()
// .domainInfos(Lists.newArrayList(
// OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
// OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
// OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTPS).build()
// ))
// .mobileInfos(Collections.emptyList())
// .clientRegistrations(firstGroup)
// .build()
// ));
//
// oAuth2Service.saveOAuth2Info(oAuth2Info);
// OAuth2Info foundOAuth2Info = oAuth2Service.findOAuth2Info();
// Assert.assertNotNull(foundOAuth2Info);
// Assert.assertEquals(oAuth2Info, foundOAuth2Info);
//
// List<OAuth2ClientInfo> firstGroupClientInfos = firstGroup.stream()
// .map(registrationInfo -> new OAuth2ClientInfo(
// registrationInfo.getLoginButtonLabel(), registrationInfo.getLoginButtonIcon(), null))
// .collect(Collectors.toList());
//
// List<OAuth2ClientInfo> firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain", null, null);
// Assert.assertEquals(firstGroupClientInfos.size(), firstDomainHttpClients.size());
// firstGroupClientInfos.forEach(firstGroupClientInfo -> {
// Assert.assertTrue(
// firstDomainHttpClients.stream().anyMatch(clientInfo ->
// clientInfo.getIcon().equals(firstGroupClientInfo.getIcon())
// && clientInfo.getName().equals(firstGroupClientInfo.getName()))
// );
// });
//
// List<OAuth2ClientInfo> firstDomainHttpsClients = oAuth2Service.getOAuth2Clients("https", "first-domain", null, null);
// Assert.assertEquals(firstGroupClientInfos.size(), firstDomainHttpsClients.size());
// firstGroupClientInfos.forEach(firstGroupClientInfo -> {
// Assert.assertTrue(
// firstDomainHttpsClients.stream().anyMatch(clientInfo ->
// clientInfo.getIcon().equals(firstGroupClientInfo.getIcon())
// && clientInfo.getName().equals(firstGroupClientInfo.getName()))
// );
// });
// }
//
// @Test
// public void testGetDisabledOAuth2Clients() {
// OAuth2Info oAuth2Info = new OAuth2Info(true, false, Lists.newArrayList(
// OAuth2ParamsInfo.builder()
// .domainInfos(Lists.newArrayList(
// OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
// OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
// OAuth2DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
// ))
// .clientRegistrations(Lists.newArrayList(
// validRegistrationInfo(),
// validRegistrationInfo(),
// validRegistrationInfo()
// ))
// .build(),
// OAuth2ParamsInfo.builder()
// .domainInfos(Lists.newArrayList(
// OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),
// OAuth2DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
// ))
// .clientRegistrations(Lists.newArrayList(
// validRegistrationInfo(),
// validRegistrationInfo()
// ))
// .build()
// ));
//
// oAuth2Service.saveOAuth2Info(oAuth2Info);
//
// List<OAuth2ClientInfo> secondDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "second-domain", null, null);
// Assert.assertEquals(5, secondDomainHttpClients.size());
//
// oAuth2Info.setEnabled(false);
// oAuth2Service.saveOAuth2Info(oAuth2Info);
//
// List<OAuth2ClientInfo> secondDomainHttpDisabledClients = oAuth2Service.getOAuth2Clients("http", "second-domain", null, null);
// Assert.assertEquals(0, secondDomainHttpDisabledClients.size());
// }
//
// @Test
// public void testFindAllRegistrations() {
// OAuth2Info oAuth2Info = new OAuth2Info(true, false, Lists.newArrayList(
// OAuth2ParamsInfo.builder()
// .domainInfos(Lists.newArrayList(
// OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
// OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
// OAuth2DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
// ))
// .clientRegistrations(Lists.newArrayList(
// validRegistrationInfo(),
// validRegistrationInfo(),
// validRegistrationInfo()
// ))
// .build(),
// OAuth2ParamsInfo.builder()
// .domainInfos(Lists.newArrayList(
// OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),
// OAuth2DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
// ))
// .clientRegistrations(Lists.newArrayList(
// validRegistrationInfo(),
// validRegistrationInfo()
// ))
// .build(),
// OAuth2ParamsInfo.builder()
// .domainInfos(Lists.newArrayList(
// OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTPS).build(),
// OAuth2DomainInfo.builder().name("fifth-domain").scheme(SchemeType.HTTP).build()
// ))
// .clientRegistrations(Lists.newArrayList(
// validRegistrationInfo()
// ))
// .build()
// ));
//
// oAuth2Service.saveOAuth2Info(oAuth2Info);
// List<OAuth2Provider> foundRegistrations = oAuth2Service.findOauth2ProvidersByTenantId();
// Assert.assertEquals(6, foundRegistrations.size());
// oAuth2Info.getOauth2ParamsInfos().stream()
// .flatMap(paramsInfo -> paramsInfo.getClientRegistrations().stream())
// .forEach(registrationInfo ->
// Assert.assertTrue(
// foundRegistrations.stream()
// .anyMatch(registration -> registration.getClientId().equals(registrationInfo.getClientId()))
// )
// );
// }
//
// @Test
// public void testFindRegistrationById() {
// OAuth2Info oAuth2Info = new OAuth2Info(true, false, Lists.newArrayList(
// OAuth2ParamsInfo.builder()
// .domainInfos(Lists.newArrayList(
// OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
// OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
// OAuth2DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
// ))
// .clientRegistrations(Lists.newArrayList(
// validRegistrationInfo(),
// validRegistrationInfo(),
// validRegistrationInfo()
// ))
// .build(),
// OAuth2ParamsInfo.builder()
// .domainInfos(Lists.newArrayList(
// OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),
// OAuth2DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
// ))
// .clientRegistrations(Lists.newArrayList(
// validRegistrationInfo(),
// validRegistrationInfo()
// ))
// .build(),
// OAuth2ParamsInfo.builder()
// .domainInfos(Lists.newArrayList(
// OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTPS).build(),
// OAuth2DomainInfo.builder().name("fifth-domain").scheme(SchemeType.HTTP).build()
// ))
// .clientRegistrations(Lists.newArrayList(
// validRegistrationInfo()
// ))
// .build()
// ));
//
// oAuth2Service.saveOAuth2Info(oAuth2Info);
// List<OAuth2Provider> foundRegistrations = oAuth2Service.findOauth2ProvidersByTenantId();
// foundRegistrations.forEach(registration -> {
// OAuth2Provider foundRegistration = oAuth2Service.findProvider(registration.getUuidId());
// Assert.assertEquals(registration, foundRegistration);
// });
// }
//
// @Test
// public void testFindAppSecret() {
// OAuth2Info oAuth2Info = new OAuth2Info(true, false, Lists.newArrayList(
// OAuth2ParamsInfo.builder()
// .domainInfos(Lists.newArrayList(
// OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
// OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
// OAuth2DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
// ))
// .mobileInfos(Lists.newArrayList(
// validMobileInfo("com.test.pkg1", "testPkg1AppSecret"),
// validMobileInfo("com.test.pkg2", "testPkg2AppSecret")
// ))
// .clientRegistrations(Lists.newArrayList(
// validRegistrationInfo(),
// validRegistrationInfo(),
// validRegistrationInfo()
// ))
// .build(),
// OAuth2ParamsInfo.builder()
// .domainInfos(Lists.newArrayList(
// OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),
// OAuth2DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
// ))
// .mobileInfos(Collections.emptyList())
// .clientRegistrations(Lists.newArrayList(
// validRegistrationInfo(),
// validRegistrationInfo()
// ))
// .build()
// ));
// oAuth2Service.saveOAuth2Info(oAuth2Info);
//
// OAuth2Info foundOAuth2Info = oAuth2Service.findOAuth2Info();
// Assert.assertEquals(oAuth2Info, foundOAuth2Info);
//
// List<OAuth2ClientInfo> firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain", "com.test.pkg1", null);
// Assert.assertEquals(3, firstDomainHttpClients.size());
// for (OAuth2ClientInfo clientInfo : firstDomainHttpClients) {
// String[] segments = clientInfo.getUrl().split("/");
// String registrationId = segments[segments.length-1];
// String appSecret = oAuth2Service.findAppSecret(UUID.fromString(registrationId), "com.test.pkg1");
// Assert.assertNotNull(appSecret);
// Assert.assertEquals("testPkg1AppSecret", appSecret);
// appSecret = oAuth2Service.findAppSecret(UUID.fromString(registrationId), "com.test.pkg2");
// Assert.assertNotNull(appSecret);
// Assert.assertEquals("testPkg2AppSecret", appSecret);
// appSecret = oAuth2Service.findAppSecret(UUID.fromString(registrationId), "com.test.pkg3");
// Assert.assertNull(appSecret);
// }
// }
//
// @Test
// public void testFindClientsByPackageAndPlatform() {
// OAuth2Info oAuth2Info = new OAuth2Info(true, false, Lists.newArrayList(
// OAuth2ParamsInfo.builder()
// .domainInfos(Lists.newArrayList(
// OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
// OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
// OAuth2DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
// ))
// .mobileInfos(Lists.newArrayList(
// validMobileInfo("com.test.pkg1", "testPkg1Callback"),
// validMobileInfo("com.test.pkg2", "testPkg2Callback")
// ))
// .clientRegistrations(Lists.newArrayList(
// validRegistrationInfo("Google", Arrays.asList(PlatformType.WEB, PlatformType.ANDROID)),
// validRegistrationInfo("Facebook", Arrays.asList(PlatformType.IOS)),
// validRegistrationInfo("GitHub", Collections.emptyList())
// ))
// .build(),
// OAuth2ParamsInfo.builder()
// .domainInfos(Lists.newArrayList(
// OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.HTTP).build(),
// OAuth2DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
// ))
// .mobileInfos(Collections.emptyList())
// .clientRegistrations(Lists.newArrayList(
// validRegistrationInfo(),
// validRegistrationInfo()
// ))
// .build()
// ));
// oAuth2Service.saveOAuth2Info(oAuth2Info);
//
// OAuth2Info foundOAuth2Info = oAuth2Service.findOAuth2Info();
// Assert.assertEquals(oAuth2Info, foundOAuth2Info);
//
// List<OAuth2ClientInfo> firstDomainHttpClients = oAuth2Service.getOAuth2Clients("http", "first-domain", null, null);
// Assert.assertEquals(3, firstDomainHttpClients.size());
// List<OAuth2ClientInfo> pkg1Clients = oAuth2Service.getOAuth2Clients("http", "first-domain", "com.test.pkg1", null);
// Assert.assertEquals(3, pkg1Clients.size());
// List<OAuth2ClientInfo> pkg1AndroidClients = oAuth2Service.getOAuth2Clients("http", "first-domain", "com.test.pkg1", PlatformType.ANDROID);
// Assert.assertEquals(2, pkg1AndroidClients.size());
// Assert.assertTrue(pkg1AndroidClients.stream().anyMatch(client -> client.getName().equals("Google")));
// Assert.assertTrue(pkg1AndroidClients.stream().anyMatch(client -> client.getName().equals("GitHub")));
// List<OAuth2ClientInfo> pkg1IOSClients = oAuth2Service.getOAuth2Clients("http", "first-domain", "com.test.pkg1", PlatformType.IOS);
// Assert.assertEquals(2, pkg1IOSClients.size());
// Assert.assertTrue(pkg1IOSClients.stream().anyMatch(client -> client.getName().equals("Facebook")));
// Assert.assertTrue(pkg1IOSClients.stream().anyMatch(client -> client.getName().equals("GitHub")));
// }
//
// private OAuth2Info createDefaultOAuth2Info() {
// return new OAuth2Info(true, false, Lists.newArrayList(
// OAuth2ParamsInfo.builder()
// .domainInfos(Lists.newArrayList(
// OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(),
// OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
// OAuth2DomainInfo.builder().name("third-domain").scheme(SchemeType.HTTPS).build()
// ))
// .mobileInfos(Collections.emptyList())
// .clientRegistrations(Lists.newArrayList(
// validRegistrationInfo(),
// validRegistrationInfo(),
// validRegistrationInfo(),
// validRegistrationInfo()
// ))
// .build(),
// OAuth2ParamsInfo.builder()
// .domainInfos(Lists.newArrayList(
// OAuth2DomainInfo.builder().name("second-domain").scheme(SchemeType.MIXED).build(),
// OAuth2DomainInfo.builder().name("fourth-domain").scheme(SchemeType.MIXED).build()
// ))
// .mobileInfos(Collections.emptyList())
// .clientRegistrations(Lists.newArrayList(
// validRegistrationInfo(),
// validRegistrationInfo()
// ))
// .build()
// ));
// }
//
// private OAuth2RegistrationInfo validRegistrationInfo() {
// return validRegistrationInfo(null, Collections.emptyList());
// }
//
// private OAuth2RegistrationInfo validRegistrationInfo(String label, List<PlatformType> platforms) {
// return OAuth2RegistrationInfo.builder()
// .clientId(UUID.randomUUID().toString())
// .clientSecret(UUID.randomUUID().toString())
// .authorizationUri(UUID.randomUUID().toString())
// .accessTokenUri(UUID.randomUUID().toString())
// .scope(Arrays.asList(UUID.randomUUID().toString(), UUID.randomUUID().toString()))
// .platforms(platforms == null ? Collections.emptyList() : platforms)
// .userInfoUri(UUID.randomUUID().toString())
// .userNameAttributeName(UUID.randomUUID().toString())
// .jwkSetUri(UUID.randomUUID().toString())
// .clientAuthenticationMethod(UUID.randomUUID().toString())
// .loginButtonLabel(label != null ? label : UUID.randomUUID().toString())
// .loginButtonIcon(UUID.randomUUID().toString())
// .additionalInfo(JacksonUtil.newObjectNode().put(UUID.randomUUID().toString(), UUID.randomUUID().toString()))
// .mapperConfig(
// OAuth2MapperConfig.builder()
// .allowUserCreation(true)
// .activateUser(true)
// .type(MapperType.CUSTOM)
// .custom(
// OAuth2CustomMapperConfig.builder()
// .url(UUID.randomUUID().toString())
// .build()
// )
// .build()
// )
// .build();
// }
//
// private MobileAppInfo validMobileInfo(String pkgName, String appSecret) {
// return MobileAppInfo.builder().pkgName(pkgName)
// .appSecret(appSecret != null ? appSecret : StringUtils.randomAlphanumeric(24))
// .build();
// }
@After
public void after() {
oAuth2ClientService.deleteByTenantId(TenantId.SYS_TENANT_ID);
}
@Test
public void testSaveOauth2Client() {
OAuth2Client oAuth2Client = validClientInfo(TenantId.SYS_TENANT_ID, "Test google client", List.of(PlatformType.ANDROID));
OAuth2Client savedOauth2Client = oAuth2ClientService.saveOAuth2Client(SYSTEM_TENANT_ID, oAuth2Client);
OAuth2Client retrievedOauth2Client = oAuth2ClientService.findOAuth2ClientById(savedOauth2Client.getTenantId(), savedOauth2Client.getId());
assertThat(retrievedOauth2Client).isEqualTo(savedOauth2Client);
savedOauth2Client.setTitle("New title");
OAuth2Client updatedOauth2Client = oAuth2ClientService.saveOAuth2Client(SYSTEM_TENANT_ID, savedOauth2Client);
OAuth2Client retrievedOauth2Client2 = oAuth2ClientService.findOAuth2ClientById(savedOauth2Client.getTenantId(), savedOauth2Client.getId());
assertThat(retrievedOauth2Client2).isEqualTo(updatedOauth2Client);
}
@Test
public void testGetTenantOAuth2Clients() {
List<OAuth2Client> oAuth2Clients = new ArrayList<>();
for (int i = 0; i < 5; i++) {
OAuth2Client oAuth2Client = validClientInfo(TenantId.SYS_TENANT_ID, StringUtils.randomAlphabetic(5));
OAuth2Client savedOauth2Client = oAuth2ClientService.saveOAuth2Client(SYSTEM_TENANT_ID, oAuth2Client);
oAuth2Clients.add(savedOauth2Client);
}
List<OAuth2Client> retrieved = oAuth2ClientService.findOAuth2ClientsByTenantId(TenantId.SYS_TENANT_ID);
assertThat(retrieved).containsOnlyOnceElementsOf(oAuth2Clients);
List<OAuth2ClientInfo> retrievedInfos = oAuth2ClientService.findOAuth2ClientInfosByTenantId(TenantId.SYS_TENANT_ID);
List<OAuth2ClientInfo> oAuth2ClientInfos = oAuth2Clients.stream().map(OAuth2Utils::toClientInfo).collect(Collectors.toList());
assertThat(retrievedInfos).containsOnlyOnceElementsOf(oAuth2ClientInfos);
}
}

6
rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java

@ -117,7 +117,7 @@ import org.thingsboard.server.common.data.id.WidgetsBundleId;
import org.thingsboard.server.common.data.kv.Aggregation;
import org.thingsboard.server.common.data.kv.AttributeKvEntry;
import org.thingsboard.server.common.data.kv.TsKvEntry;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientLoginInfo;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationTemplate;
import org.thingsboard.server.common.data.oauth2.PlatformType;
import org.thingsboard.server.common.data.ota.ChecksumAlgorithm;
@ -2045,7 +2045,7 @@ public class RestClient implements Closeable {
}).getBody();
}
public List<OAuth2ClientInfo> getOAuth2Clients(String pkgName, PlatformType platformType) {
public List<OAuth2ClientLoginInfo> getOAuth2Clients(String pkgName, PlatformType platformType) {
Map<String, String> params = new HashMap<>();
StringBuilder urlBuilder = new StringBuilder(baseURL);
urlBuilder.append("/api/noauth/oauth2Clients");
@ -2066,7 +2066,7 @@ public class RestClient implements Closeable {
urlBuilder.toString(),
HttpMethod.POST,
HttpEntity.EMPTY,
new ParameterizedTypeReference<List<OAuth2ClientInfo>>() {
new ParameterizedTypeReference<List<OAuth2ClientLoginInfo>>() {
}, params).getBody();
}

Loading…
Cancel
Save