fixed SqlDatabaseUpgradeService with new upgrade, refactoring

This commit is contained in:
dashevchenko 2024-07-22 13:48:43 +03:00
parent b57744f5d5
commit 333154ad62
23 changed files with 160 additions and 239 deletions

View File

@ -24,10 +24,19 @@ ALTER TABLE domain ADD COLUMN IF NOT EXISTS oauth2_enabled boolean,
ADD COLUMN IF NOT EXISTS edge_enabled boolean,
ADD COLUMN IF NOT EXISTS tenant_id uuid DEFAULT '13814000-1dd2-11b2-8080-808080808080',
DROP COLUMN IF EXISTS domain_scheme;
-- delete duplicated domains
DELETE FROM domain d1 USING domain d2 WHERE d1.created_time < d2.created_time AND d1.domain_name = d2.domain_name;
ALTER TABLE mobile_app ADD COLUMN IF NOT EXISTS oauth2_enabled boolean,
ADD COLUMN IF NOT EXISTS tenant_id uuid DEFAULT '13814000-1dd2-11b2-8080-808080808080';
ALTER TABLE oauth2_client ADD COLUMN IF NOT EXISTS tenant_id uuid DEFAULT '13814000-1dd2-11b2-8080-808080808080';
ALTER TABLE oauth2_client ADD COLUMN IF NOT EXISTS title varchar(100);
-- 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;
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);
UPDATE oauth2_client SET title = additional_info::jsonb->>'providerName' WHERE additional_info IS NOT NULL;
CREATE TABLE IF NOT EXISTS domain_oauth2_client (
domain_id uuid NOT NULL,
@ -43,13 +52,11 @@ CREATE TABLE IF NOT EXISTS mobile_app_oauth2_client (
CONSTRAINT fk_oauth2_client FOREIGN KEY (oauth2_client_id) REFERENCES oauth2_client(id) ON DELETE CASCADE
);
-- migrate oauth2_params table
DO
$$
BEGIN
IF EXISTS(SELECT 1 FROM information_schema.tables WHERE table_name = 'oauth2_params') THEN
-- delete duplicated domains
DELETE FROM domain d1 USING domain d2 WHERE d1.created_time < d2.created_time AND d1.domain_name = d2.domain_name;
UPDATE domain SET oauth2_enabled = p.enabled,
edge_enabled = p.edge_enabled
FROM oauth2_params p WHERE p.id = domain.oauth2_params_id;
@ -68,7 +75,6 @@ $$
ALTER TABLE mobile_app RENAME CONSTRAINT oauth2_mobile_pkey TO mobile_app_pkey;
ALTER TABLE domain RENAME CONSTRAINT oauth2_domain_pkey TO domain_pkey;
ALTER TABLE oauth2_client RENAME CONSTRAINT oauth2_registration_pkey TO oauth2_client_pkey;
UPDATE oauth2_client SET title = additional_info::jsonb->>'providerName' WHERE additional_info IS NOT NULL;
ALTER TABLE domain DROP COLUMN oauth2_params_id;
ALTER TABLE mobile_app DROP COLUMN oauth2_params_id;

View File

@ -63,7 +63,7 @@ public class DomainController extends BaseController {
"The newly created Domain Id will be present in the response. " +
"Specify existing Domain Id to update the domain. " +
"Referencing non-existing Domain Id will cause 'Not Found' error." +
"\n\nDomain name is unique for entire platform setup.\n\n")
"\n\nDomain name is unique for entire platform setup.\n\n" + SYSTEM_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('SYS_ADMIN')")
@PostMapping(value = "/domain")
public Domain saveDomain(
@ -104,13 +104,13 @@ 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." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
notes = "Deletes Domain by ID. Referencing non-existing asset Id will cause an error." + SYSTEM_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('SYS_ADMIN')")
@DeleteMapping(value = "/domain/{id}")
public void deleteDomain(@PathVariable UUID id) throws Exception {
DomainId domainId = new DomainId(id);
checkDomainId(domainId, Operation.DELETE);
domainService.deleteDomainById(getTenantId(), domainId);
Domain domain = checkDomainId(domainId, Operation.DELETE);
tbDomainService.delete(domain, getCurrentUser());
}
}

View File

@ -64,7 +64,7 @@ public class MobileAppController extends BaseController {
"The newly created Mobile App Id will be present in the response. " +
"Specify existing Mobile App Id to update the mobile app. " +
"Referencing non-existing Mobile App Id will cause 'Not Found' error." +
"\n\nMobile app package name is unique for entire platform setup.\n\n")
"\n\nMobile app package name is unique for entire platform setup.\n\n" + SYSTEM_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('SYS_ADMIN')")
@PostMapping(value = "/mobileApp")
public MobileApp saveMobileApp(
@ -106,13 +106,13 @@ 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." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
notes = "Deletes Mobile App by ID. Referencing non-existing asset Id will cause an error." + SYSTEM_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('SYS_ADMIN')")
@DeleteMapping(value = "/mobileApp/{id}")
public void deleteMobileApp(@PathVariable UUID id) throws Exception {
MobileAppId mobileAppId = new MobileAppId(id);
checkMobileAppId(mobileAppId, Operation.DELETE);
mobileAppService.deleteMobileAppById(getTenantId(), mobileAppId);
MobileApp mobileApp = checkMobileAppId(mobileAppId, Operation.DELETE);
tbMobileAppService.delete(mobileApp, getCurrentUser());
}
}

View File

@ -51,7 +51,6 @@ import java.util.List;
import java.util.UUID;
import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_AUTHORITY_PARAGRAPH;
import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
@RestController
@TbCoreComponent
@ -100,7 +99,7 @@ public class OAuth2Controller extends BaseController {
}
}
@ApiOperation(value = "Save OAuth2 Client Registration (saveOAuth2Client)", notes = SYSTEM_AUTHORITY_PARAGRAPH)
@ApiOperation(value = "Save OAuth2 Client (saveOAuth2Client)", notes = SYSTEM_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('SYS_ADMIN')")
@PostMapping(value = "/oauth2/client")
public OAuth2Client saveOAuth2Client(@RequestBody @Valid OAuth2Client oAuth2Client) throws Exception {
@ -126,7 +125,7 @@ public class OAuth2Controller extends BaseController {
}
@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." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
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)
@PreAuthorize("hasAuthority('SYS_ADMIN')")
@DeleteMapping(value = "/oauth2/client/{id}")
public void deleteOauth2Client(@PathVariable UUID id) throws Exception {

View File

@ -137,6 +137,9 @@ public class ThingsboardInstallService {
entityDatabaseSchemaService.createCustomerTitleUniqueConstraintIfNotExists();
systemDataLoaderService.updateDefaultNotificationConfigs(false);
systemDataLoaderService.updateSecuritySettings();
case "3.7.0":
log.info("Upgrading ThingsBoard from version 3.7.0 to 3.7.1 ...");
databaseEntitiesUpgradeService.upgradeDatabase("3.7.0");
//TODO DON'T FORGET to update switch statement in the CacheCleanupService if you need to clear the cache
break;
default:

View File

@ -121,6 +121,9 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService
case "3.6.4":
updateSchema("3.6.4", 3006004, "3.7.0", 3007000, null);
break;
case "3.7.0":
updateSchema("3.7.0", 3007000, "3.7.1", 3007001, null);
break;
default:
throw new RuntimeException("Unable to upgrade SQL database, unsupported fromVersion: " + fromVersion);
}

View File

@ -99,6 +99,11 @@ import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.TenantProfileId;
import org.thingsboard.server.common.data.id.UUIDBased;
import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.oauth2.MapperType;
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
import org.thingsboard.server.common.data.oauth2.OAuth2CustomMapperConfig;
import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig;
import org.thingsboard.server.common.data.oauth2.PlatformType;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.page.TimePageLink;
@ -1109,4 +1114,39 @@ 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 validClientInfo(TenantId tenantId, String title, List<PlatformType> platforms) {
OAuth2Client oAuth2Client = new OAuth2Client();
oAuth2Client.setTenantId(tenantId);
oAuth2Client.setTitle(title);
oAuth2Client.setClientId(UUID.randomUUID().toString());
oAuth2Client.setClientSecret(UUID.randomUUID().toString());
oAuth2Client.setAuthorizationUri(UUID.randomUUID().toString());
oAuth2Client.setAccessTokenUri(UUID.randomUUID().toString());
oAuth2Client.setScope(Arrays.asList(UUID.randomUUID().toString(), UUID.randomUUID().toString()));
oAuth2Client.setPlatforms(platforms == null ? Collections.emptyList() : platforms);
oAuth2Client.setUserInfoUri(UUID.randomUUID().toString());
oAuth2Client.setUserNameAttributeName(UUID.randomUUID().toString());
oAuth2Client.setJwkSetUri(UUID.randomUUID().toString());
oAuth2Client.setClientAuthenticationMethod(UUID.randomUUID().toString());
oAuth2Client.setLoginButtonLabel(UUID.randomUUID().toString());
oAuth2Client.setLoginButtonIcon(UUID.randomUUID().toString());
oAuth2Client.setAdditionalInfo(JacksonUtil.newObjectNode().put(UUID.randomUUID().toString(), UUID.randomUUID().toString()));
oAuth2Client.setMapperConfig(
OAuth2MapperConfig.builder()
.allowUserCreation(true)
.activateUser(true)
.type(MapperType.CUSTOM)
.custom(
OAuth2CustomMapperConfig.builder()
.url(UUID.randomUUID().toString())
.build()
)
.build());
return oAuth2Client;
}
}

View File

@ -140,39 +140,4 @@ public class DomainControllerTest extends AbstractControllerTest {
return domain;
}
protected OAuth2Client validClientInfo(TenantId tenantId, String title) {
return validClientInfo(tenantId, title, null);
}
protected OAuth2Client validClientInfo(TenantId tenantId, String title, List<PlatformType> platforms) {
OAuth2Client oAuth2Client = new OAuth2Client();
oAuth2Client.setTenantId(tenantId);
oAuth2Client.setTitle(title);
oAuth2Client.setClientId(UUID.randomUUID().toString());
oAuth2Client.setClientSecret(UUID.randomUUID().toString());
oAuth2Client.setAuthorizationUri(UUID.randomUUID().toString());
oAuth2Client.setAccessTokenUri(UUID.randomUUID().toString());
oAuth2Client.setScope(Arrays.asList(UUID.randomUUID().toString(), UUID.randomUUID().toString()));
oAuth2Client.setPlatforms(platforms == null ? Collections.emptyList() : platforms);
oAuth2Client.setUserInfoUri(UUID.randomUUID().toString());
oAuth2Client.setUserNameAttributeName(UUID.randomUUID().toString());
oAuth2Client.setJwkSetUri(UUID.randomUUID().toString());
oAuth2Client.setClientAuthenticationMethod(UUID.randomUUID().toString());
oAuth2Client.setLoginButtonLabel(UUID.randomUUID().toString());
oAuth2Client.setLoginButtonIcon(UUID.randomUUID().toString());
oAuth2Client.setAdditionalInfo(JacksonUtil.newObjectNode().put(UUID.randomUUID().toString(), UUID.randomUUID().toString()));
oAuth2Client.setMapperConfig(
OAuth2MapperConfig.builder()
.allowUserCreation(true)
.activateUser(true)
.type(MapperType.CUSTOM)
.custom(
OAuth2CustomMapperConfig.builder()
.url(UUID.randomUUID().toString())
.build()
)
.build());
return oAuth2Client;
}
}

