Browse Source

fixed pull request comments

pull/11231/head
dashevchenko 2 years ago
parent
commit
931102f73c
  1. 18
      application/src/main/data/upgrade/3.7.0/schema_update.sql
  2. 11
      application/src/main/java/org/thingsboard/server/config/CustomOAuth2AuthorizationRequestResolver.java
  3. 6
      application/src/main/java/org/thingsboard/server/controller/BaseController.java
  4. 6
      application/src/main/java/org/thingsboard/server/controller/DomainController.java
  5. 15
      application/src/main/java/org/thingsboard/server/controller/MobileAppController.java
  6. 28
      application/src/main/java/org/thingsboard/server/controller/OAuth2Controller.java
  7. 10
      application/src/main/java/org/thingsboard/server/service/entitiy/domain/DefaultTbDomainService.java
  8. 6
      application/src/main/java/org/thingsboard/server/service/entitiy/mobile/DefaultTbMobileAppService.java
  9. 6
      application/src/main/java/org/thingsboard/server/service/entitiy/oauth2client/DefaultTbOauth2ClientService.java
  10. 6
      application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java
  11. 10
      application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AbstractOAuth2ClientMapper.java
  12. 6
      application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AppleOAuth2ClientMapper.java
  13. 6
      application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java
  14. 6
      application/src/test/java/org/thingsboard/server/controller/DomainControllerTest.java
  15. 2
      application/src/test/java/org/thingsboard/server/controller/HomePageApiTest.java
  16. 6
      application/src/test/java/org/thingsboard/server/controller/MobileAppControllerTest.java
  17. 2
      application/src/test/java/org/thingsboard/server/controller/Oauth2ClientControllerTest.java
  18. 2
      common/dao-api/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientService.java
  19. 2
      common/data/src/main/java/org/thingsboard/server/common/data/domain/DomainOauth2Client.java
  20. 2
      common/data/src/main/java/org/thingsboard/server/common/data/mobile/MobileAppInfo.java
  21. 4
      common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2Client.java
  22. 5
      common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientInfo.java
  23. 5
      dao/src/main/java/org/thingsboard/server/dao/domain/DomainDao.java
  24. 94
      dao/src/main/java/org/thingsboard/server/dao/domain/DomainServiceImpl.java
  25. 4
      dao/src/main/java/org/thingsboard/server/dao/mobile/MobileAppDao.java
  26. 74
      dao/src/main/java/org/thingsboard/server/dao/mobile/MobileAppServiceImpl.java
  27. 4
      dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java
  28. 2
      dao/src/main/java/org/thingsboard/server/dao/model/sql/DomainEntity.java
  29. 4
      dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientDao.java
  30. 25
      dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientServiceImpl.java
  31. 3
      dao/src/main/java/org/thingsboard/server/dao/sql/domain/DomainOauth2ClientRepository.java
  32. 2
      dao/src/main/java/org/thingsboard/server/dao/sql/domain/DomainRepository.java
  33. 7
      dao/src/main/java/org/thingsboard/server/dao/sql/domain/JpaDomainDao.java
  34. 10
      dao/src/main/java/org/thingsboard/server/dao/sql/mobile/JpaMobileAppDao.java
  35. 3
      dao/src/main/java/org/thingsboard/server/dao/sql/mobile/MobileAppOauth2ClientRepository.java
  36. 6
      dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ClientDao.java
  37. 8
      dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/OAuth2ClientRepository.java
  38. 1
      dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java
  39. 2
      dao/src/main/resources/sql/schema-entities.sql

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

@ -18,6 +18,7 @@
ALTER TABLE IF EXISTS oauth2_mobile RENAME TO mobile_app;
ALTER TABLE IF EXISTS oauth2_domain RENAME TO domain;
ALTER TABLE IF EXISTS oauth2_domain RENAME domain_name TO name;
ALTER TABLE IF EXISTS oauth2_registration RENAME TO oauth2_client;
ALTER TABLE domain ADD COLUMN IF NOT EXISTS oauth2_enabled boolean,
@ -26,13 +27,21 @@ ALTER TABLE domain ADD COLUMN IF NOT EXISTS oauth2_enabled boolean,
DROP COLUMN IF EXISTS domain_scheme;
-- delete duplicated domains
DELETE FROM domain d1 USING domain d2 WHERE d1.created_time < d2.created_time AND d1.domain_name = d2.domain_name;
DELETE FROM domain d1 USING (
SELECT MIN(ctid) as ctid, name
FROM domain
GROUP BY name HAVING COUNT(*) > 1
) d2 WHERE d1.name = d2.name AND d1.ctid <> d2.ctid;
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';
-- delete duplicated apps
DELETE FROM mobile_app m1 USING mobile_app m2 WHERE m1.created_time < m2.created_time AND m1.pkg_name = m2.pkg_name;
DELETE FROM mobile_app m1 USING (
SELECT MIN(ctid) as ctid, pkg_name
FROM mobile_app
GROUP BY pkg_name HAVING COUNT(*) > 1
) m2 WHERE m1.pkg_name = m2.pkg_name AND m1.ctid <> m2.ctid;
ALTER TABLE oauth2_client ADD COLUMN IF NOT EXISTS tenant_id uuid DEFAULT '13814000-1dd2-11b2-8080-808080808080',
ADD COLUMN IF NOT EXISTS title varchar(100);
@ -81,9 +90,12 @@ $$
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);
ALTER TABLE domain ADD CONSTRAINT domain_unq_key UNIQUE (name);
DROP TABLE IF EXISTS oauth2_params;
-- drop deprecated tables
DROP TABLE IF EXISTS oauth2_client_registration_info;
DROP TABLE IF EXISTS oauth2_client_registration;
END IF;
END
$$;

11
application/src/main/java/org/thingsboard/server/config/CustomOAuth2AuthorizationRequestResolver.java

