moved 'enabled' from StoreInfo to QrCoodeSettings
This commit is contained in:
parent
c6396e4074
commit
d7582223f4
@ -41,6 +41,7 @@ CREATE TABLE IF NOT EXISTS mobile_app_bundle (
|
||||
CONSTRAINT fk_android_app_id FOREIGN KEY (android_app_id) REFERENCES mobile_app(id),
|
||||
CONSTRAINT fk_ios_app_id FOREIGN KEY (ios_app_id) REFERENCES mobile_app(id)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS mobile_app_bundle_tenant_id ON mobile_app_bundle(tenant_id);
|
||||
|
||||
ALTER TABLE mobile_app ADD COLUMN IF NOT EXISTS platform_type varchar(32),
|
||||
ADD COLUMN IF NOT EXISTS status varchar(32),
|
||||
@ -82,31 +83,34 @@ $$
|
||||
-- duplicate app for iOS platform type
|
||||
iosAppId := uuid_generate_v4();
|
||||
INSERT INTO mobile_app(id, created_time, tenant_id, pkg_name, app_secret, platform_type, status)
|
||||
VALUES (iosAppId, (extract(epoch from now()) * 1000), mobileAppRecord.tenant_id, mobileAppRecord.pkg_name, mobileAppRecord.app_secret, 'IOS', mobileAppRecord.status)
|
||||
VALUES (iosAppId, mobileAppRecord.created_time, mobileAppRecord.tenant_id, mobileAppRecord.pkg_name, mobileAppRecord.app_secret, 'IOS', mobileAppRecord.status)
|
||||
ON CONFLICT DO NOTHING;
|
||||
-- create bundle for android and iOS app
|
||||
generatedBundleId := uuid_generate_v4();
|
||||
INSERT INTO mobile_app_bundle(id, created_time, tenant_id, title, android_app_id, ios_app_id, oauth2_enabled)
|
||||
VALUES (generatedBundleId, (extract(epoch from now()) * 1000), mobileAppRecord.tenant_id,
|
||||
'Autogenerated for ' || mobileAppRecord.pkg_name, mobileAppRecord.id, iosAppId, mobileAppRecord.oauth2_enabled)
|
||||
VALUES (generatedBundleId, mobileAppRecord.created_time, mobileAppRecord.tenant_id,
|
||||
mobileAppRecord.pkg_name || ' (autogenerated)', mobileAppRecord.id, iosAppId, mobileAppRecord.oauth2_enabled)
|
||||
ON CONFLICT DO NOTHING;
|
||||
UPDATE mobile_app_bundle_oauth2_client SET mobile_app_bundle_id = generatedBundleId WHERE mobile_app_bundle_id = mobileAppRecord.id;
|
||||
END LOOP;
|
||||
END IF;
|
||||
ALTER TABLE mobile_app DROP COLUMN IF EXISTS oauth2_enabled;
|
||||
IF NOT EXISTS(SELECT 1 FROM pg_constraint WHERE conname = 'pkg_name_platform_unique') THEN
|
||||
ALTER TABLE mobile_app ADD CONSTRAINT pkg_name_platform_unique UNIQUE (pkg_name, platform_type);
|
||||
IF NOT EXISTS(SELECT 1 FROM pg_constraint WHERE conname = 'mobile_app_pkg_name_platform_unq_key') THEN
|
||||
ALTER TABLE mobile_app ADD CONSTRAINT mobile_app_pkg_name_platform_unq_key UNIQUE (pkg_name, platform_type);
|
||||
END IF;
|
||||
END;
|
||||
$$;
|
||||
|
||||
ALTER TABLE IF EXISTS mobile_app_settings RENAME TO qr_code_settings;
|
||||
ALTER TABLE qr_code_settings ADD COLUMN IF NOT EXISTS mobile_app_bundle_id uuid;
|
||||
ALTER TABLE qr_code_settings ADD COLUMN IF NOT EXISTS mobile_app_bundle_id uuid,
|
||||
ADD COLUMN IF NOT EXISTS android_enabled boolean,
|
||||
ADD COLUMN IF NOT EXISTS ios_enabled boolean;
|
||||
|
||||
-- migrate mobile apps from qr code settings to mobile_app, create mobile app bundle for the pair of apps
|
||||
DO
|
||||
$$
|
||||
DECLARE
|
||||
androidPkgName varchar;
|
||||
iosPkgName varchar;
|
||||
androidAppId uuid;
|
||||
iosAppId uuid;
|
||||
@ -119,40 +123,49 @@ $$
|
||||
LOOP
|
||||
generatedBundleId := NULL;
|
||||
-- migrate android config
|
||||
SELECT id into androidAppId FROM mobile_app WHERE pkg_name = qrCodeRecord.android_config::jsonb ->> 'appPackage' AND platform_type = 'ANDROID';
|
||||
IF androidAppId IS NULL THEN
|
||||
androidAppId := uuid_generate_v4();
|
||||
INSERT INTO mobile_app(id, created_time, tenant_id, pkg_name, platform_type, status, store_info)
|
||||
VALUES (androidAppId, (extract(epoch from now()) * 1000), qrCodeRecord.tenant_id,
|
||||
qrCodeRecord.android_config::jsonb ->> 'appPackage', 'ANDROID', 'DRAFT', qrCodeRecord.android_config::jsonb - 'appPackage');
|
||||
generatedBundleId := uuid_generate_v4();
|
||||
INSERT INTO mobile_app_bundle(id, created_time, tenant_id, title, android_app_id)
|
||||
VALUES (generatedBundleId, (extract(epoch from now()) * 1000), qrCodeRecord.tenant_id, 'Autogenerated for qr code', androidAppId);
|
||||
UPDATE qr_code_settings SET mobile_app_bundle_id = generatedBundleId WHERE id = qrCodeRecord.id;
|
||||
ELSE
|
||||
UPDATE mobile_app SET store_info = qrCodeRecord.android_config::jsonb - 'appPackage' WHERE id = androidAppId;
|
||||
UPDATE qr_code_settings SET mobile_app_bundle_id = (SELECT id FROM mobile_app_bundle WHERE mobile_app_bundle.android_app_id = androidAppId) WHERE id = qrCodeRecord.id;
|
||||
IF (qrCodeRecord.android_config IS NOT NULL AND qrCodeRecord.android_config::jsonb -> 'appPackage' IS NOT NULL) THEN
|
||||
androidPkgName := qrCodeRecord.android_config::jsonb ->> 'appPackage';
|
||||
SELECT id into androidAppId FROM mobile_app WHERE pkg_name = androidPkgName AND platform_type = 'ANDROID';
|
||||
IF androidAppId IS NULL THEN
|
||||
androidAppId := uuid_generate_v4();
|
||||
INSERT INTO mobile_app(id, created_time, tenant_id, pkg_name, platform_type, status, store_info)
|
||||
VALUES (androidAppId, (extract(epoch from now()) * 1000), qrCodeRecord.tenant_id,
|
||||
androidPkgName, 'ANDROID', 'DRAFT', qrCodeRecord.android_config::jsonb - 'appPackage' - 'enabled');
|
||||
generatedBundleId := uuid_generate_v4();
|
||||
INSERT INTO mobile_app_bundle(id, created_time, tenant_id, title, android_app_id)
|
||||
VALUES (generatedBundleId, (extract(epoch from now()) * 1000), qrCodeRecord.tenant_id, androidPkgName || ' (autogenerated)', androidAppId);
|
||||
UPDATE qr_code_settings SET mobile_app_bundle_id = generatedBundleId,
|
||||
android_enabled = (qrCodeRecord.android_config::jsonb ->> 'enabled')::boolean WHERE id = qrCodeRecord.id;
|
||||
ELSE
|
||||
UPDATE mobile_app SET store_info = qrCodeRecord.android_config::jsonb - 'appPackage' - 'enabled' WHERE id = androidAppId;
|
||||
UPDATE qr_code_settings SET mobile_app_bundle_id = (SELECT id FROM mobile_app_bundle WHERE mobile_app_bundle.android_app_id = androidAppId),
|
||||
android_enabled = (qrCodeRecord.android_config::jsonb ->> 'enabled')::boolean WHERE id = qrCodeRecord.id;
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
-- migrate ios config
|
||||
iosPkgName := substring(qrCodeRecord.ios_config::jsonb ->> 'appId', strpos(qrCodeRecord.ios_config::jsonb ->> 'appId', '.') + 1);
|
||||
SELECT id INTO iosAppId FROM mobile_app WHERE pkg_name = iosPkgName AND platform_type = 'IOS';
|
||||
IF iosAppId IS NULL THEN
|
||||
iosAppId := uuid_generate_v4();
|
||||
INSERT INTO mobile_app(id, created_time, tenant_id, pkg_name, platform_type, status, store_info)
|
||||
VALUES (iosAppId, (extract(epoch from now()) * 1000), qrCodeRecord.tenant_id,
|
||||
iosPkgName, 'IOS', 'DRAFT', qrCodeRecord.ios_config);
|
||||
IF generatedBundleId IS NULL THEN
|
||||
generatedBundleId := uuid_generate_v4();
|
||||
INSERT INTO mobile_app_bundle(id, created_time, tenant_id, title, ios_app_id)
|
||||
VALUES (generatedBundleId, (extract(epoch from now()) * 1000), qrCodeRecord.tenant_id, 'Autogenerated for qr code', iosAppId);
|
||||
UPDATE qr_code_settings SET mobile_app_bundle_id = generatedBundleId WHERE id = qrCodeRecord.id;
|
||||
IF (qrCodeRecord.ios_config IS NOT NULL AND qrCodeRecord.ios_config::jsonb -> 'appId' IS NOT NULL) THEN
|
||||
iosPkgName := substring(qrCodeRecord.ios_config::jsonb ->> 'appId', strpos(qrCodeRecord.ios_config::jsonb ->> 'appId', '.') + 1);
|
||||
SELECT id INTO iosAppId FROM mobile_app WHERE pkg_name = iosPkgName AND platform_type = 'IOS';
|
||||
IF iosAppId IS NULL THEN
|
||||
iosAppId := uuid_generate_v4();
|
||||
INSERT INTO mobile_app(id, created_time, tenant_id, pkg_name, platform_type, status, store_info)
|
||||
VALUES (iosAppId, (extract(epoch from now()) * 1000), qrCodeRecord.tenant_id,
|
||||
iosPkgName, 'IOS', 'DRAFT', qrCodeRecord.ios_config);
|
||||
IF generatedBundleId IS NULL THEN
|
||||
generatedBundleId := uuid_generate_v4();
|
||||
INSERT INTO mobile_app_bundle(id, created_time, tenant_id, title, ios_app_id)
|
||||
VALUES (generatedBundleId, (extract(epoch from now()) * 1000), qrCodeRecord.tenant_id, iosPkgName || ' (autogenerated)', iosAppId);
|
||||
UPDATE qr_code_settings SET mobile_app_bundle_id = generatedBundleId,
|
||||
ios_enabled = (qrCodeRecord.ios_config::jsonb ->> 'enabled')::boolean WHERE id = qrCodeRecord.id;
|
||||
ELSE
|
||||
UPDATE mobile_app_bundle SET ios_app_id = iosAppId WHERE id = generatedBundleId;
|
||||
END IF;
|
||||
ELSE
|
||||
UPDATE mobile_app_bundle SET ios_app_id = iosAppId WHERE id = generatedBundleId;
|
||||
UPDATE qr_code_settings SET mobile_app_bundle_id = (SELECT id FROM mobile_app_bundle WHERE mobile_app_bundle.ios_app_id = iosAppId),
|
||||
ios_enabled = (qrCodeRecord.ios_config::jsonb -> 'enabled')::boolean WHERE id = qrCodeRecord.id;
|
||||
UPDATE mobile_app SET store_info = qrCodeRecord.ios_config::jsonb - 'enabled' WHERE id = iosAppId;
|
||||
END IF;
|
||||
ELSE
|
||||
UPDATE mobile_app SET store_info = qrCodeRecord.ios_config WHERE id = iosAppId;
|
||||
UPDATE qr_code_settings SET mobile_app_bundle_id = (SELECT id FROM mobile_app_bundle WHERE mobile_app_bundle.ios_app_id = iosAppId) WHERE id = qrCodeRecord.id;
|
||||
END IF;
|
||||
END LOOP;
|
||||
ALTER TABLE qr_code_settings RENAME CONSTRAINT mobile_app_settings_tenant_id_unq_key TO qr_code_settings_tenant_id_unq_key;
|
||||
|
||||
@ -95,14 +95,13 @@ public class QrCodeSettingsController extends BaseController {
|
||||
private final SystemSecurityService systemSecurityService;
|
||||
private final MobileAppSecretService mobileAppSecretService;
|
||||
private final QrCodeSettingService qrCodeSettingService;
|
||||
private final MobileAppService mobileAppService;
|
||||
|
||||
@ApiOperation(value = "Get associated android applications (getAssetLinks)")
|
||||
@GetMapping(value = "/.well-known/assetlinks.json")
|
||||
public ResponseEntity<JsonNode> getAssetLinks() {
|
||||
MobileApp mobileApp = qrCodeSettingService.findAppFromQrCodeSettings(TenantId.SYS_TENANT_ID, ANDROID);
|
||||
StoreInfo storeInfo = mobileApp != null ? mobileApp.getStoreInfo() : null;
|
||||
if (storeInfo != null && storeInfo.isEnabled() && storeInfo.getSha256CertFingerprints() != null) {
|
||||
if (storeInfo != null && storeInfo.getSha256CertFingerprints() != null) {
|
||||
return ResponseEntity.ok(JacksonUtil.toJsonNode(String.format(ASSET_LINKS_PATTERN, mobileApp.getPkgName(), storeInfo.getSha256CertFingerprints())));
|
||||
} else {
|
||||
return ResponseEntity.notFound().build();
|
||||
@ -114,7 +113,7 @@ public class QrCodeSettingsController extends BaseController {
|
||||
public ResponseEntity<JsonNode> getAppleAppSiteAssociation() {
|
||||
MobileApp mobileApp = qrCodeSettingService.findAppFromQrCodeSettings(TenantId.SYS_TENANT_ID, IOS);
|
||||
StoreInfo storeInfo = mobileApp != null ? mobileApp.getStoreInfo() : null;
|
||||
if (storeInfo != null && storeInfo.isEnabled() && storeInfo.getAppId() != null) {
|
||||
if (storeInfo != null && storeInfo.getAppId() != null) {
|
||||
return ResponseEntity.ok(JacksonUtil.toJsonNode(String.format(APPLE_APP_SITE_ASSOCIATION_PATTERN, storeInfo.getAppId())));
|
||||
} else {
|
||||
return ResponseEntity.notFound().build();
|
||||
@ -177,14 +176,13 @@ public class QrCodeSettingsController extends BaseController {
|
||||
@GetMapping(value = "/api/noauth/qr")
|
||||
public ResponseEntity<?> getApplicationRedirect(@RequestHeader(value = "User-Agent") String userAgent) {
|
||||
QrCodeSettings qrCodeSettings = qrCodeSettingService.findQrCodeSettings(TenantId.SYS_TENANT_ID);
|
||||
boolean useDefaultApp = qrCodeSettings.isUseDefaultApp();
|
||||
if (userAgent.contains("Android")) {
|
||||
String googlePlayLink = useDefaultApp ? qrCodeSettings.getGooglePlayLink() : getStoreLink(qrCodeSettings.getMobileAppBundleId(), ANDROID);
|
||||
if (userAgent.contains("Android") && qrCodeSettings.isAndroidEnabled()) {
|
||||
String googlePlayLink = qrCodeSettings.getGooglePlayLink();
|
||||
return ResponseEntity.status(HttpStatus.FOUND)
|
||||
.header("Location", googlePlayLink)
|
||||
.build();
|
||||
} else if (userAgent.contains("iPhone") || userAgent.contains("iPad")) {
|
||||
String appStoreLink = useDefaultApp ? qrCodeSettings.getAppStoreLink() : getStoreLink(qrCodeSettings.getMobileAppBundleId(), IOS);
|
||||
} else if (userAgent.contains("iPhone") || userAgent.contains("iPad") && qrCodeSettings.isIosEnabled()) {
|
||||
String appStoreLink = qrCodeSettings.getAppStoreLink();
|
||||
return ResponseEntity.status(HttpStatus.FOUND)
|
||||
.header("Location", appStoreLink)
|
||||
.build();
|
||||
@ -193,12 +191,4 @@ public class QrCodeSettingsController extends BaseController {
|
||||
}
|
||||
}
|
||||
|
||||
private String getStoreLink(MobileAppBundleId mobileAppBundleId, PlatformType platformType) {
|
||||
if (mobileAppBundleId == null) {
|
||||
return null;
|
||||
}
|
||||
MobileApp mobileApp = mobileAppService.findByBundleIdAndPlatformType(TenantId.SYS_TENANT_ID, mobileAppBundleId, platformType);
|
||||
return (mobileApp != null && mobileApp.getStoreInfo() != null) ? mobileApp.getStoreInfo().getStoreLink() : null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -70,7 +70,6 @@ public class QrCodeSettingsControllerTest extends AbstractControllerTest {
|
||||
StoreInfo androidStoreInfo = StoreInfo.builder()
|
||||
.sha256CertFingerprints(ANDROID_APP_SHA256)
|
||||
.storeLink(ANDROID_STORE_LINK)
|
||||
.enabled(true)
|
||||
.build();
|
||||
androidApp.setStoreInfo(androidStoreInfo);
|
||||
MobileApp savedAndroidApp = doPost("/api/mobile/app", androidApp, MobileApp.class);
|
||||
@ -78,7 +77,6 @@ public class QrCodeSettingsControllerTest extends AbstractControllerTest {
|
||||
MobileApp iosApp = validMobileApp( "my.ios.package", PlatformType.IOS);
|
||||
StoreInfo iosQrCodeConfig = StoreInfo.builder()
|
||||
.appId(APPLE_APP_ID)
|
||||
.enabled(true)
|
||||
.storeLink(IOS_STORE_LINK)
|
||||
.build();
|
||||
iosApp.setStoreInfo(iosQrCodeConfig);
|
||||
|
||||
@ -33,6 +33,7 @@ import org.thingsboard.server.common.data.ApiUsageState;
|
||||
import org.thingsboard.server.common.data.AttributeScope;
|
||||
import org.thingsboard.server.common.data.Device;
|
||||
import org.thingsboard.server.common.data.EventInfo;
|
||||
import org.thingsboard.server.common.data.StringUtils;
|
||||
import org.thingsboard.server.common.data.alarm.Alarm;
|
||||
import org.thingsboard.server.common.data.alarm.AlarmSeverity;
|
||||
import org.thingsboard.server.common.data.alarm.EntityAlarm;
|
||||
@ -45,6 +46,9 @@ import org.thingsboard.server.common.data.id.AlarmId;
|
||||
import org.thingsboard.server.common.data.id.AssetId;
|
||||
import org.thingsboard.server.common.data.id.DeviceId;
|
||||
import org.thingsboard.server.common.data.id.EntityId;
|
||||
import org.thingsboard.server.common.data.id.MobileAppBundleId;
|
||||
import org.thingsboard.server.common.data.id.MobileAppId;
|
||||
import org.thingsboard.server.common.data.id.OAuth2ClientId;
|
||||
import org.thingsboard.server.common.data.id.RuleChainId;
|
||||
import org.thingsboard.server.common.data.id.RuleNodeId;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
@ -54,7 +58,12 @@ import org.thingsboard.server.common.data.kv.BaseReadTsKvQuery;
|
||||
import org.thingsboard.server.common.data.kv.BasicTsKvEntry;
|
||||
import org.thingsboard.server.common.data.kv.StringDataEntry;
|
||||
import org.thingsboard.server.common.data.kv.TsKvEntry;
|
||||
import org.thingsboard.server.common.data.mobile.app.MobileApp;
|
||||
import org.thingsboard.server.common.data.mobile.app.MobileAppStatus;
|
||||
import org.thingsboard.server.common.data.mobile.bundle.MobileAppBundle;
|
||||
import org.thingsboard.server.common.data.msg.TbNodeConnectionType;
|
||||
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
|
||||
import org.thingsboard.server.common.data.oauth2.PlatformType;
|
||||
import org.thingsboard.server.common.data.page.TimePageLink;
|
||||
import org.thingsboard.server.common.data.relation.EntityRelation;
|
||||
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
|
||||
@ -233,6 +242,27 @@ public class HousekeeperServiceTest extends AbstractControllerTest {
|
||||
tenantId = differentTenantId;
|
||||
|
||||
createRelatedData(tenantId);
|
||||
|
||||
MobileApp androidApp = validMobileApp(TenantId.SYS_TENANT_ID, "my.android.package", PlatformType.ANDROID);
|
||||
androidApp = doPost("/api/mobile/app", androidApp, MobileApp.class);
|
||||
MobileAppId androidAppId = androidApp.getId();
|
||||
|
||||
MobileApp iosApp = validMobileApp(TenantId.SYS_TENANT_ID, "my.ios.package", PlatformType.IOS);
|
||||
iosApp = doPost("/api/mobile/app", iosApp, MobileApp.class);
|
||||
MobileAppId iosAppId = androidApp.getId();
|
||||
|
||||
OAuth2Client oAuth2Client = createOauth2Client(TenantId.SYS_TENANT_ID, "test google client");
|
||||
OAuth2Client savedOAuth2Client = doPost("/api/oauth2/client", oAuth2Client, OAuth2Client.class);
|
||||
OAuth2ClientId oAuth2ClientId = savedOAuth2Client.getId();
|
||||
|
||||
MobileAppBundle mobileAppBundle = new MobileAppBundle();
|
||||
mobileAppBundle.setTitle("Test bundle");
|
||||
mobileAppBundle.setAndroidAppId(androidApp.getId());
|
||||
mobileAppBundle.setIosAppId(iosApp.getId());
|
||||
|
||||
MobileAppBundle savedAppBundle = doPost("/api/mobile/bundle?oauth2ClientIds=" + savedOAuth2Client.getId().getId(), mobileAppBundle, MobileAppBundle.class);
|
||||
MobileAppBundleId appBundleId = savedAppBundle.getId();
|
||||
|
||||
createDifferentTenantCustomer();
|
||||
createRelatedData(differentTenantCustomerId);
|
||||
loginDifferentTenant();
|
||||
@ -279,6 +309,10 @@ public class HousekeeperServiceTest extends AbstractControllerTest {
|
||||
verifyNoRelatedData(userId);
|
||||
verifyNoRelatedData(differentTenantCustomerId);
|
||||
verifyNoRelatedData(tenantApiUsageState.getId());
|
||||
verifyNoRelatedData(androidAppId);
|
||||
verifyNoRelatedData(iosAppId);
|
||||
verifyNoRelatedData(oAuth2ClientId);
|
||||
verifyNoRelatedData(appBundleId);
|
||||
verifyNoRelatedData(tenantId);
|
||||
});
|
||||
}
|
||||
@ -483,4 +517,14 @@ public class HousekeeperServiceTest extends AbstractControllerTest {
|
||||
return ruleChainService.loadRuleChainMetaData(tenantId, ruleChainId);
|
||||
}
|
||||
|
||||
private MobileApp validMobileApp(TenantId tenantId, String mobileAppName, PlatformType platformType) {
|
||||
MobileApp mobileApp = new MobileApp();
|
||||
mobileApp.setTenantId(tenantId);
|
||||
mobileApp.setStatus(MobileAppStatus.DRAFT);
|
||||
mobileApp.setPkgName(mobileAppName);
|
||||
mobileApp.setPlatformType(platformType);
|
||||
mobileApp.setAppSecret(StringUtils.randomAlphanumeric(24));
|
||||
return mobileApp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -23,7 +23,6 @@ import org.thingsboard.server.common.data.validation.NoXss;
|
||||
@Builder
|
||||
public class StoreInfo {
|
||||
|
||||
private boolean enabled;
|
||||
@NoXss
|
||||
private String appId;
|
||||
@NoXss
|
||||
|
||||
@ -44,10 +44,12 @@ public class QrCodeSettings extends BaseData<QrCodeSettingsId> implements HasTen
|
||||
@Valid
|
||||
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, description = "QR code config configuration.")
|
||||
private QRCodeConfig qrCodeConfig;
|
||||
|
||||
@Schema(description = "Indicates if google play link is available", example = "true")
|
||||
private boolean androidEnabled;
|
||||
@Schema(description = "Indicates if apple store link is available", example = "true")
|
||||
private boolean iosEnabled;
|
||||
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||
private String googlePlayLink;
|
||||
|
||||
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||
private String appStoreLink;
|
||||
|
||||
|
||||
@ -56,7 +56,7 @@ public class MobileAppServiceImpl extends AbstractEntityService implements Mobil
|
||||
return savedMobileApp;
|
||||
} catch (Exception e) {
|
||||
checkConstraintViolation(e,
|
||||
Map.of("mobile_app_unq_key", "Mobile app with such package already exists!"));
|
||||
Map.of("mobile_app_pkg_name_platform_unq_key", "Mobile app with such package name and platform already exists!"));
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,10 +119,10 @@ public class QrCodeSettingServiceImpl extends AbstractCachedEntityService<Tenant
|
||||
} else {
|
||||
MobileApp androidApp = mobileAppService.findByBundleIdAndPlatformType(qrCodeSettings.getTenantId(), qrCodeSettings.getMobileAppBundleId(), ANDROID);
|
||||
MobileApp iosApp = mobileAppService.findByBundleIdAndPlatformType(qrCodeSettings.getTenantId(), qrCodeSettings.getMobileAppBundleId(), IOS);
|
||||
if (androidApp != null && androidApp.getStoreInfo() != null && androidApp.getStoreInfo().isEnabled()) {
|
||||
if (androidApp != null && androidApp.getStoreInfo() != null) {
|
||||
qrCodeSettings.setGooglePlayLink(androidApp.getStoreInfo().getStoreLink());
|
||||
}
|
||||
if (iosApp != null && iosApp.getStoreInfo() != null && iosApp.getStoreInfo().isEnabled()) {
|
||||
if (iosApp != null && iosApp.getStoreInfo() != null) {
|
||||
qrCodeSettings.setAppStoreLink(iosApp.getStoreInfo().getStoreLink());
|
||||
}
|
||||
}
|
||||
|
||||
@ -701,6 +701,8 @@ public class ModelConstants {
|
||||
*/
|
||||
public static final String QR_CODE_SETTINGS_TABLE_NAME = "qr_code_settings";
|
||||
public static final String QR_CODE_SETTINGS_USE_DEFAULT_APP_PROPERTY = "use_default_app";
|
||||
public static final String QR_CODE_SETTINGS_ANDROID_ENABLED_PROPERTY = "android_enabled";
|
||||
public static final String QR_CODE_SETTINGS_IOS_ENABLED_PROPERTY = "ios_enabled";
|
||||
public static final String QR_CODE_SETTINGS_BUNDLE_ID_PROPERTY = "mobile_app_bundle_id";
|
||||
public static final String QR_CODE_SETTINGS_CONFIG_PROPERTY = "qr_code_config";
|
||||
|
||||
|
||||
@ -47,6 +47,12 @@ public class QrCodeSettingsEntity extends BaseSqlEntity<QrCodeSettings> {
|
||||
@Column(name = ModelConstants.QR_CODE_SETTINGS_USE_DEFAULT_APP_PROPERTY)
|
||||
private boolean useDefaultApp;
|
||||
|
||||
@Column(name = ModelConstants.QR_CODE_SETTINGS_ANDROID_ENABLED_PROPERTY)
|
||||
private boolean androidEnabled;
|
||||
|
||||
@Column(name = ModelConstants.QR_CODE_SETTINGS_IOS_ENABLED_PROPERTY)
|
||||
private boolean iosEnabled;
|
||||
|
||||
@Column(name = ModelConstants.QR_CODE_SETTINGS_BUNDLE_ID_PROPERTY)
|
||||
private UUID mobileAppBundleId;
|
||||
|
||||
@ -59,6 +65,8 @@ public class QrCodeSettingsEntity extends BaseSqlEntity<QrCodeSettings> {
|
||||
this.setCreatedTime(qrCodeSettings.getCreatedTime());
|
||||
this.tenantId = qrCodeSettings.getTenantId().getId();
|
||||
this.useDefaultApp = qrCodeSettings.isUseDefaultApp();
|
||||
this.androidEnabled = qrCodeSettings.isAndroidEnabled();
|
||||
this.iosEnabled = qrCodeSettings.isIosEnabled();
|
||||
if (qrCodeSettings.getMobileAppBundleId() != null) {
|
||||
this.mobileAppBundleId = qrCodeSettings.getMobileAppBundleId().getId();
|
||||
}
|
||||
@ -71,6 +79,8 @@ public class QrCodeSettingsEntity extends BaseSqlEntity<QrCodeSettings> {
|
||||
qrCodeSettings.setCreatedTime(createdTime);
|
||||
qrCodeSettings.setTenantId(TenantId.fromUUID(tenantId));
|
||||
qrCodeSettings.setUseDefaultApp(useDefaultApp);
|
||||
qrCodeSettings.setAndroidEnabled(androidEnabled);
|
||||
qrCodeSettings.setIosEnabled(iosEnabled);
|
||||
if (mobileAppBundleId != null) {
|
||||
qrCodeSettings.setMobileAppBundleId(new MobileAppBundleId(mobileAppBundleId));
|
||||
}
|
||||
|
||||
@ -31,12 +31,12 @@ public class MobileAppDataValidator extends DataValidator<MobileApp> {
|
||||
@Override
|
||||
protected void validateDataImpl(TenantId tenantId, MobileApp mobileApp) {
|
||||
if (mobileApp.getPlatformType() == PlatformType.ANDROID) {
|
||||
if (mobileApp.getStoreInfo() != null && mobileApp.getStoreInfo().isEnabled() &&
|
||||
if (mobileApp.getStoreInfo() != null &&
|
||||
(mobileApp.getStoreInfo().getSha256CertFingerprints() == null || mobileApp.getStoreInfo().getStoreLink() == null)) {
|
||||
throw new DataValidationException("Sha256CertFingerprints and store link are required");
|
||||
}
|
||||
} else if (mobileApp.getPlatformType() == PlatformType.IOS) {
|
||||
if (mobileApp.getStoreInfo() != null && mobileApp.getStoreInfo().isEnabled() &&
|
||||
if (mobileApp.getStoreInfo() != null &&
|
||||
(mobileApp.getStoreInfo().getAppId() == null || mobileApp.getStoreInfo().getStoreLink() == null)) {
|
||||
throw new DataValidationException("AppId and store link are required");
|
||||
}
|
||||
|
||||
@ -127,3 +127,5 @@ CREATE INDEX IF NOT EXISTS idx_resource_etag ON resource(tenant_id, etag);
|
||||
CREATE INDEX IF NOT EXISTS idx_resource_etag ON resource(tenant_id, etag);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_resource_type_public_resource_key ON resource(resource_type, public_resource_key);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS mobile_app_bundle_tenant_id ON mobile_app_bundle(tenant_id);
|
||||
|
||||
@ -628,7 +628,7 @@ CREATE TABLE IF NOT EXISTS mobile_app (
|
||||
status varchar(32),
|
||||
version_info varchar(100000),
|
||||
store_info varchar(16384),
|
||||
CONSTRAINT pkg_name_platform_unique UNIQUE (pkg_name, platform_type)
|
||||
CONSTRAINT mobile_app_pkg_name_platform_unq_key UNIQUE (pkg_name, platform_type)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS mobile_app_bundle (
|
||||
|
||||
@ -126,6 +126,7 @@ import org.thingsboard.server.common.data.kv.AttributeKvEntry;
|
||||
import org.thingsboard.server.common.data.kv.TsKvEntry;
|
||||
import org.thingsboard.server.common.data.mobile.app.MobileApp;
|
||||
import org.thingsboard.server.common.data.mobile.bundle.MobileAppBundle;
|
||||
import org.thingsboard.server.common.data.mobile.bundle.MobileAppBundleInfo;
|
||||
import org.thingsboard.server.common.data.oauth2.OAuth2Client;
|
||||
import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo;
|
||||
import org.thingsboard.server.common.data.oauth2.OAuth2ClientLoginInfo;
|
||||
@ -2108,12 +2109,12 @@ public class RestClient implements Closeable {
|
||||
}, params).getBody();
|
||||
}
|
||||
|
||||
public List<OAuth2ClientInfo> getTenantOAuth2Clients() {
|
||||
public PageData<OAuth2ClientInfo> getTenantOAuth2Clients() {
|
||||
return restTemplate.exchange(
|
||||
baseURL + "/api/oauth2/client/infos",
|
||||
HttpMethod.GET,
|
||||
HttpEntity.EMPTY,
|
||||
new ParameterizedTypeReference<List<OAuth2ClientInfo>>() {
|
||||
new ParameterizedTypeReference<PageData<OAuth2ClientInfo>>() {
|
||||
}).getBody();
|
||||
}
|
||||
|
||||
@ -2138,12 +2139,12 @@ public class RestClient implements Closeable {
|
||||
restTemplate.delete(baseURL + "/api/oauth2/client/{id}", oAuth2ClientId.getId());
|
||||
}
|
||||
|
||||
public List<DomainInfo> getTenantDomainInfos() {
|
||||
public PageData<DomainInfo> getTenantDomainInfos() {
|
||||
return restTemplate.exchange(
|
||||
baseURL + "/api/domain/infos",
|
||||
HttpMethod.GET,
|
||||
HttpEntity.EMPTY,
|
||||
new ParameterizedTypeReference<List<DomainInfo>>() {
|
||||
new ParameterizedTypeReference<PageData<DomainInfo>>() {
|
||||
}).getBody();
|
||||
}
|
||||
|
||||
@ -2172,12 +2173,12 @@ public class RestClient implements Closeable {
|
||||
restTemplate.postForLocation(baseURL + "/api/domain/{id}/oauth2Clients", oauth2ClientIds, domainId.getId());
|
||||
}
|
||||
|
||||
public List<DomainInfo> getTenantMobileApps() {
|
||||
public PageData<MobileApp> getTenantMobileApps() {
|
||||
return restTemplate.exchange(
|
||||
baseURL + "/api/mobile/app",
|
||||
HttpMethod.GET,
|
||||
HttpEntity.EMPTY,
|
||||
new ParameterizedTypeReference<List<DomainInfo>>() {
|
||||
new ParameterizedTypeReference<PageData<MobileApp>>() {
|
||||
}).getBody();
|
||||
}
|
||||
|
||||
@ -2202,18 +2203,18 @@ public class RestClient implements Closeable {
|
||||
restTemplate.delete(baseURL + "/api/mobile/app/{id}", mobileAppId.getId());
|
||||
}
|
||||
|
||||
public List<DomainInfo> getTenantMobileBundleInfos() {
|
||||
public PageData<MobileAppBundleInfo> getTenantMobileBundleInfos() {
|
||||
return restTemplate.exchange(
|
||||
baseURL + "/api/mobile/bundle/infos",
|
||||
HttpMethod.GET,
|
||||
HttpEntity.EMPTY,
|
||||
new ParameterizedTypeReference<List<DomainInfo>>() {
|
||||
new ParameterizedTypeReference<PageData<MobileAppBundleInfo>>() {
|
||||
}).getBody();
|
||||
}
|
||||
|
||||
public Optional<MobileAppBundle> getMobileBundleById(MobileAppBundleId mobileAppBundleId) {
|
||||
try {
|
||||
ResponseEntity<MobileAppBundle> mobileApp = restTemplate.getForEntity(baseURL + "/api/mobile/app/{id}", MobileAppBundle.class, mobileAppBundleId.getId());
|
||||
ResponseEntity<MobileAppBundle> mobileApp = restTemplate.getForEntity(baseURL + "/api/mobile/bundle/{id}", MobileAppBundle.class, mobileAppBundleId.getId());
|
||||
return Optional.ofNullable(mobileApp.getBody());
|
||||
} catch (HttpClientErrorException exception) {
|
||||
if (exception.getStatusCode() == HttpStatus.NOT_FOUND) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user