View File

@ -60,7 +60,6 @@ import org.thingsboard.server.service.ws.telemetry.cmd.v2.EntityDataUpdate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@ -361,8 +360,11 @@ public class HomePageApiTest extends AbstractControllerTest {
Assert.assertTrue(featuresInfo.isNotificationEnabled());
Assert.assertFalse(featuresInfo.isOauthEnabled());
Domain domain = createDomain(TenantId.SYS_TENANT_ID, "mydomain", true);
doPost("/api/domain", domain).andExpect(status().isOk());
OAuth2Client oAuth2Client = validClientInfo(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);
doPost("/api/domain?oauth2ClientIds=" + savedOAuth2Client.getId().getId(), domain, Domain.class);
featuresInfo = doGet("/api/admin/featuresInfo", FeaturesInfo.class);
Assert.assertNotNull(featuresInfo);
@ -484,38 +486,13 @@ public class HomePageApiTest extends AbstractControllerTest {
return doPostWithResponse("/api/entitiesQuery/count", query, Long.class);
}
private Domain createDomain(TenantId tenantId, String domainName, boolean oauth2Enabled) {
private Domain createDomain(TenantId tenantId, String domainName, boolean oauth2Enabled, boolean edgeEnabled) {
Domain domain = new Domain();
domain.setTenantId(tenantId);
domain.setName(domainName);
domain.setOauth2Enabled(oauth2Enabled);
domain.setPropagateToEdge(edgeEnabled);
return domain;
}
private OAuth2Client validRegistration() {
OAuth2Client oAuth2Client = new OAuth2Client();
oAuth2Client.setClientId(UUID.randomUUID().toString());
// .clientSecret(UUID.randomUUID().toString())
// .authorizationUri(UUID.randomUUID().toString())
// .accessTokenUri(UUID.randomUUID().toString())
// .scope(Arrays.asList(UUID.randomUUID().toString(), UUID.randomUUID().toString()))
// .platforms(Collections.emptyList())
// .userInfoUri(UUID.randomUUID().toString())
// .userNameAttributeName(UUID.randomUUID().toString())
// .jwkSetUri(UUID.randomUUID().toString())
// .clientAuthenticationMethod(UUID.randomUUID().toString())
// .loginButtonLabel(UUID.randomUUID().toString())
// .mapperConfig(
// OAuth2MapperConfig.builder()
// .type(MapperType.CUSTOM)
// .custom(
// OAuth2CustomMapperConfig.builder()
// .url(UUID.randomUUID().toString())
// .build()
// )
// .build()
// )
// .build();
return oAuth2Client;
}
}

View File

@ -142,39 +142,4 @@ public class MobileAppControllerTest extends AbstractControllerTest {
return MobileApp;
}
protected OAuth2Client validClientInfo(TenantId tenantId, String title) {
return validClientInfo(tenantId, title, null);
}
protected OAuth2Client validClientInfo(TenantId tenantId, String title, List<PlatformType> platforms) {
OAuth2Client oAuth2Client = new OAuth2Client();
oAuth2Client.setTenantId(tenantId);
oAuth2Client.setTitle(title);
oAuth2Client.setClientId(UUID.randomUUID().toString());
oAuth2Client.setClientSecret(UUID.randomUUID().toString());
oAuth2Client.setAuthorizationUri(UUID.randomUUID().toString());
oAuth2Client.setAccessTokenUri(UUID.randomUUID().toString());
oAuth2Client.setScope(Arrays.asList(UUID.randomUUID().toString(), UUID.randomUUID().toString()));
oAuth2Client.setPlatforms(platforms == null ? Collections.emptyList() : platforms);
oAuth2Client.setUserInfoUri(UUID.randomUUID().toString());
oAuth2Client.setUserNameAttributeName(UUID.randomUUID().toString());
oAuth2Client.setJwkSetUri(UUID.randomUUID().toString());
oAuth2Client.setClientAuthenticationMethod(UUID.randomUUID().toString());
oAuth2Client.setLoginButtonLabel(UUID.randomUUID().toString());
oAuth2Client.setLoginButtonIcon(UUID.randomUUID().toString());
oAuth2Client.setAdditionalInfo(JacksonUtil.newObjectNode().put(UUID.randomUUID().toString(), UUID.randomUUID().toString()));
oAuth2Client.setMapperConfig(
OAuth2MapperConfig.builder()
.allowUserCreation(true)
.activateUser(true)
.type(MapperType.CUSTOM)
.custom(
OAuth2CustomMapperConfig.builder()
.url(UUID.randomUUID().toString())
.build()
)
.build());
return oAuth2Client;
}
}