@ -37,6 +37,7 @@ import org.springframework.util.CollectionUtils;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import org.thingsboard.server.dao.oauth2.OAuth2Configuration;
import org.thingsboard.server.dao.oauth2.OAuth2ClientService;
import org.thingsboard.server.queue.util.TbCoreComponent;
@ -115,14 +116,14 @@ public class CustomOAuth2AuthorizationRequestResolver implements OAuth2Authoriza
return request.getParameter("appToken");
}
private OAuth2AuthorizationRequest resolve(HttpServletRequest request, String registrationId, String redirectUriAction, String appPackage, String appToken) {
if (registrationId == null) {
private OAuth2AuthorizationRequest resolve(HttpServletRequest request, String oauth2ClientId, String redirectUriAction, String appPackage, String appToken) {
if (oauth2ClientId == null) {
return null;
}
ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId(registrationId);
ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId(oauth2ClientId);
if (clientRegistration == null) {
throw new IllegalArgumentException("Invalid Client Registration with Id: " + registrationId);
throw new IllegalArgumentException("Invalid Client Registration with Id: " + oauth2ClientId);
}
Map<String, Object> attributes = new HashMap<>();
@ -131,7 +132,7 @@ public class CustomOAuth2AuthorizationRequestResolver implements OAuth2Authoriza
if (StringUtils.isEmpty(appToken)) {
throw new IllegalArgumentException("Invalid application token.");
} else {
String appSecret = this.oAuth2ClientService.findAppSecret(UUID.fromString(registrationId), appPackage);
String appSecret = this.oAuth2ClientService.findAppSecret(new OAuth2ClientId(UUID.fromString(oauth2ClientId)), appPackage);
if (StringUtils.isEmpty(appSecret)) {
throw new IllegalArgumentException("Invalid package: " + appPackage + ". No application secret found for Client Registration with given application package.");
}

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

@ -901,9 +901,11 @@ public abstract class BaseController {
}
protected List<OAuth2ClientId> getOAuth2ClientIds(UUID[] ids) throws ThingsboardException {
List<UUID> oauth2ClientIds = ids != null ? Arrays.asList(ids) : Collections.emptyList();
if (ids == null) {
return Collections.emptyList();
}
List<OAuth2ClientId> oAuth2ClientIds = new ArrayList<>();
for (UUID id : oauth2ClientIds) {
for (UUID id : ids) {
OAuth2ClientId oauth2ClientId = new OAuth2ClientId(id);
checkOauth2ClientId(oauth2ClientId, Operation.READ);
oAuth2ClientIds.add(oauth2ClientId);

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

@ -76,7 +76,7 @@ public class DomainController extends BaseController {
@RequestBody @Valid Domain domain,
@Parameter(description = "A list of oauth2 client registration ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")))
@RequestParam(name = "oauth2ClientIds", required = false) UUID[] ids) throws Exception {
domain.setTenantId(getCurrentUser().getTenantId());
domain.setTenantId(getTenantId());
checkEntity(domain.getId(), domain, Resource.DOMAIN);
return tbDomainService.save(domain, getOAuth2ClientIds(ids), getCurrentUser());
}
@ -100,7 +100,7 @@ public class DomainController extends BaseController {
@RequestParam int pageSize,
@Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true)
@RequestParam int page,
@Parameter(description = "Case-insensitive 'substring' filter based on rule's name")
@Parameter(description = "Case-insensitive 'substring' filter based on domain's name")
@RequestParam(required = false) String textSearch,
@Parameter(description = SORT_PROPERTY_DESCRIPTION)
@RequestParam(required = false) String sortProperty,
@ -119,7 +119,7 @@ public class DomainController extends BaseController {
}
@ApiOperation(value = "Delete Domain by ID (deleteDomain)",
notes = "Deletes Domain by ID. Referencing non-existing asset Id will cause an error." + SYSTEM_AUTHORITY_PARAGRAPH)
notes = "Deletes Domain by ID. Referencing non-existing domain Id will cause an error." + SYSTEM_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('SYS_ADMIN')")
@DeleteMapping(value = "/domain/{id}")
public void deleteDomain(@PathVariable UUID id) throws Exception {

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

@ -75,19 +75,19 @@ public class MobileAppController extends BaseController {
public MobileApp saveMobileApp(
@Parameter(description = "A JSON value representing the Mobile Application.", required = true)
@RequestBody @Valid MobileApp mobileApp,
@Parameter(description = "A list of entity group ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")))
@Parameter(description = "A list of entity oauth2 client ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")))
@RequestParam(name = "oauth2ClientIds", required = false) UUID[] ids) throws Exception {
mobileApp.setTenantId(getCurrentUser().getTenantId());
mobileApp.setTenantId(getTenantId());
checkEntity(mobileApp.getId(), mobileApp, Resource.MOBILE_APP);
return tbMobileAppService.save(mobileApp, getOAuth2ClientIds(ids), getCurrentUser());
}
@ApiOperation(value = "Update oauth2 clients (updateOauth2Clients)",
notes = "Update oauth2 clients to the specified mobile app. ")
notes = "Update oauth2 clients of the specified mobile app. ")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN')")
@PutMapping(value = "/mobileApp/{id}/oauth2Clients")
public void updateOauth2Clients(@PathVariable UUID id,
@RequestBody UUID[] clientIds) throws ThingsboardException {
@RequestBody UUID[] clientIds) throws ThingsboardException {
MobileAppId mobileAppId = new MobileAppId(id);
MobileApp mobileApp = checkMobileAppId(mobileAppId, Operation.WRITE);
List<OAuth2ClientId> oAuth2ClientIds = getOAuth2ClientIds(clientIds);
@ -101,15 +101,14 @@ public class MobileAppController extends BaseController {
@RequestParam int pageSize,
@Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true)
@RequestParam int page,
@Parameter(description = "Case-insensitive 'substring' filter based on rule's name")
@Parameter(description = "Case-insensitive 'substring' filter based on app's name")
@RequestParam(required = false) String textSearch,
@Parameter(description = SORT_PROPERTY_DESCRIPTION)
@RequestParam(required = false) String sortProperty,
@Parameter(description = SORT_ORDER_DESCRIPTION)
@RequestParam(required = false) String sortOrder) throws ThingsboardException {
TenantId tenantId = getCurrentUser().getTenantId();
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
return mobileAppService.findMobileAppInfosByTenantId(tenantId, pageLink);
return mobileAppService.findMobileAppInfosByTenantId(getTenantId(), pageLink);
}
@ApiOperation(value = "Get mobile info by id (getMobileAppInfoById)", notes = SYSTEM_AUTHORITY_PARAGRAPH)
@ -121,7 +120,7 @@ public class MobileAppController extends BaseController {
}
@ApiOperation(value = "Delete Mobile App by ID (deleteMobileApp)",
notes = "Deletes Mobile App by ID. Referencing non-existing asset Id will cause an error." + SYSTEM_AUTHORITY_PARAGRAPH)
notes = "Deletes Mobile App by ID. Referencing non-existing mobile app Id will cause an error." + SYSTEM_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('SYS_ADMIN')")
@DeleteMapping(value = "/mobileApp/{id}")
public void deleteMobileApp(@PathVariable UUID id) throws Exception {

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

@ -84,7 +84,7 @@ public class OAuth2Controller extends BaseController {
"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"}))
@RequestParam(required = false) String platform) throws ThingsboardException {
@RequestParam(required = false) String platform) {
if (log.isDebugEnabled()) {
log.debug("Executing getOAuth2Clients: [{}][{}][{}]", request.getScheme(), request.getServerName(), request.getServerPort());
Enumeration<String> headerNames = request.getHeaderNames();
@ -95,10 +95,7 @@ public class OAuth2Controller extends BaseController {
}
PlatformType platformType = null;
if (StringUtils.isNotEmpty(platform)) {
try {
platformType = PlatformType.valueOf(platform);
} catch (Exception e) {
}
platformType = PlatformType.valueOf(platform);
}
if (StringUtils.isNotEmpty(pkgName)) {
return oAuth2ClientService.findOAuth2ClientLoginInfosByMobilePkgNameAndPlatformType(pkgName, platformType);
@ -117,14 +114,14 @@ public class OAuth2Controller extends BaseController {
return tbOauth2ClientService.save(oAuth2Client, getCurrentUser());
}
@ApiOperation(value = "Get OAuth2 Client Registration infos (findTenantOAuth2ClientInfos)", notes = SYSTEM_AUTHORITY_PARAGRAPH)
@ApiOperation(value = "Get OAuth2 Client infos (findTenantOAuth2ClientInfos)", notes = SYSTEM_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('SYS_ADMIN')")
@GetMapping(value = "/oauth2/client/infos")
public PageData<OAuth2ClientInfo> findTenantOAuth2ClientInfos(@Parameter(description = PAGE_SIZE_DESCRIPTION, required = true)
@RequestParam int pageSize,
@Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true)
@RequestParam int page,
@Parameter(description = "Case-insensitive 'substring' filter based on rule's name")
@Parameter(description = "Case-insensitive 'substring' filter based on client's title")
@RequestParam(required = false) String textSearch,
@Parameter(description = SORT_PROPERTY_DESCRIPTION)
@RequestParam(required = false) String sortProperty,
@ -134,22 +131,21 @@ public class OAuth2Controller extends BaseController {
return oAuth2ClientService.findOAuth2ClientInfosByTenantId(getTenantId(), pageLink);
}
@ApiOperation(value = "Get OAuth2 Client Registration infos By Ids (findTenantOAuth2ClientInfosByIds)",
notes = "Fetch OAuth2 Client Registration info objects based on the provided ids. ")
@ApiOperation(value = "Get OAuth2 Client infos By Ids (findTenantOAuth2ClientInfosByIds)",
notes = "Fetch OAuth2 Client info objects based on the provided ids. ")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN')")
@GetMapping(value = "/oauth2/client/infos", params = {"clientIds"})
public List<OAuth2ClientInfo> findTenantOAuth2ClientInfosByIds(
@Parameter(description = "A list of oauth2 ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")), required = true)
@RequestParam("clientIds") String[] strClientIds) throws ThingsboardException {
checkArrayParameter("clientIds", strClientIds);
@RequestParam("clientIds") UUID[] clientIds) throws ThingsboardException {
List<OAuth2ClientId> oAuth2ClientIds = new ArrayList<>();
for (String oauth2ClientId : strClientIds) {
oAuth2ClientIds.add(new OAuth2ClientId(toUUID(oauth2ClientId)));
for (UUID oauth2ClientId : clientIds) {
oAuth2ClientIds.add(new OAuth2ClientId(oauth2ClientId));
}
return oAuth2ClientService.findOAuth2ClientInfosByIds(getTenantId(), oAuth2ClientIds);
}
@ApiOperation(value = "Get OAuth2 Client Registration by id (getOAuth2ClientById)", notes = SYSTEM_AUTHORITY_PARAGRAPH)
@ApiOperation(value = "Get OAuth2 Client by id (getOAuth2ClientById)", notes = SYSTEM_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('SYS_ADMIN')")
@GetMapping(value = "/oauth2/client/{id}")
public OAuth2Client getOAuth2ClientById(@PathVariable UUID id) throws ThingsboardException {
@ -157,8 +153,8 @@ public class OAuth2Controller extends BaseController {
return checkEntityId(oAuth2ClientId, oAuth2ClientService::findOAuth2ClientById, Operation.READ);
}
@ApiOperation(value = "Delete oauth2 client (deleteAsset)",
notes = "Deletes the asset and all the relations (from and to the asset). Referencing non-existing asset Id will cause an error." + SYSTEM_AUTHORITY_PARAGRAPH)
@ApiOperation(value = "Delete oauth2 client (deleteOauth2Client)",
notes = "Deletes the oauth2 client. Referencing non-existing oauth2 client Id will cause an error." + SYSTEM_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('SYS_ADMIN')")
@DeleteMapping(value = "/oauth2/client/{id}")
public void deleteOauth2Client(@PathVariable UUID id) throws Exception {

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

@ -16,9 +16,8 @@
package org.thingsboard.server.service.entitiy.domain;
import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.audit.ActionType;
@ -46,7 +45,7 @@ public class DefaultTbDomainService extends AbstractTbEntityService implements T
if (!CollectionUtils.isEmpty(oAuth2Clients)) {
domainService.updateOauth2Clients(domain.getTenantId(), savedDomain.getId(), oAuth2Clients);
}
logEntityActionService.logEntityAction(tenantId, savedDomain.getId(), domain, actionType, user, oAuth2Clients);
logEntityActionService.logEntityAction(tenantId, savedDomain.getId(), savedDomain, actionType, user, oAuth2Clients);
return savedDomain;
} catch (Exception e) {
logEntityActionService.logEntityAction(tenantId, emptyId(EntityType.DOMAIN), domain, actionType, user, e, oAuth2Clients);
@ -61,15 +60,14 @@ public class DefaultTbDomainService extends AbstractTbEntityService implements T
DomainId domainId = domain.getId();
try {
domainService.updateOauth2Clients(tenantId, domainId, oAuth2ClientIds);
logEntityActionService.logEntityAction(tenantId, domainId, domain, actionType, user, oAuth2ClientIds.toString());
logEntityActionService.logEntityAction(tenantId, domainId, domain, actionType, user, oAuth2ClientIds);
} catch (Exception e) {
logEntityActionService.logEntityAction(tenantId, domainId, domain, actionType, user, e, oAuth2ClientIds.toString());
logEntityActionService.logEntityAction(tenantId, domainId, domain, actionType, user, e, oAuth2ClientIds);
throw e;
}
}
@Override
@Transactional
public void delete(Domain domain, User user) {
ActionType actionType = ActionType.DELETED;
TenantId tenantId = domain.getTenantId();

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

@ -16,9 +16,8 @@
package org.thingsboard.server.service.entitiy.mobile;
import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.audit.ActionType;
@ -46,7 +45,7 @@ public class DefaultTbMobileAppService extends AbstractTbEntityService implement
if (!CollectionUtils.isEmpty(oauth2Clients)) {
mobileAppService.updateOauth2Clients(tenantId, savedMobileApp.getId(), oauth2Clients);
}
logEntityActionService.logEntityAction(tenantId, savedMobileApp.getId(), mobileApp, actionType, user);
logEntityActionService.logEntityAction(tenantId, savedMobileApp.getId(), savedMobileApp, actionType, user);
return savedMobileApp;
} catch (Exception e) {
logEntityActionService.logEntityAction(tenantId, emptyId(EntityType.MOBILE_APP), mobileApp, actionType, user, e);
@ -69,7 +68,6 @@ public class DefaultTbMobileAppService extends AbstractTbEntityService implement
}
@Override
@Transactional
public void delete(MobileApp mobileApp, User user) {
ActionType actionType = ActionType.DELETED;
TenantId tenantId = mobileApp.getTenantId();

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

@ -37,9 +37,9 @@ public class DefaultTbOauth2ClientService extends AbstractTbEntityService implem
ActionType actionType = oAuth2Client.getId() == null ? ActionType.ADDED : ActionType.UPDATED;
TenantId tenantId = oAuth2Client.getTenantId();
try {
OAuth2Client savedRegistration = checkNotNull(oAuth2ClientService.saveOAuth2Client(tenantId, oAuth2Client));
logEntityActionService.logEntityAction(tenantId, savedRegistration.getId(), oAuth2Client, actionType, user);
return savedRegistration;
OAuth2Client savedClient = checkNotNull(oAuth2ClientService.saveOAuth2Client(tenantId, oAuth2Client));
logEntityActionService.logEntityAction(tenantId, savedClient.getId(), savedClient, actionType, user);
return savedClient;
} catch (Exception e) {
logEntityActionService.logEntityAction(tenantId, emptyId(EntityType.OAUTH2_CLIENT), oAuth2Client, actionType, user, e);
throw e;

6
application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java

@ -149,7 +149,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
private final DeviceConnectivityConfiguration connectivityConfiguration;
private final QueueService queueService;
private final JwtSettingsService jwtSettingsService;
private final MobileAppDao oAuth2MobileDao;
private final MobileAppDao mobileAppDao;
private final NotificationSettingsService notificationSettingsService;
private final NotificationTargetService notificationTargetService;
@ -308,7 +308,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
jwtSettingsService.saveJwtSettings(jwtSettings);
}
List<MobileApp> mobiles = oAuth2MobileDao.findByTenantId(TenantId.SYS_TENANT_ID, new PageLink(Integer.MAX_VALUE,0)).getData();
List<MobileApp> mobiles = mobileAppDao.findByTenantId(TenantId.SYS_TENANT_ID, new PageLink(Integer.MAX_VALUE,0)).getData();
if (CollectionUtils.isNotEmpty(mobiles)) {
mobiles.stream()
.filter(config -> !validateKeyLength(config.getAppSecret()))
@ -318,7 +318,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
"You can change the Application Secret using the Web UI: " +
"Navigate to \"Security settings -> OAuth2 -> Mobile applications\" while logged in as a System Administrator.", config.getPkgName());
config.setAppSecret(generateRandomKey());
oAuth2MobileDao.save(TenantId.SYS_TENANT_ID, config);
mobileAppDao.save(TenantId.SYS_TENANT_ID, config);
});
}
}

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

@ -97,9 +97,9 @@ public abstract class AbstractOAuth2ClientMapper {
private final Lock userCreationLock = new ReentrantLock();
protected SecurityUser getOrCreateSecurityUserFromOAuth2User(OAuth2User oauth2User, OAuth2Client registration) {
protected SecurityUser getOrCreateSecurityUserFromOAuth2User(OAuth2User oauth2User, OAuth2Client oAuth2Client) {
OAuth2MapperConfig config = registration.getMapperConfig();
OAuth2MapperConfig config = oAuth2Client.getMapperConfig();
UserPrincipal principal = new UserPrincipal(UserPrincipal.Type.USER_NAME, oauth2User.getEmail());
@ -143,9 +143,9 @@ public abstract class AbstractOAuth2ClientMapper {
}
}
if (registration.getAdditionalInfo() != null &&
registration.getAdditionalInfo().has("providerName")) {
additionalInfo.put("authProviderName", registration.getAdditionalInfo().get("providerName").asText());
if (oAuth2Client.getAdditionalInfo() != null &&
oAuth2Client.getAdditionalInfo().has("providerName")) {
additionalInfo.put("authProviderName", oAuth2Client.getAdditionalInfo().get("providerName").asText());
}
user.setAdditionalInfo(additionalInfo);

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

@ -45,13 +45,13 @@ public class AppleOAuth2ClientMapper extends AbstractOAuth2ClientMapper implemen
private static final String EMAIL = "email";
@Override
public SecurityUser getOrCreateUserByClientPrincipal(HttpServletRequest request, OAuth2AuthenticationToken token, String providerAccessToken, OAuth2Client registration) {
OAuth2MapperConfig config = registration.getMapperConfig();
public SecurityUser getOrCreateUserByClientPrincipal(HttpServletRequest request, OAuth2AuthenticationToken token, String providerAccessToken, OAuth2Client oAuth2Client) {
OAuth2MapperConfig config = oAuth2Client.getMapperConfig();
Map<String, Object> attributes = updateAttributesFromRequestParams(request, token.getPrincipal().getAttributes());
String email = BasicMapperUtils.getStringAttributeByKey(attributes, config.getBasic().getEmailAttributeKey());
OAuth2User oauth2User = BasicMapperUtils.getOAuth2User(email, attributes, config);
return getOrCreateSecurityUserFromOAuth2User(oauth2User, registration);
return getOrCreateSecurityUserFromOAuth2User(oauth2User, oAuth2Client);
}
private static Map<String, Object> updateAttributesFromRequestParams(HttpServletRequest request, Map<String, Object> attributes) {

6
application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java

@ -1114,11 +1114,11 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest {
tbTenantProfileService.save(TenantId.SYS_TENANT_ID, tenantProfile, oldTenantProfile);
}
protected OAuth2Client validClientInfo(TenantId tenantId, String title) {
return validClientInfo(tenantId, title, null);
protected OAuth2Client createOauth2Client(TenantId tenantId, String title) {
return createOauth2Client(tenantId, title, null);
}
protected OAuth2Client validClientInfo(TenantId tenantId, String title, List<PlatformType> platforms) {
protected OAuth2Client createOauth2Client(TenantId tenantId, String title, List<PlatformType> platforms) {
OAuth2Client oAuth2Client = new OAuth2Client();
oAuth2Client.setTenantId(tenantId);
oAuth2Client.setTitle(title);

6
application/src/test/java/org/thingsboard/server/controller/DomainControllerTest.java

@ -98,10 +98,10 @@ public class DomainControllerTest extends AbstractControllerTest {
Domain domain = constructDomain(TenantId.SYS_TENANT_ID, "my.test.domain", true, true);
Domain savedDomain = doPost("/api/domain", domain, Domain.class);
OAuth2Client oAuth2Client = validClientInfo(TenantId.SYS_TENANT_ID, "test google client");
OAuth2Client oAuth2Client = createOauth2Client(TenantId.SYS_TENANT_ID, "test google client");
OAuth2Client savedOAuth2Client = doPost("/api/oauth2/client", oAuth2Client, OAuth2Client.class);
OAuth2Client oAuth2Client2 = validClientInfo(TenantId.SYS_TENANT_ID, "test facebook client");
OAuth2Client oAuth2Client2 = createOauth2Client(TenantId.SYS_TENANT_ID, "test facebook client");
OAuth2Client savedOAuth2Client2 = doPost("/api/oauth2/client", oAuth2Client2, OAuth2Client.class);
doPut("/api/domain/" + savedDomain.getId() + "/oauth2Clients", List.of(savedOAuth2Client.getId().getId(), savedOAuth2Client2.getId().getId()));
@ -117,7 +117,7 @@ public class DomainControllerTest extends AbstractControllerTest {
@Test
public void testCreateDomainWithOauth2Clients() throws Exception {
OAuth2Client oAuth2Client = validClientInfo(TenantId.SYS_TENANT_ID, "test google client");
OAuth2Client oAuth2Client = createOauth2Client(TenantId.SYS_TENANT_ID, "test google client");
OAuth2Client savedOAuth2Client = doPost("/api/oauth2/client", oAuth2Client, OAuth2Client.class);
Domain domain = constructDomain(TenantId.SYS_TENANT_ID, "my.test.domain", true, true);

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

@ -360,7 +360,7 @@ public class HomePageApiTest extends AbstractControllerTest {
Assert.assertTrue(featuresInfo.isNotificationEnabled());
Assert.assertFalse(featuresInfo.isOauthEnabled());
OAuth2Client oAuth2Client = validClientInfo(TenantId.SYS_TENANT_ID, "test google client");
OAuth2Client oAuth2Client = createOauth2Client(TenantId.SYS_TENANT_ID, "test google client");
OAuth2Client savedOAuth2Client = doPost("/api/oauth2/client", oAuth2Client, OAuth2Client.class);
Domain domain = createDomain(TenantId.SYS_TENANT_ID, "my.test.domain", true, true);

6
application/src/test/java/org/thingsboard/server/controller/MobileAppControllerTest.java

@ -100,10 +100,10 @@ public class MobileAppControllerTest extends AbstractControllerTest {
MobileApp mobileApp = validMobileApp(TenantId.SYS_TENANT_ID, "my.test.package", true);
MobileApp savedMobileApp = doPost("/api/mobileApp", mobileApp, MobileApp.class);
OAuth2Client oAuth2Client = validClientInfo(TenantId.SYS_TENANT_ID, "test google client");
OAuth2Client oAuth2Client = createOauth2Client(TenantId.SYS_TENANT_ID, "test google client");
OAuth2Client savedOAuth2Client = doPost("/api/oauth2/client", oAuth2Client, OAuth2Client.class);
OAuth2Client oAuth2Client2 = validClientInfo(TenantId.SYS_TENANT_ID, "test facebook client");
OAuth2Client oAuth2Client2 = createOauth2Client(TenantId.SYS_TENANT_ID, "test facebook client");
OAuth2Client savedOAuth2Client2 = doPost("/api/oauth2/client", oAuth2Client2, OAuth2Client.class);
doPut("/api/mobileApp/" + savedMobileApp.getId() + "/oauth2Clients", List.of(savedOAuth2Client.getId().getId(), savedOAuth2Client2.getId().getId()));
@ -119,7 +119,7 @@ public class MobileAppControllerTest extends AbstractControllerTest {
@Test
public void testCreateMobileAppWithOauth2Clients() throws Exception {
OAuth2Client oAuth2Client = validClientInfo(TenantId.SYS_TENANT_ID, "test google client");
OAuth2Client oAuth2Client = createOauth2Client(TenantId.SYS_TENANT_ID, "test google client");
OAuth2Client savedOAuth2Client = doPost("/api/oauth2/client", oAuth2Client, OAuth2Client.class);
MobileApp mobileApp = validMobileApp(TenantId.SYS_TENANT_ID, "my.test.package", true);

2
application/src/test/java/org/thingsboard/server/controller/Oauth2ClientControllerTest.java

@ -57,7 +57,7 @@ public class Oauth2ClientControllerTest extends AbstractControllerTest {
PageData<OAuth2ClientInfo> pageData = doGetTypedWithPageLink("/api/oauth2/client/infos?", PAGE_DATA_OAUTH2_CLIENT_TYPE_REF, new PageLink(10, 0));
assertThat(pageData.getData()).isEmpty();
OAuth2Client oAuth2Client = validClientInfo(TenantId.SYS_TENANT_ID, "test google client");
OAuth2Client oAuth2Client = createOauth2Client(TenantId.SYS_TENANT_ID, "test google client");
OAuth2Client savedOAuth2Client = doPost("/api/oauth2/client", oAuth2Client, OAuth2Client.class);
PageData<OAuth2ClientInfo> pageData2 = doGetTypedWithPageLink("/api/oauth2/client/infos?", PAGE_DATA_OAUTH2_CLIENT_TYPE_REF, new PageLink(10, 0));

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

@ -40,7 +40,7 @@ public interface OAuth2ClientService extends EntityDaoService {
OAuth2Client findOAuth2ClientById(TenantId tenantId, OAuth2ClientId providerId);
String findAppSecret(UUID registrationId, String pkgName);
String findAppSecret(OAuth2ClientId oAuth2ClientId, String pkgName);
void deleteOAuth2ClientById(TenantId tenantId, OAuth2ClientId oAuth2ClientId);

2
common/data/src/main/java/org/thingsboard/server/common/data/domain/DomainOauth2Client.java

@ -17,6 +17,7 @@ package org.thingsboard.server.common.data.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.thingsboard.server.common.data.id.DomainId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
@ -24,6 +25,7 @@ import org.thingsboard.server.common.data.id.OAuth2ClientId;
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
public class DomainOauth2Client {
private DomainId domainId;

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

@ -28,7 +28,7 @@ import java.util.List;
@Schema
public class MobileAppInfo extends MobileApp {
@Schema(description = "List of available oauth2 client registrations")
@Schema(description = "List of available oauth2 clients")
private List<OAuth2ClientInfo> oauth2ClientInfos;
public MobileAppInfo(MobileApp mobileApp, List<OAuth2ClientInfo> oauth2ClientInfos) {

4
common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2Client.java

@ -29,6 +29,7 @@ import org.thingsboard.server.common.data.HasName;
import org.thingsboard.server.common.data.HasTenantId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.validation.Length;
import java.util.List;
@ -41,6 +42,7 @@ public class OAuth2Client extends BaseDataWithAdditionalInfo<OAuth2ClientId> imp
private TenantId tenantId;
@Schema(description = "Oauth2 client title")
@NotBlank
@Length(max = 100, message = "cannot be longer than 100 chars")
private String title;
@Schema(description = "Config for mapping OAuth2 log in response to platform entities", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull
@ -110,6 +112,6 @@ public class OAuth2Client extends BaseDataWithAdditionalInfo<OAuth2ClientId> imp
@Override
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
public String getName() {
return loginButtonLabel;
return title;
}
}

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

@ -16,6 +16,7 @@
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 lombok.Data;
import lombok.EqualsAndHashCode;
@ -49,9 +50,7 @@ public class OAuth2ClientInfo extends BaseData<OAuth2ClientId> implements HasNam
public OAuth2ClientInfo(OAuth2Client oAuth2Client) {
super(oAuth2Client);
this.title = oAuth2Client.getTitle();
if (oAuth2Client.getAdditionalInfo() != null && oAuth2Client.getAdditionalInfo().has("providerName")) {
this.providerName = oAuth2Client.getAdditionalInfo().get("providerName").asText();
}
this.providerName = oAuth2Client.getAdditionalInfoField("providerName", JsonNode::asText,"");
this.platforms = oAuth2Client.getPlatforms();
}

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

@ -18,7 +18,6 @@ package org.thingsboard.server.dao.domain;
import org.thingsboard.server.common.data.domain.Domain;
import org.thingsboard.server.common.data.domain.DomainOauth2Client;
import org.thingsboard.server.common.data.id.DomainId;
import org.thingsboard.server.common.data.id.OAuth2ClientId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
@ -34,9 +33,9 @@ public interface DomainDao extends Dao<Domain> {
List<DomainOauth2Client> findOauth2ClientsByDomainId(TenantId tenantId, DomainId domainId);
void saveOauth2Clients(DomainOauth2Client domainOauth2Client);
void addOauth2Client(DomainOauth2Client domainOauth2Client);
void removeOauth2Clients(DomainId domainId, OAuth2ClientId oAuth2ClientId);
void removeOauth2Client(DomainOauth2Client domainOauth2Client);
void deleteByTenantId(TenantId tenantId);
}

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

@ -16,11 +16,9 @@
package org.thingsboard.server.dao.domain;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.exception.ConstraintViolationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
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;
@ -36,24 +34,21 @@ import org.thingsboard.server.common.data.page.PageLink;
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.OAuth2ClientDao;
import org.thingsboard.server.dao.service.Validator;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import static org.thingsboard.server.dao.service.Validator.validateIds;
import static org.thingsboard.server.dao.service.Validator.validateId;
@Slf4j
@Service
public class DomainServiceImpl extends AbstractEntityService implements DomainService {
public static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
public static final String INCORRECT_DOMAIN_ID = "Incorrect domainId ";
@Autowired
private OAuth2ClientDao oauth2ClientDao;
@ -67,39 +62,31 @@ public class DomainServiceImpl extends AbstractEntityService implements DomainSe
Domain savedDomain = domainDao.save(tenantId, domain);
eventPublisher.publishEvent(SaveEntityEvent.builder().tenantId(tenantId).entity(savedDomain).build());
return savedDomain;
} catch (Exception t) {
ConstraintViolationException e = extractConstraintViolationException(t).orElse(null);
if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("domain_unq_key")) {
throw new DataValidationException("Domain with such name and scheme already exists!");
} else {
throw t;
}
} catch (Exception e) {
checkConstraintViolation(e,
Map.of("domain_unq_key", "Domain with such name and scheme already exists!"));
throw e;
}
}
@Override
public void updateOauth2Clients(TenantId tenantId, DomainId domainId, List<OAuth2ClientId> oAuth2ClientIds) {
log.trace("Executing updateOauth2Clients, domainId [{}], oAuth2ClientIds [{}]", domainId, oAuth2ClientIds);
Validator.validateId(tenantId, id -> INCORRECT_TENANT_ID + id);
Validator.validateId(domainId, id -> INCORRECT_DOMAIN_ID + id);
Validator.checkNotNull(oAuth2ClientIds, "Incorrect oAuth2ClientIds " + oAuth2ClientIds);
if (!oAuth2ClientIds.isEmpty()) {
validateIds(oAuth2ClientIds, ids -> "Incorrect oAuth2ClientIds " + ids);
}
List<DomainOauth2Client> oauth2Clients = new ArrayList<>();
for (OAuth2ClientId oAuth2ClientId : oAuth2ClientIds) {
oauth2Clients.add(new DomainOauth2Client(domainId, oAuth2ClientId));
}
Set<DomainOauth2Client> newClientList = oAuth2ClientIds.stream()
.map(clientId -> new DomainOauth2Client(domainId, clientId))
.collect(Collectors.toSet());
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 (OAuth2ClientId clientId : toRemove) {
domainDao.removeOauth2Clients(domainId, clientId);
List<DomainOauth2Client> toRemoveList = existingClients.stream()
.filter(client -> !newClientList.contains(client))
.toList();
newClientList.removeIf(existingClients::contains);
for (DomainOauth2Client client : toRemoveList) {
domainDao.removeOauth2Client(client);
}
for (DomainOauth2Client domainOauth2Client : oauth2Clients) {
domainDao.saveOauth2Clients(domainOauth2Client);
for (DomainOauth2Client client : newClientList) {
domainDao.addOauth2Client(client);
}
eventPublisher.publishEvent(SaveEntityEvent.builder().tenantId(tenantId)
.entityId(domainId).created(false).build());
@ -121,26 +108,15 @@ public class DomainServiceImpl extends AbstractEntityService implements DomainSe
@Override
public PageData<DomainInfo> findDomainInfosByTenantId(TenantId tenantId, PageLink pageLink) {
log.trace("Executing findDomainInfosByTenantId [{}]", tenantId);
PageData<Domain> pageData = domainDao.findByTenantId(tenantId, pageLink);
List<DomainInfo> domainInfos = new ArrayList<>();
for (Domain domain : pageData.getData()) {
domainInfos.add(new DomainInfo(domain, oauth2ClientDao.findByDomainId(domain.getUuidId()).stream()
.map(OAuth2ClientInfo::new)
.collect(Collectors.toList())));
}
return new PageData<>(domainInfos, pageData.getTotalPages(), pageData.getTotalElements(), pageData.hasNext());
PageData<Domain> domains = domainDao.findByTenantId(tenantId, pageLink);
return domains.mapData(this::getDomainInfo);
}
@Override
public DomainInfo findDomainInfoById(TenantId tenantId, DomainId domainId) {
log.trace("Executing findDomainInfoById [{}] [{}]", tenantId, domainId);
Domain domain = domainDao.findById(tenantId, domainId.getId());
if (domain == null) {
return null;
}
return new DomainInfo(domain, oauth2ClientDao.findByDomainId(domain.getUuidId()).stream()
.map(OAuth2ClientInfo::new)
.collect(Collectors.toList()));
return getDomainInfo(domain);
}
@Override
@ -152,7 +128,7 @@ public class DomainServiceImpl extends AbstractEntityService implements DomainSe
@Override
public void deleteDomainsByTenantId(TenantId tenantId) {
log.trace("Executing deleteDomainsByTenantId, tenantId [{}]", tenantId);
Validator.validateId(tenantId, id -> INCORRECT_TENANT_ID + id);
validateId(tenantId, id -> INCORRECT_TENANT_ID + id);
domainDao.deleteByTenantId(tenantId);
}
@ -166,18 +142,24 @@ public class DomainServiceImpl extends AbstractEntityService implements DomainSe
return Optional.ofNullable(findDomainById(tenantId, new DomainId(entityId.getId())));
}
@Override
public EntityType getEntityType() {
return EntityType.DOMAIN;
}
@Override
@Transactional
public void deleteEntity(TenantId tenantId, EntityId id, boolean force) {
Domain domain = domainDao.findById(tenantId, id.getId());
deleteDomainById(tenantId, (DomainId) id);
}
private DomainInfo getDomainInfo(Domain domain) {
if (domain == null) {
return;
return null;
}
deleteDomainById(tenantId, domain.getId());
List<OAuth2ClientInfo> clients = oauth2ClientDao.findByDomainId(domain.getUuidId()).stream()
.map(OAuth2ClientInfo::new)
.collect(Collectors.toList());
return new DomainInfo(domain, clients);
}
@Override
public EntityType getEntityType() {
return EntityType.DOMAIN;
}
}

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

@ -32,9 +32,9 @@ public interface MobileAppDao extends Dao<MobileApp> {
List<MobileAppOauth2Client> findOauth2ClientsByMobileAppId(TenantId tenantId, MobileAppId mobileAppId);
void saveOauth2Clients(MobileAppOauth2Client mobileAppOauth2Client);
void addOauth2Client(MobileAppOauth2Client mobileAppOauth2Client);
void removeOauth2Clients(MobileAppId mobileAppId, OAuth2ClientId oAuth2ClientId);
void removeOauth2Client(MobileAppOauth2Client mobileAppOauth2Client);
void deleteByTenantId(TenantId tenantId);
}

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

@ -39,20 +39,16 @@ import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.oauth2.OAuth2ClientDao;
import org.thingsboard.server.dao.service.Validator;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import static org.thingsboard.server.dao.service.Validator.validateIds;
@Slf4j
@Service
public class MobileAppServiceImpl extends AbstractEntityService implements MobileAppService {
public static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
public static final String INCORRECT_MOBILE_APP_ID = "Incorrect mobileApppId ";
@Autowired
private OAuth2ClientDao oauth2ClientDao;
@ -92,14 +88,8 @@ public class MobileAppServiceImpl extends AbstractEntityService implements Mobil
@Override
public PageData<MobileAppInfo> findMobileAppInfosByTenantId(TenantId tenantId, PageLink pageLink) {
log.trace("Executing findMobileAppInfosByTenantId [{}]", tenantId);
PageData<MobileApp> pageData = mobileAppDao.findByTenantId(tenantId, pageLink);
List<MobileAppInfo> mobileAppInfos = new ArrayList<>();
for (MobileApp mobileApp : pageData.getData()) {
mobileAppInfos.add(new MobileAppInfo(mobileApp, oauth2ClientDao.findByMobileAppId(mobileApp.getUuidId()).stream()
.map(OAuth2ClientInfo::new)
.collect(Collectors.toList())));
}
return new PageData<>(mobileAppInfos, pageData.getTotalPages(), pageData.getTotalElements(), pageData.hasNext());
PageData<MobileApp> mobiles = mobileAppDao.findByTenantId(tenantId, pageLink);
return mobiles.mapData(this::getMobileAppInfo);
}
@Override
@ -109,34 +99,27 @@ public class MobileAppServiceImpl extends AbstractEntityService implements Mobil
if (mobileApp == null) {
return null;
}
return new MobileAppInfo(mobileApp, oauth2ClientDao.findByMobileAppId(mobileApp.getUuidId()).stream()
.map(OAuth2ClientInfo::new)
.collect(Collectors.toList()));
return getMobileAppInfo(mobileApp);
}
@Override
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);
Validator.checkNotNull(oAuth2ClientIds, "Incorrect oAuth2ClientIds " + oAuth2ClientIds);
if (!oAuth2ClientIds.isEmpty()) {
validateIds(oAuth2ClientIds, ids -> "Incorrect oAuth2ClientIds " + ids);
}
List<MobileAppOauth2Client> oauth2Clients = new ArrayList<>();
for (OAuth2ClientId oAuth2ClientId : oAuth2ClientIds) {
oauth2Clients.add(new MobileAppOauth2Client(mobileAppId, oAuth2ClientId));
}
Set<MobileAppOauth2Client> newClientList = oAuth2ClientIds.stream()
.map(clientId -> new MobileAppOauth2Client(mobileAppId, clientId))
.collect(Collectors.toSet());
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 (OAuth2ClientId clientId : toRemove) {
mobileAppDao.removeOauth2Clients(mobileAppId, clientId);
List<MobileAppOauth2Client> toRemoveList = existingClients.stream()
.filter(client -> !newClientList.contains(client))
.toList();
newClientList.removeIf(existingClients::contains);
for (MobileAppOauth2Client client : toRemoveList) {
mobileAppDao.removeOauth2Client(client);
}
for (MobileAppOauth2Client mobileAppOauth2Client : oauth2Clients) {
mobileAppDao.saveOauth2Clients(mobileAppOauth2Client);
for (MobileAppOauth2Client client : newClientList) {
mobileAppDao.addOauth2Client(client);
}
eventPublisher.publishEvent(SaveEntityEvent.builder().tenantId(tenantId)
.entityId(mobileAppId).created(false).build());
@ -147,19 +130,10 @@ public class MobileAppServiceImpl extends AbstractEntityService implements Mobil
return Optional.ofNullable(findMobileAppById(tenantId, new MobileAppId(entityId.getId())));
}
@Override
public EntityType getEntityType() {
return EntityType.MOBILE_APP;
}
@Override
@Transactional
public void deleteEntity(TenantId tenantId, EntityId id, boolean force) {
MobileApp mobileApp = mobileAppDao.findById(tenantId, id.getId());
if (mobileApp == null) {
return;
}
deleteMobileAppById(tenantId, mobileApp.getId());
deleteMobileAppById(tenantId, (MobileAppId) id);
}
@Override
@ -173,4 +147,16 @@ public class MobileAppServiceImpl extends AbstractEntityService implements Mobil
public void deleteByTenantId(TenantId tenantId) {
deleteMobileAppsByTenantId(tenantId);
}
private MobileAppInfo getMobileAppInfo(MobileApp mobileApp) {
List<OAuth2ClientInfo> clients = oauth2ClientDao.findByMobileAppId(mobileApp.getUuidId()).stream()
.map(OAuth2ClientInfo::new)
.collect(Collectors.toList());
return new MobileAppInfo(mobileApp, clients);
}
@Override
public EntityType getEntityType() {
return EntityType.MOBILE_APP;
}
}

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

@ -427,7 +427,7 @@ public class ModelConstants {
* Domain constants.
*/
public static final String DOMAIN_TABLE_NAME = "domain";
public static final String DOMAIN_DOMAIN_NAME_PROPERTY = "domain_name";
public static final String DOMAIN_NAME_PROPERTY = "name";
public static final String DOMAIN_OAUTH2_ENABLED_PROPERTY = "oauth2_enabled";
public static final String DOMAIN_PROPAGATE_TO_EDGE_PROPERTY = "edge_enabled";
@ -449,7 +449,7 @@ public class ModelConstants {
/**
* OAuth2 client registration constants.
* OAuth2 client constants.
*/
public static final String OAUTH2_CLIENT_TABLE_NAME = "oauth2_client";
public static final String OAUTH2_CLIENT_REGISTRATION_TEMPLATE_TABLE_NAME = "oauth2_client_registration_template";

2
dao/src/main/java/org/thingsboard/server/dao/model/sql/DomainEntity.java

@ -39,7 +39,7 @@ public class DomainEntity extends BaseSqlEntity<Domain> {
@Column(name = TENANT_ID_COLUMN)
private UUID tenantId;
@Column(name = ModelConstants.DOMAIN_DOMAIN_NAME_PROPERTY)
@Column(name = ModelConstants.DOMAIN_NAME_PROPERTY)
private String name;
@Column(name = ModelConstants.DOMAIN_OAUTH2_ENABLED_PROPERTY)

4
dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientDao.java

@ -36,11 +36,11 @@ public interface OAuth2ClientDao extends Dao<OAuth2Client> {
List<OAuth2Client> findByDomainId(UUID domainId);
List<OAuth2Client> findByMobileAppId(UUID domainId);
List<OAuth2Client> findByMobileAppId(UUID mobileAppId);
String findAppSecret(UUID id, String pkgName);
void deleteByTenantId(TenantId tenantId);
void deleteByTenantId(UUID tenantId);
List<OAuth2Client> findByIds(TenantId tenantId, List<OAuth2ClientId> oAuth2ClientIds);
}

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

@ -101,11 +101,11 @@ public class OAuth2ClientServiceImpl extends AbstractEntityService implements OA
}
@Override
public String findAppSecret(UUID id, String pkgName) {
log.trace("Executing findAppSecret [{}][{}]", id, pkgName);
validateId(id, uuid -> INCORRECT_CLIENT_REGISTRATION_ID + uuid);
public String findAppSecret(OAuth2ClientId oAuth2ClientId, String pkgName) {
log.trace("Executing findAppSecret [{}][{}]", oAuth2ClientId, pkgName);
validateId(oAuth2ClientId, uuid -> INCORRECT_CLIENT_REGISTRATION_ID + uuid);
validateString(pkgName, "Incorrect package name");
return oauth2ClientDao.findAppSecret(id, pkgName);
return oauth2ClientDao.findAppSecret(oAuth2ClientId.getId(), pkgName);
}
@Override
@ -124,19 +124,14 @@ public class OAuth2ClientServiceImpl extends AbstractEntityService implements OA
public void deleteOauth2ClientsByTenantId(TenantId tenantId) {
log.trace("Executing deleteOauth2ClientsByTenantId, tenantId [{}]", tenantId);
Validator.validateId(tenantId, id -> INCORRECT_TENANT_ID + id);
oauth2ClientDao.deleteByTenantId(tenantId);
oauth2ClientDao.deleteByTenantId(tenantId.getId());
}
@Override
public PageData<OAuth2ClientInfo> findOAuth2ClientInfosByTenantId(TenantId tenantId, PageLink pageLink) {
log.trace("Executing findOAuth2ClientInfosByTenantId tenantId=[{}]", tenantId);
PageData<OAuth2Client> clientInfos = oauth2ClientDao.findByTenantId(tenantId.getId(), pageLink);
List<OAuth2ClientInfo> oAuth2ClientInfos = clientInfos
.getData()
.stream()
.map(OAuth2ClientInfo::new)
.collect(Collectors.toList());
return new PageData<>(oAuth2ClientInfos, clientInfos.getTotalPages(), clientInfos.getTotalPages(), clientInfos.hasNext());
PageData<OAuth2Client> clients = oauth2ClientDao.findByTenantId(tenantId.getId(), pageLink);
return clients.mapData(OAuth2ClientInfo::new);
}
@Override
@ -163,11 +158,7 @@ public class OAuth2ClientServiceImpl extends AbstractEntityService implements OA
@Override
@Transactional
public void deleteEntity(TenantId tenantId, EntityId id, boolean force) {
OAuth2Client oAuth2Client = oauth2ClientDao.findById(tenantId, id.getId());
if (oAuth2Client == null) {
return;
}
deleteOAuth2ClientById(tenantId, oAuth2Client.getId());
deleteOAuth2ClientById(tenantId, (OAuth2ClientId) id);
}
@Override

3
dao/src/main/java/org/thingsboard/server/dao/sql/domain/DomainOauth2ClientRepository.java

@ -16,7 +16,6 @@
package org.thingsboard.server.dao.sql.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.query.Param;
import org.thingsboard.server.dao.model.sql.DomainOauth2ClientCompositeKey;
import org.thingsboard.server.dao.model.sql.DomainOauth2ClientEntity;
@ -25,6 +24,6 @@ import java.util.UUID;
public interface DomainOauth2ClientRepository extends JpaRepository<DomainOauth2ClientEntity, DomainOauth2ClientCompositeKey> {
List<DomainOauth2ClientEntity> findAllByDomainId(@Param("domainId") UUID domainId);
List<DomainOauth2ClientEntity> findAllByDomainId(UUID domainId);
}

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

@ -39,6 +39,6 @@ public interface DomainRepository extends JpaRepository<DomainEntity, UUID> {
@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);
int countByTenantIdAndOauth2Enabled(UUID tenantId, boolean oauth2Enabled);
}

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

@ -71,13 +71,14 @@ public class JpaDomainDao extends JpaAbstractDao<DomainEntity, Domain> implement
}
@Override
public void saveOauth2Clients(DomainOauth2Client domainOauth2Client) {
public void addOauth2Client(DomainOauth2Client domainOauth2Client) {
domainOauth2ClientRepository.save(new DomainOauth2ClientEntity(domainOauth2Client));
}
@Override
public void removeOauth2Clients(DomainId domainId, OAuth2ClientId oAuth2ClientId) {
domainOauth2ClientRepository.deleteById(new DomainOauth2ClientCompositeKey(domainId.getId(), oAuth2ClientId.getId()));
public void removeOauth2Client(DomainOauth2Client domainOauth2Client) {
domainOauth2ClientRepository.deleteById(new DomainOauth2ClientCompositeKey(domainOauth2Client.getDomainId().getId(),
domainOauth2Client.getOAuth2ClientId().getId()));
}
@Override

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

@ -20,7 +20,6 @@ import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.id.MobileAppId;
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.MobileAppOauth2Client;
@ -62,17 +61,18 @@ public class JpaMobileAppDao extends JpaAbstractDao<MobileAppEntity, MobileApp>
@Override
public List<MobileAppOauth2Client> findOauth2ClientsByMobileAppId(TenantId tenantId, MobileAppId mobileAppId) {
return DaoUtil.convertDataList(mobileOauth2ProviderRepository.findAllByMobileAppId(mobileAppId.getId()));
return DaoUtil.convertDataList(mobileOauth2ProviderRepository.findAllByMobileAppId(mobileAppId.getId()));
}
@Override
public void saveOauth2Clients(MobileAppOauth2Client mobileAppOauth2Client) {
public void addOauth2Client(MobileAppOauth2Client mobileAppOauth2Client) {
mobileOauth2ProviderRepository.save(new MobileAppOauth2ClientEntity(mobileAppOauth2Client));
}
@Override
public void removeOauth2Clients(MobileAppId mobileAppId, OAuth2ClientId oAuth2ClientId) {
mobileOauth2ProviderRepository.deleteById(new MobileAppOauth2ClientCompositeKey(mobileAppId.getId(), oAuth2ClientId.getId()));
public void removeOauth2Client(MobileAppOauth2Client mobileAppOauth2Client) {
mobileOauth2ProviderRepository.deleteById(new MobileAppOauth2ClientCompositeKey(mobileAppOauth2Client.getMobileAppId().getId(),
mobileAppOauth2Client.getOAuth2ClientId().getId()));
}
@Override

3
dao/src/main/java/org/thingsboard/server/dao/sql/mobile/MobileAppOauth2ClientRepository.java

@ -16,7 +16,6 @@
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.dao.model.sql.MobileAppOauth2ClientCompositeKey;
import org.thingsboard.server.dao.model.sql.MobileAppOauth2ClientEntity;
@ -25,6 +24,6 @@ import java.util.UUID;
public interface MobileAppOauth2ClientRepository extends JpaRepository<MobileAppOauth2ClientEntity, MobileAppOauth2ClientCompositeKey> {
List<MobileAppOauth2ClientEntity> findAllByMobileAppId(@Param("mobileAppId") UUID mobileAppId);
List<MobileAppOauth2ClientEntity> findAllByMobileAppId(UUID mobileAppId);
}

6
dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ClientDao.java

@ -66,7 +66,7 @@ public class JpaOAuth2ClientDao extends JpaAbstractDao<OAuth2ClientEntity, OAuth
@Override
public List<OAuth2Client> findEnabledByPckNameAndPlatformType(String pkgName, PlatformType platformType) {
return DaoUtil.convertDataList(repository.findEnabledByPkgNameAndPlatformType(pkgName,
platformType != null ? "%" + platformType.name() + "%" : null));
platformType != null ? platformType.name() : null));
}
@Override
@ -85,8 +85,8 @@ public class JpaOAuth2ClientDao extends JpaAbstractDao<OAuth2ClientEntity, OAuth
}
@Override
public void deleteByTenantId(TenantId tenantId) {
repository.deleteByTenantId(tenantId.getId());
public void deleteByTenantId(UUID tenantId) {
repository.deleteByTenantId(tenantId);
}
@Override

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

@ -39,7 +39,7 @@ public interface OAuth2ClientRepository extends JpaRepository<OAuth2ClientEntity
"FROM OAuth2ClientEntity c " +
"LEFT JOIN DomainOauth2ClientEntity dc on c.id = dc.oauth2ClientId " +
"LEFT JOIN DomainEntity domain on dc.domainId = domain.id " +
"WHERE domain.name = :domainName " +
"WHERE domain.name = :domainName AND domain.oauth2Enabled = true " +
"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);
@ -48,8 +48,8 @@ public interface OAuth2ClientRepository extends JpaRepository<OAuth2ClientEntity
"FROM OAuth2ClientEntity c " +
"LEFT JOIN MobileAppOauth2ClientEntity mc on c.id = mc.oauth2ClientId " +
"LEFT JOIN MobileAppEntity app on mc.mobileAppId = app.id " +
"WHERE app.pkgName = :pkgName " +
"AND (:platformFilter IS NULL OR c.platforms IS NULL OR c.platforms = '' OR c.platforms LIKE :platformFilter)")
"WHERE app.pkgName = :pkgName AND app.oauth2Enabled = true " +
"AND (:platformFilter IS NULL OR c.platforms IS NULL OR c.platforms = '' OR ilike(c.platforms, CONCAT('%', :platformFilter, '%')) = true)")
List<OAuth2ClientEntity> findEnabledByPkgNameAndPlatformType(@Param("pkgName") String pkgName,
@Param("platformFilter") String platformFilter);
@ -79,6 +79,6 @@ public interface OAuth2ClientRepository extends JpaRepository<OAuth2ClientEntity
@Query("DELETE FROM OAuth2ClientEntity t WHERE t.tenantId = :tenantId")
void deleteByTenantId(@Param("tenantId") UUID tenantId);
List<OAuth2ClientEntity> findByTenantIdAndIdIn(UUID tenantId, List<UUID> queueStatsIds);
List<OAuth2ClientEntity> findByTenantIdAndIdIn(UUID tenantId, List<UUID> uuids);
}

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

@ -177,6 +177,7 @@ public class TenantServiceImpl extends AbstractCachedEntityService<TenantId, Ten
EntityType.DASHBOARD, EntityType.EDGE, EntityType.RULE_CHAIN, EntityType.API_USAGE_STATE,
EntityType.TB_RESOURCE, EntityType.OTA_PACKAGE, EntityType.RPC, EntityType.QUEUE,
EntityType.NOTIFICATION_REQUEST, EntityType.NOTIFICATION_RULE, EntityType.NOTIFICATION_TEMPLATE,
EntityType.NOTIFICATION_TARGET, EntityType.QUEUE_STATS, EntityType.CUSTOMER,
EntityType.DOMAIN, EntityType.MOBILE_APP, EntityType.OAUTH2_CLIENT
);
}

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

@ -597,7 +597,7 @@ CREATE TABLE IF NOT EXISTS domain (
id uuid NOT NULL CONSTRAINT domain_pkey PRIMARY KEY,
created_time bigint NOT NULL,
tenant_id uuid NOT NULL,
domain_name varchar(255) UNIQUE,
name varchar(255) UNIQUE,
oauth2_enabled boolean,
edge_enabled boolean
);

Loading…
Cancel
Save