From 951f017e7c70d79c51887e846202636740aceff3 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Thu, 6 Jun 2024 11:53:02 +0300 Subject: [PATCH] extended mobile application settings with default store links --- .../MobileApplicationController.java | 12 ++++++---- .../src/main/resources/thingsboard.yml | 15 +++++++++--- .../common/data/mobile/MobileAppSettings.java | 17 +++++++++++++ .../mobile/BaseMobileAppSettingsService.java | 24 +++++++++---------- 4 files changed, 48 insertions(+), 20 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/MobileApplicationController.java b/application/src/main/java/org/thingsboard/server/controller/MobileApplicationController.java index 486eac4444..b736da8ab4 100644 --- a/application/src/main/java/org/thingsboard/server/controller/MobileApplicationController.java +++ b/application/src/main/java/org/thingsboard/server/controller/MobileApplicationController.java @@ -58,6 +58,8 @@ public class MobileApplicationController extends BaseController { @Value("${cache.specs.mobileSecretKey.timeToLiveInMinutes:2}") private int mobileSecretKeyTtl; + @Value("${mobileApp.domain:demo.thingsboard.io}") + private String defaultAppDomain; public static final String ASSET_LINKS_PATTERN = "[{\n" + " \"relation\": [\"delegate_permission/common.handle_all_urls\"],\n" + @@ -83,7 +85,6 @@ public class MobileApplicationController extends BaseController { public static final String SECRET = "secret"; public static final String SECRET_PARAM_DESCRIPTION = "A string value representing short-lived secret key"; - public static final String DEFAULT_APP_DOMAIN = "demo.thingsboard.io"; public static final String DEEP_LINK_PATTERN = "https://%s/api/noauth/qr?secret=%s&ttl=%s"; private final SystemSecurityService systemSecurityService; @@ -149,7 +150,7 @@ public class MobileApplicationController extends BaseController { if (!mobileAppSettings.isUseDefaultApp()) { appDomain = platformDomain; } else { - appDomain = DEFAULT_APP_DOMAIN; + appDomain = defaultAppDomain; } String deepLink = String.format(DEEP_LINK_PATTERN, appDomain, secret, mobileSecretKeyTtl); if (!appDomain.equals(platformDomain)) { @@ -170,13 +171,16 @@ public class MobileApplicationController extends BaseController { @GetMapping(value = "/api/noauth/qr") public ResponseEntity getApplicationRedirect(@RequestHeader(value = "User-Agent") String userAgent) { MobileAppSettings mobileAppSettings = mobileAppSettingsService.getMobileAppSettings(TenantId.SYS_TENANT_ID); + boolean useDefaultApp = mobileAppSettings.isUseDefaultApp(); + String googlePlayLink = useDefaultApp ? mobileAppSettings.getDefaultGooglePlayLink() : mobileAppSettings.getAndroidConfig().getStoreLink(); + String appStoreLink = useDefaultApp ? mobileAppSettings.getDefaultGooglePlayLink() : mobileAppSettings.getIosConfig().getStoreLink(); if (userAgent.contains("Android")) { return ResponseEntity.status(HttpStatus.FOUND) - .header("Location", mobileAppSettings.getAndroidConfig().getStoreLink()) + .header("Location", googlePlayLink) .build(); } else if (userAgent.contains("iPhone") || userAgent.contains("iPad")) { return ResponseEntity.status(HttpStatus.FOUND) - .header("Location", mobileAppSettings.getIosConfig().getStoreLink()) + .header("Location", appStoreLink) .build(); } else { return ResponseEntity.status(HttpStatus.NOT_FOUND) diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 454ca9427f..d61c376a83 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -1463,9 +1463,9 @@ queue: - key: max.poll.interval.ms # Example of specific consumer properties value per topic for VC value: "${TB_QUEUE_KAFKA_VC_MAX_POLL_INTERVAL_MS:600000}" - # tb_rule_engine.sq: - # - key: max.poll.records - # value: "${TB_QUEUE_KAFKA_SQ_MAX_POLL_RECORDS:1024}" + # tb_rule_engine.sq: + # - key: max.poll.records + # value: "${TB_QUEUE_KAFKA_SQ_MAX_POLL_RECORDS:1024}" tb_housekeeper: # Consumer properties for Housekeeper tasks topic - key: max.poll.records @@ -1794,3 +1794,12 @@ management: elasticsearch: # Enable the org.springframework.boot.actuate.elasticsearch.ElasticsearchRestClientHealthIndicator.doHealthCheck enabled: "false" + +# Mobile application settings for Thingsboard mobile application +mobileApp: + # Host for default Thingsboard mobile application for common edition + domain: "${TB_MOBILE_APP_DOMAIN:demo.thingsboard.io}" + # Link to Google Play store for default Thingsboard mobile application + googlePlayLink: "${TB_MOBILE_APP_GOOGLE_PLAY_LINK:https://play.google.com/store/apps/details?id=org.thingsboard.demo.app}" + # Link to App Store for default Thingsboard mobile application + appStoreLink: "${TB_MOBILE_APP_APP_STORE_LINK:https://apps.apple.com/us/app/thingsboard-live/id1594355695}" diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/mobile/MobileAppSettings.java b/common/data/src/main/java/org/thingsboard/server/common/data/mobile/MobileAppSettings.java index 9a7b88f22c..31b2029bfc 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/mobile/MobileAppSettings.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/mobile/MobileAppSettings.java @@ -15,29 +15,46 @@ */ package org.thingsboard.server.common.data.mobile; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.Valid; import lombok.Data; +import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.BaseData; import org.thingsboard.server.common.data.HasTenantId; import org.thingsboard.server.common.data.id.MobileAppSettingsId; import org.thingsboard.server.common.data.id.TenantId; +@Schema @Data +@EqualsAndHashCode(callSuper = true) public class MobileAppSettings extends BaseData implements HasTenantId { private static final long serialVersionUID = 2628323657987010348L; + @Schema(description = "JSON object with Tenant Id.", accessMode = Schema.AccessMode.READ_ONLY) private TenantId tenantId; + @Schema(requiredMode = Schema.RequiredMode.REQUIRED, description = "Type of application: true means use default Thingsboard app", example = "true") private boolean useDefaultApp; @Valid + @Schema(requiredMode = Schema.RequiredMode.REQUIRED, description = "Android mobile app configuration.") private AndroidConfig androidConfig; @Valid + @Schema(requiredMode = Schema.RequiredMode.REQUIRED, description = "Ios mobile app configuration.") private IosConfig iosConfig; @Valid + @Schema(requiredMode = Schema.RequiredMode.REQUIRED, description = "QR code config configuration.") private QRCodeConfig qrCodeConfig; + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + private String defaultGooglePlayLink; + + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + private String defaultAppStoreLink; + public MobileAppSettings() { } + public MobileAppSettings(MobileAppSettingsId id) { super(id); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/mobile/BaseMobileAppSettingsService.java b/dao/src/main/java/org/thingsboard/server/dao/mobile/BaseMobileAppSettingsService.java index 4c67d97884..bb445426f1 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/mobile/BaseMobileAppSettingsService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/mobile/BaseMobileAppSettingsService.java @@ -17,9 +17,9 @@ package org.thingsboard.server.dao.mobile; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.event.TransactionalEventListener; -import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.mobile.AndroidConfig; import org.thingsboard.server.common.data.mobile.BadgePosition; @@ -40,8 +40,11 @@ public class BaseMobileAppSettingsService extends AbstractCachedEntityService mobileAppSettingsDataValidator; @@ -52,7 +55,7 @@ public class BaseMobileAppSettingsService extends AbstractCachedEntityService