View File

@ -80,39 +80,4 @@ public class Oauth2ClientControllerTest extends AbstractControllerTest {
.andExpect(status().isNotFound());
}
protected OAuth2Client validClientInfo(TenantId tenantId, String title) {
return validClientInfo(tenantId, title, null);
}
protected OAuth2Client validClientInfo(TenantId tenantId, String title, List<PlatformType> platforms) {
OAuth2Client oAuth2Client = new OAuth2Client();
oAuth2Client.setTenantId(tenantId);
oAuth2Client.setTitle(title);
oAuth2Client.setClientId(UUID.randomUUID().toString());
oAuth2Client.setClientSecret(UUID.randomUUID().toString());
oAuth2Client.setAuthorizationUri(UUID.randomUUID().toString());
oAuth2Client.setAccessTokenUri(UUID.randomUUID().toString());
oAuth2Client.setScope(Arrays.asList(UUID.randomUUID().toString(), UUID.randomUUID().toString()));
oAuth2Client.setPlatforms(platforms == null ? Collections.emptyList() : platforms);
oAuth2Client.setUserInfoUri(UUID.randomUUID().toString());
oAuth2Client.setUserNameAttributeName(UUID.randomUUID().toString());
oAuth2Client.setJwkSetUri(UUID.randomUUID().toString());
oAuth2Client.setClientAuthenticationMethod(UUID.randomUUID().toString());
oAuth2Client.setLoginButtonLabel(UUID.randomUUID().toString());
oAuth2Client.setLoginButtonIcon(UUID.randomUUID().toString());
oAuth2Client.setAdditionalInfo(JacksonUtil.newObjectNode().put(UUID.randomUUID().toString(), UUID.randomUUID().toString()));
oAuth2Client.setMapperConfig(
OAuth2MapperConfig.builder()
.allowUserCreation(true)
.activateUser(true)
.type(MapperType.CUSTOM)
.custom(
OAuth2CustomMapperConfig.builder()
.url(UUID.randomUUID().toString())
.build()
)
.build());
return oAuth2Client;
}
}

