diff --git a/application/src/main/data/upgrade/3.7.0/schema_update.sql b/application/src/main/data/upgrade/3.7.0/schema_update.sql index dce84e3a40..5bb1a61f28 100644 --- a/application/src/main/data/upgrade/3.7.0/schema_update.sql +++ b/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 $$; diff --git a/application/src/main/java/org/thingsboard/server/config/CustomOAuth2AuthorizationRequestResolver.java b/application/src/main/java/org/thingsboard/server/config/CustomOAuth2AuthorizationRequestResolver.java index 2dd5027a2a..542a7c71cb 100644 --- a/application/src/main/java/org/thingsboard/server/config/CustomOAuth2AuthorizationRequestResolver.java +++ b/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 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."); } diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index f45e687b8d..7750376a75 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -901,9 +901,11 @@ public abstract class BaseController { } protected List getOAuth2ClientIds(UUID[] ids) throws ThingsboardException { - List oauth2ClientIds = ids != null ? Arrays.asList(ids) : Collections.emptyList(); + if (ids == null) { + return Collections.emptyList(); + } List oAuth2ClientIds = new ArrayList<>(); - for (UUID id : oauth2ClientIds) { + for (UUID id : ids) { OAuth2ClientId oauth2ClientId = new OAuth2ClientId(id); checkOauth2ClientId(oauth2ClientId, Operation.READ); oAuth2ClientIds.add(oauth2ClientId); diff --git a/application/src/main/java/org/thingsboard/server/controller/DomainController.java b/application/src/main/java/org/thingsboard/server/controller/DomainController.java index 79326f56bc..fa1f639281 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DomainController.java +++ b/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 { diff --git a/application/src/main/java/org/thingsboard/server/controller/MobileAppController.java b/application/src/main/java/org/thingsboard/server/controller/MobileAppController.java index 4d0f19299f..6620e854d0 100644 --- a/application/src/main/java/org/thingsboard/server/controller/MobileAppController.java +++ b/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 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 { diff --git a/application/src/main/java/org/thingsboard/server/controller/OAuth2Controller.java b/application/src/main/java/org/thingsboard/server/controller/OAuth2Controller.java index ee46438569..4d0dc61750 100644 --- a/application/src/main/java/org/thingsboard/server/controller/OAuth2Controller.java +++ b/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 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 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 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 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 { diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/domain/DefaultTbDomainService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/domain/DefaultTbDomainService.java index 755972f9fa..59cf6f9856 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/domain/DefaultTbDomainService.java +++ b/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(); diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/mobile/DefaultTbMobileAppService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/mobile/DefaultTbMobileAppService.java index a0731789be..7d5f1122da 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/mobile/DefaultTbMobileAppService.java +++ b/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(); diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/oauth2client/DefaultTbOauth2ClientService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/oauth2client/DefaultTbOauth2ClientService.java index 0a36c23369..999bf3976c 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/oauth2client/DefaultTbOauth2ClientService.java +++ b/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; diff --git a/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java b/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java index dcb19ed271..92c5909056 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java +++ b/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 mobiles = oAuth2MobileDao.findByTenantId(TenantId.SYS_TENANT_ID, new PageLink(Integer.MAX_VALUE,0)).getData(); + List 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); }); } } diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AbstractOAuth2ClientMapper.java b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AbstractOAuth2ClientMapper.java index 0182d5026c..a4960182b1 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AbstractOAuth2ClientMapper.java +++ b/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); diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AppleOAuth2ClientMapper.java b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AppleOAuth2ClientMapper.java index 0e4ee821f7..c7a499c7ec 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AppleOAuth2ClientMapper.java +++ b/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 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 updateAttributesFromRequestParams(HttpServletRequest request, Map attributes) { diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java index 59c1a50fa1..de3de1db7e 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java +++ b/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 platforms) { + protected OAuth2Client createOauth2Client(TenantId tenantId, String title, List platforms) { OAuth2Client oAuth2Client = new OAuth2Client(); oAuth2Client.setTenantId(tenantId); oAuth2Client.setTitle(title); diff --git a/application/src/test/java/org/thingsboard/server/controller/DomainControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/DomainControllerTest.java index 609444bd3d..c899aeeddb 100644 --- a/application/src/test/java/org/thingsboard/server/controller/DomainControllerTest.java +++ b/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); diff --git a/application/src/test/java/org/thingsboard/server/controller/HomePageApiTest.java b/application/src/test/java/org/thingsboard/server/controller/HomePageApiTest.java index 6b46e64cfe..69f3c2a7db 100644 --- a/application/src/test/java/org/thingsboard/server/controller/HomePageApiTest.java +++ b/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); diff --git a/application/src/test/java/org/thingsboard/server/controller/MobileAppControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/MobileAppControllerTest.java index a0deb39a51..23b1f47c91 100644 --- a/application/src/test/java/org/thingsboard/server/controller/MobileAppControllerTest.java +++ b/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); diff --git a/application/src/test/java/org/thingsboard/server/controller/Oauth2ClientControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/Oauth2ClientControllerTest.java index fbde35567c..4e8ac72676 100644 --- a/application/src/test/java/org/thingsboard/server/controller/Oauth2ClientControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/Oauth2ClientControllerTest.java @@ -57,7 +57,7 @@ public class Oauth2ClientControllerTest extends AbstractControllerTest { PageData 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 pageData2 = doGetTypedWithPageLink("/api/oauth2/client/infos?", PAGE_DATA_OAUTH2_CLIENT_TYPE_REF, new PageLink(10, 0)); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientService.java index a195e50917..e4c67108db 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientService.java +++ b/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); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/domain/DomainOauth2Client.java b/common/data/src/main/java/org/thingsboard/server/common/data/domain/DomainOauth2Client.java index 11c872c8be..91cbb8a7a6 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/domain/DomainOauth2Client.java +++ b/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; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/mobile/MobileAppInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/mobile/MobileAppInfo.java index 9a0b0b3b1c..4d85028e36 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/mobile/MobileAppInfo.java +++ b/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 oauth2ClientInfos; public MobileAppInfo(MobileApp mobileApp, List oauth2ClientInfos) { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2Client.java b/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2Client.java index 7624a6ccd5..f9b93b00e1 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2Client.java +++ b/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 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 imp @Override @JsonProperty(access = JsonProperty.Access.READ_ONLY) public String getName() { - return loginButtonLabel; + return title; } } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientInfo.java index c2e9bce7be..4e083545c9 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientInfo.java +++ b/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 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(); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/domain/DomainDao.java b/dao/src/main/java/org/thingsboard/server/dao/domain/DomainDao.java index cbc371520c..e4eaf57356 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/domain/DomainDao.java +++ b/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 { List 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); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/domain/DomainServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/domain/DomainServiceImpl.java index 196a9324e7..487e3feb5c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/domain/DomainServiceImpl.java +++ b/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 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 oauth2Clients = new ArrayList<>(); - for (OAuth2ClientId oAuth2ClientId : oAuth2ClientIds) { - oauth2Clients.add(new DomainOauth2Client(domainId, oAuth2ClientId)); - } + Set newClientList = oAuth2ClientIds.stream() + .map(clientId -> new DomainOauth2Client(domainId, clientId)) + .collect(Collectors.toSet()); + List existingClients = domainDao.findOauth2ClientsByDomainId(tenantId, domainId); - List 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 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 findDomainInfosByTenantId(TenantId tenantId, PageLink pageLink) { log.trace("Executing findDomainInfosByTenantId [{}]", tenantId); - PageData pageData = domainDao.findByTenantId(tenantId, pageLink); - List 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 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 clients = oauth2ClientDao.findByDomainId(domain.getUuidId()).stream() + .map(OAuth2ClientInfo::new) + .collect(Collectors.toList()); + return new DomainInfo(domain, clients); + } + + @Override + public EntityType getEntityType() { + return EntityType.DOMAIN; } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/mobile/MobileAppDao.java b/dao/src/main/java/org/thingsboard/server/dao/mobile/MobileAppDao.java index f42acb1638..8da92e1eb3 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/mobile/MobileAppDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/mobile/MobileAppDao.java @@ -32,9 +32,9 @@ public interface MobileAppDao extends Dao { List 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); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/mobile/MobileAppServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/mobile/MobileAppServiceImpl.java index aeac676903..3089cc9ef4 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/mobile/MobileAppServiceImpl.java +++ b/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 findMobileAppInfosByTenantId(TenantId tenantId, PageLink pageLink) { log.trace("Executing findMobileAppInfosByTenantId [{}]", tenantId); - PageData pageData = mobileAppDao.findByTenantId(tenantId, pageLink); - List 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 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 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 oauth2Clients = new ArrayList<>(); - for (OAuth2ClientId oAuth2ClientId : oAuth2ClientIds) { - oauth2Clients.add(new MobileAppOauth2Client(mobileAppId, oAuth2ClientId)); - } + Set newClientList = oAuth2ClientIds.stream() + .map(clientId -> new MobileAppOauth2Client(mobileAppId, clientId)) + .collect(Collectors.toSet()); + List existingClients = mobileAppDao.findOauth2ClientsByMobileAppId(tenantId, mobileAppId); - List 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 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 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; + } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java index 96c3a9a562..233797285a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java +++ b/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"; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DomainEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DomainEntity.java index 6138e8f114..069481a205 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DomainEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DomainEntity.java @@ -39,7 +39,7 @@ public class DomainEntity extends BaseSqlEntity { @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) diff --git a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientDao.java b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientDao.java index c4c3b2e2ec..5880db100f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientDao.java @@ -36,11 +36,11 @@ public interface OAuth2ClientDao extends Dao { List findByDomainId(UUID domainId); - List findByMobileAppId(UUID domainId); + List findByMobileAppId(UUID mobileAppId); String findAppSecret(UUID id, String pkgName); - void deleteByTenantId(TenantId tenantId); + void deleteByTenantId(UUID tenantId); List findByIds(TenantId tenantId, List oAuth2ClientIds); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientServiceImpl.java index f7eeb20277..6273ee2763 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientServiceImpl.java +++ b/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 findOAuth2ClientInfosByTenantId(TenantId tenantId, PageLink pageLink) { log.trace("Executing findOAuth2ClientInfosByTenantId tenantId=[{}]", tenantId); - PageData clientInfos = oauth2ClientDao.findByTenantId(tenantId.getId(), pageLink); - List oAuth2ClientInfos = clientInfos - .getData() - .stream() - .map(OAuth2ClientInfo::new) - .collect(Collectors.toList()); - return new PageData<>(oAuth2ClientInfos, clientInfos.getTotalPages(), clientInfos.getTotalPages(), clientInfos.hasNext()); + PageData 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 diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/domain/DomainOauth2ClientRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/domain/DomainOauth2ClientRepository.java index 3fe20226d1..40e9d2166f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/domain/DomainOauth2ClientRepository.java +++ b/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 { - List findAllByDomainId(@Param("domainId") UUID domainId); + List findAllByDomainId(UUID domainId); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/domain/DomainRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/domain/DomainRepository.java index d2cc957fe8..bf3ad8f9cf 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/domain/DomainRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/domain/DomainRepository.java @@ -39,6 +39,6 @@ public interface DomainRepository extends JpaRepository { @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); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/domain/JpaDomainDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/domain/JpaDomainDao.java index 7701483644..2cbe109af5 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/domain/JpaDomainDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/domain/JpaDomainDao.java @@ -71,13 +71,14 @@ public class JpaDomainDao extends JpaAbstractDao 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 diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/mobile/JpaMobileAppDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/mobile/JpaMobileAppDao.java index 8f09c7267b..0453481d08 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/mobile/JpaMobileAppDao.java +++ b/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 @Override public List 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 diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/mobile/MobileAppOauth2ClientRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/mobile/MobileAppOauth2ClientRepository.java index 6ce4c99977..9abf9b3b61 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/mobile/MobileAppOauth2ClientRepository.java +++ b/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 { - List findAllByMobileAppId(@Param("mobileAppId") UUID mobileAppId); + List findAllByMobileAppId(UUID mobileAppId); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ClientDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ClientDao.java index d58b68ed7c..cd36da43cf 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ClientDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/oauth2/JpaOAuth2ClientDao.java @@ -66,7 +66,7 @@ public class JpaOAuth2ClientDao extends JpaAbstractDao 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 findEnabledByDomainNameAndPlatformType(@Param("domainName") String domainName, @Param("platformFilter") String platformFilter); @@ -48,8 +48,8 @@ public interface OAuth2ClientRepository extends JpaRepository findEnabledByPkgNameAndPlatformType(@Param("pkgName") String pkgName, @Param("platformFilter") String platformFilter); @@ -79,6 +79,6 @@ public interface OAuth2ClientRepository extends JpaRepository findByTenantIdAndIdIn(UUID tenantId, List queueStatsIds); + List findByTenantIdAndIdIn(UUID tenantId, List uuids); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java index 75d04757ad..8e6c38814a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java @@ -177,6 +177,7 @@ public class TenantServiceImpl extends AbstractCachedEntityService