View File

@ -19,7 +19,6 @@ import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.thingsboard.server.common.data.BaseData;
import org.thingsboard.server.common.data.HasName;
@ -30,7 +29,6 @@ import org.thingsboard.server.common.data.id.TenantId;
@EqualsAndHashCode(callSuper = true)
@Data
@ToString
@NoArgsConstructor
public class Domain extends BaseData<DomainId> implements HasTenantId, HasName {
@Schema(description = "JSON object with Tenant Id")
@ -43,6 +41,14 @@ public class Domain extends BaseData<DomainId> implements HasTenantId, HasName {
@Schema(description = "Whether OAuth2 settings are enabled on Edge or not")
private boolean propagateToEdge;
public Domain() {
super();
}
public Domain(DomainId id) {
super(id);
}
public Domain(Domain domain) {
super(domain);
this.tenantId = domain.tenantId;

View File

@ -16,21 +16,17 @@
package org.thingsboard.server.common.data.domain;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.thingsboard.server.common.data.oauth2.HasOauth2Clients;
import org.thingsboard.server.common.data.id.DomainId;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo;
import java.util.List;
@EqualsAndHashCode(callSuper = true)
@Data
@NoArgsConstructor
@AllArgsConstructor
@Schema
public class DomainInfo extends Domain implements HasOauth2Clients {
public class DomainInfo extends Domain {
@Schema(description = "List of available oauth2 client registration")
private List<OAuth2ClientInfo> oauth2ClientInfos;
@ -39,4 +35,12 @@ public class DomainInfo extends Domain implements HasOauth2Clients {
super(domain);
this.oauth2ClientInfos = oauth2ClientInfos;
}
public DomainInfo() {
super();
}
public DomainInfo(DomainId domainId) {
super(domainId);
}
}

View File

@ -17,10 +17,10 @@ package org.thingsboard.server.common.data.mobile;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.thingsboard.server.common.data.BaseData;
import org.thingsboard.server.common.data.HasName;
@ -32,13 +32,12 @@ import org.thingsboard.server.common.data.validation.Length;
@EqualsAndHashCode(callSuper = true)
@Data
@ToString
@NoArgsConstructor
public class MobileApp extends BaseData<MobileAppId> implements HasTenantId, HasName {
@Schema(description = "JSON object with Tenant Id")
private TenantId tenantId;
@Schema(description = "Application package name. Cannot be empty", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty
@NotBlank
private String pkgName;
@Schema(description = "Application secret. The length must be at least 16 characters", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty
@ -47,6 +46,14 @@ public class MobileApp extends BaseData<MobileAppId> implements HasTenantId, Has
@Schema(description = "Whether OAuth2 settings are enabled or not")
private boolean oauth2Enabled;
public MobileApp() {
super();
}
public MobileApp(MobileAppId id) {
super(id);
}
public MobileApp(MobileApp mobile) {
super(mobile);
this.tenantId = mobile.tenantId;

View File

@ -16,25 +16,17 @@
package org.thingsboard.server.common.data.mobile;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.thingsboard.server.common.data.oauth2.HasOauth2Clients;
import org.thingsboard.server.common.data.id.MobileAppId;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo;
import java.util.List;
@EqualsAndHashCode(callSuper = true)
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Schema
public class MobileAppInfo extends MobileApp implements HasOauth2Clients {
public class MobileAppInfo extends MobileApp {
@Schema(description = "List of available oauth2 client registrations")
private List<OAuth2ClientInfo> oauth2ClientInfos;
@ -44,4 +36,12 @@ public class MobileAppInfo extends MobileApp implements HasOauth2Clients {
this.oauth2ClientInfos = oauth2ClientInfos;
}
public MobileAppInfo() {
super();
}
public MobileAppInfo(MobileAppId mobileAppId) {
super(mobileAppId);
}
}

View File

@ -1,26 +0,0 @@
/**
* Copyright © 2016-2024 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.oauth2;
import java.io.Serializable;
import java.util.List;
public interface HasOauth2Clients extends Serializable {
List<OAuth2ClientInfo> getOauth2ClientInfos();
}

View File

@ -23,7 +23,6 @@ import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.thingsboard.server.common.data.BaseDataWithAdditionalInfo;
import org.thingsboard.server.common.data.HasName;
@ -36,7 +35,6 @@ import java.util.List;
@EqualsAndHashCode(callSuper = true)
@Data
@ToString(exclude = {"clientSecret"})
@NoArgsConstructor
public class OAuth2Client extends BaseDataWithAdditionalInfo<OAuth2ClientId> implements HasName, HasTenantId {
@Schema(description = "JSON object with Tenant Id")
@ -82,23 +80,31 @@ public class OAuth2Client extends BaseDataWithAdditionalInfo<OAuth2ClientId> imp
@Schema(description = "Additional info of OAuth2 client (e.g. providerName)", requiredMode = Schema.RequiredMode.REQUIRED)
private JsonNode additionalInfo;
public OAuth2Client(OAuth2Client registration) {
super(registration);
this.tenantId = registration.tenantId;
this.title = registration.title;
this.mapperConfig = registration.mapperConfig;
this.clientId = registration.clientId;
this.clientSecret = registration.clientSecret;
this.authorizationUri = registration.authorizationUri;
this.accessTokenUri = registration.accessTokenUri;
this.scope = registration.scope;
this.userInfoUri = registration.userInfoUri;
this.userNameAttributeName = registration.userNameAttributeName;
this.jwkSetUri = registration.jwkSetUri;
this.clientAuthenticationMethod = registration.clientAuthenticationMethod;
this.loginButtonLabel = registration.loginButtonLabel;
this.loginButtonIcon = registration.loginButtonIcon;
this.platforms = registration.platforms;
public OAuth2Client() {
super();
}
public OAuth2Client(OAuth2ClientId id) {
super(id);
}
public OAuth2Client(OAuth2Client oAuth2Client) {
super(oAuth2Client);
this.tenantId = oAuth2Client.tenantId;
this.title = oAuth2Client.title;
this.mapperConfig = oAuth2Client.mapperConfig;
this.clientId = oAuth2Client.clientId;
this.clientSecret = oAuth2Client.clientSecret;
this.authorizationUri = oAuth2Client.authorizationUri;
this.accessTokenUri = oAuth2Client.accessTokenUri;
this.scope = oAuth2Client.scope;
this.userInfoUri = oAuth2Client.userInfoUri;
this.userNameAttributeName = oAuth2Client.userNameAttributeName;
this.jwkSetUri = oAuth2Client.jwkSetUri;
this.clientAuthenticationMethod = oAuth2Client.clientAuthenticationMethod;
this.loginButtonLabel = oAuth2Client.loginButtonLabel;
this.loginButtonIcon = oAuth2Client.loginButtonIcon;
this.platforms = oAuth2Client.platforms;
}
@Override

View File

@ -55,6 +55,9 @@ enum EntityTypeProto {
NOTIFICATION = 32;
NOTIFICATION_RULE = 33;
QUEUE_STATS = 34;
OAUTH2_CLIENT = 35;
DOMAIN = 36;
MOBILE_APP = 37;
}
/**

View File

@ -77,7 +77,7 @@ public class DomainServiceImpl extends AbstractEntityService implements DomainSe
@Override
public void updateOauth2Clients(TenantId tenantId, DomainId domainId, List<OAuth2ClientId> oAuth2ClientIds) {
log.trace("Executing addOauth2Clients, domainId [{}], oAuth2ClientIds [{}]", domainId, 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);
@ -118,7 +118,7 @@ public class DomainServiceImpl extends AbstractEntityService implements DomainSe
@Override
public List<DomainInfo> findDomainInfosByTenantId(TenantId tenantId) {
log.trace("Executing findDomainInfo [{}]", tenantId);
log.trace("Executing findDomainInfosByTenantId [{}]", tenantId);
List<Domain> domains = domainDao.findByTenantId(tenantId);
List<DomainInfo> domainInfos = new ArrayList<>();
domains.stream().sorted(Comparator.comparing(BaseData::getUuidId)).forEach(domain -> {

View File

@ -163,7 +163,7 @@ public class MobileAppServiceImpl extends AbstractEntityService implements Mobil
@Override
public void deleteMobileAppsByTenantId(TenantId tenantId) {
log.trace("Executing deleteDomainsByTenantId, tenantId [{}]", tenantId);
log.trace("Executing deleteMobileAppsByTenantId, tenantId [{}]", tenantId);
Validator.validateId(tenantId, id -> INCORRECT_TENANT_ID + id);
mobileAppDao.deleteByTenantId(tenantId);
}

View File

@ -57,7 +57,7 @@ public class OAuth2ClientServiceImpl extends AbstractEntityService implements OA
@Override
public List<OAuth2ClientLoginInfo> findOAuth2ClientLoginInfosByDomainName(String domainName) {
log.trace("Executing getOAuth2Clients [{}] ", domainName);
log.trace("Executing findOAuth2ClientLoginInfosByDomainName [{}] ", domainName);
validateString(domainName, dn -> INCORRECT_DOMAIN_NAME + dn);
return oauth2ClientDao.findEnabledByDomainName(domainName)
.stream()
@ -67,7 +67,7 @@ public class OAuth2ClientServiceImpl extends AbstractEntityService implements OA
@Override
public List<OAuth2ClientLoginInfo> findOAuth2ClientLoginInfosByMobilePkgNameAndPlatformType(String pkgName, PlatformType platformType) {
log.trace("Executing getOAuth2Clients pkgName=[{}] platformType=[{}]",pkgName, platformType);
log.trace("Executing findOAuth2ClientLoginInfosByMobilePkgNameAndPlatformType pkgName=[{}] platformType=[{}]",pkgName, platformType);
return oauth2ClientDao.findEnabledByPckNameAndPlatformType(pkgName, platformType)
.stream()
.map(OAuth2Utils::toClientLoginInfo)
@ -108,7 +108,7 @@ public class OAuth2ClientServiceImpl extends AbstractEntityService implements OA
@Override
@Transactional
public void deleteOAuth2ClientById(TenantId tenantId, OAuth2ClientId oAuth2ClientId) {
log.trace("[{}][{}] Executing deleteOAuth2ClientById [{}]", tenantId, oAuth2ClientId);
log.trace("Executing deleteOAuth2ClientById [{}]", oAuth2ClientId);
oauth2ClientDao.removeById(tenantId, oAuth2ClientId.getId());
eventPublisher.publishEvent(DeleteEntityEvent.builder()
.tenantId(tenantId)

View File

@ -40,7 +40,7 @@ import java.util.UUID;
@SqlDao
public class JpaMobileAppDao extends JpaAbstractDao<MobileAppEntity, MobileApp> implements MobileAppDao {
private final MobileAppRepository repository;
private final MobileAppRepository mobileAppRepository;
private final MobileAppOauth2ClientRepository mobileOauth2ProviderRepository;
@Override
@ -50,12 +50,12 @@ public class JpaMobileAppDao extends JpaAbstractDao<MobileAppEntity, MobileApp>
@Override
protected JpaRepository<MobileAppEntity, UUID> getRepository() {
return repository;
return mobileAppRepository;
}
@Override
public List<MobileApp> findByTenantId(TenantId tenantId) {
return DaoUtil.convertDataList(repository.findByTenantId(tenantId.getId()));
return DaoUtil.convertDataList(mobileAppRepository.findByTenantId(tenantId.getId()));
}
@Override
@ -75,7 +75,7 @@ public class JpaMobileAppDao extends JpaAbstractDao<MobileAppEntity, MobileApp>
@Override
public void deleteByTenantId(TenantId tenantId) {
repository.deleteByTenantId(tenantId.getId());
mobileAppRepository.deleteByTenantId(tenantId.getId());
}
@Override

View File

@ -560,9 +560,9 @@ CREATE TABLE IF NOT EXISTS key_dictionary
CREATE TABLE IF NOT EXISTS oauth2_client (
id uuid NOT NULL CONSTRAINT oauth2_client_pkey PRIMARY KEY,
created_time bigint NOT NULL,
tenant_id uuid NOT NULL,
title varchar(100) NOT NULL,
created_time bigint NOT NULL,
additional_info varchar,
client_id varchar(255),
client_secret varchar(2048),
@ -595,22 +595,20 @@ CREATE TABLE IF NOT EXISTS oauth2_client (
CREATE TABLE IF NOT EXISTS domain (
id uuid NOT NULL CONSTRAINT domain_pkey PRIMARY KEY,
tenant_id uuid NOT NULL,
created_time bigint NOT NULL,
domain_name varchar(255),
tenant_id uuid NOT NULL,
domain_name varchar(255) UNIQUE,
oauth2_enabled boolean,
edge_enabled boolean,
CONSTRAINT domain_unq_key UNIQUE (domain_name)
edge_enabled boolean
);
CREATE TABLE IF NOT EXISTS mobile_app (
id uuid NOT NULL CONSTRAINT mobile_app_pkey PRIMARY KEY,
tenant_id uuid,
created_time bigint NOT NULL,
pkg_name varchar(255),
tenant_id uuid,
pkg_name varchar(255) UNIQUE,
app_secret varchar(2048),
oauth2_enabled boolean,
CONSTRAINT mobile_app_unq_key UNIQUE (pkg_name)
oauth2_enabled boolean
);
CREATE TABLE IF NOT EXISTS domain_oauth2_client (