refactoring

This commit is contained in:
dashevchenko 2024-10-21 18:54:22 +03:00
parent ccc29db76a
commit fb87cd6df7
13 changed files with 107 additions and 13 deletions

View File

@ -75,7 +75,7 @@ $$
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,
'App bundle ' || mobileAppRecord.pkg_name, mobileAppRecord.id, iosAppId, mobileAppRecord.oauth2_enabled);
'Autogenerated for ' || mobileAppRecord.pkg_name, mobileAppRecord.id, iosAppId, mobileAppRecord.oauth2_enabled);
UPDATE mobile_app_bundle_oauth2_client SET mobile_app_bundle_id = generatedBundleId WHERE mobile_app_bundle_id = mobileAppRecord.id;
END LOOP;
END IF;
@ -110,10 +110,10 @@ $$
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', 'PUBLISHED', qrCodeRecord.android_config::jsonb - 'appPackage');
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, 'App bundle for qr code', androidAppId);
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;
@ -127,11 +127,11 @@ $$
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', 'PUBLISHED', qrCodeRecord.ios_config);
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, 'App bundle for qr code', iosAppId);
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;
ELSE
UPDATE mobile_app_bundle SET ios_app_id = iosAppId WHERE id = generatedBundleId;

View File

@ -15,6 +15,8 @@
*/
package org.thingsboard.server.controller;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.RequiredArgsConstructor;
@ -22,21 +24,26 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.HomeDashboardInfo;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.Views;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.mobile.LoginMobileInfo;
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.app.MobileAppVersionInfo;
import org.thingsboard.server.common.data.mobile.UserMobileInfo;
import org.thingsboard.server.common.data.mobile.layout.MobilePage;
import org.thingsboard.server.common.data.oauth2.OAuth2ClientLoginInfo;
import org.thingsboard.server.common.data.oauth2.PlatformType;
import org.thingsboard.server.config.annotations.ApiOperation;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.security.model.SecurityUser;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import static org.thingsboard.server.controller.ControllerConstants.AVAILABLE_FOR_ANY_AUTHORIZED_USER;
@ -62,12 +69,12 @@ public class MobileV2Controller extends BaseController {
public UserMobileInfo getUserMobileInfo(@Parameter(description = "Mobile application package name")
@RequestParam String pkgName,
@Parameter(description = "Platform type", schema = @Schema(allowableValues = {"ANDROID", "IOS"}))
@RequestParam PlatformType platform) throws ThingsboardException {
@RequestParam PlatformType platform) throws ThingsboardException, JsonProcessingException {
SecurityUser securityUser = getCurrentUser();
User user = userService.findUserById(securityUser.getTenantId(), securityUser.getId());
HomeDashboardInfo homeDashboardInfo = securityUser.isSystemAdmin() ? null : getHomeDashboardInfo(securityUser, user.getAdditionalInfo());
MobileAppBundle mobileAppBundle = mobileAppBundleService.findMobileAppBundleByPkgNameAndPlatform(securityUser.getTenantId(), pkgName, platform);
return new UserMobileInfo(user, homeDashboardInfo, mobileAppBundle != null ? mobileAppBundle.getLayoutConfig() : null);
return new UserMobileInfo(user, homeDashboardInfo, getVisiblePages(mobileAppBundle));
}
@ApiOperation(value = "Get mobile app version info (getMobileVersionInfo)")
@ -80,4 +87,16 @@ public class MobileV2Controller extends BaseController {
return mobileApp != null ? mobileApp.getVersionInfo() : null;
}
private List<MobilePage> getVisiblePages(MobileAppBundle mobileAppBundle) throws JsonProcessingException {
if (mobileAppBundle != null && mobileAppBundle.getLayoutConfig() != null) {
List<MobilePage> mobilePages = mobileAppBundle.getLayoutConfig().getPages()
.stream()
.filter(MobilePage::isVisible)
.collect(Collectors.toList());
return JacksonUtil.readValue(JacksonUtil.writeValueAsViewIgnoringNullFields(mobilePages, Views.Public.class), new TypeReference<>() {});
} else {
return Collections.emptyList();
}
}
}

View File

@ -125,7 +125,7 @@ public class QrCodeSettingsController extends BaseController {
notes = "The request payload contains configuration for android/iOS applications and platform qr code widget settings." + SYSTEM_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAnyAuthority('SYS_ADMIN')")
@PostMapping(value = "/api/mobile/qr/settings")
public QrCodeSettings saveMobileAppSettings(@Parameter(description = "A JSON value representing the mobile apps configuration")
public QrCodeSettings saveQrCodeSettings(@Parameter(description = "A JSON value representing the mobile apps configuration")
@RequestBody QrCodeSettings qrCodeSettings) throws ThingsboardException {
SecurityUser currentUser = getCurrentUser();
accessControlService.checkPermission(currentUser, Resource.QR_CODE_SETTINGS, Operation.WRITE);
@ -137,7 +137,7 @@ public class QrCodeSettingsController extends BaseController {
notes = "The response payload contains configuration for android/iOS applications and platform qr code widget settings." + AVAILABLE_FOR_ANY_AUTHORIZED_USER)
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@GetMapping(value = "/api/mobile/qr/settings")
public QrCodeSettings getMobileAppSettings() throws ThingsboardException {
public QrCodeSettings getQrAppSettings() throws ThingsboardException {
SecurityUser currentUser = getCurrentUser();
accessControlService.checkPermission(currentUser, Resource.QR_CODE_SETTINGS, Operation.READ);
return qrCodeSettingService.findQrCodeSettings(TenantId.SYS_TENANT_ID);

View File

@ -0,0 +1,36 @@
/**
* ThingsBoard, Inc. ("COMPANY") CONFIDENTIAL
*
* Copyright © 2016-2024 ThingsBoard, Inc. All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of ThingsBoard, Inc. and its suppliers,
* if any. The intellectual and technical concepts contained
* herein are proprietary to ThingsBoard, Inc.
* and its suppliers and may be covered by U.S. and Foreign Patents,
* patents in process, and are protected by trade secret or copyright law.
*
* Dissemination of this information or reproduction of this material is strictly forbidden
* unless prior written permission is obtained from COMPANY.
*
* Access to the source code contained herein is hereby forbidden to anyone except current COMPANY employees,
* managers or contractors who have executed Confidentiality and Non-disclosure agreements
* explicitly covering such access.
*
* The copyright notice above does not evidence any actual or intended publication
* or disclosure of this source code, which includes
* information that is confidential and/or proprietary, and is a trade secret, of COMPANY.
* ANY REPRODUCTION, MODIFICATION, DISTRIBUTION, PUBLIC PERFORMANCE,
* OR PUBLIC DISPLAY OF OR THROUGH USE OF THIS SOURCE CODE WITHOUT
* THE EXPRESS WRITTEN CONSENT OF COMPANY IS STRICTLY PROHIBITED,
* AND IN VIOLATION OF APPLICABLE LAWS AND INTERNATIONAL TREATIES.
* THE RECEIPT OR POSSESSION OF THIS SOURCE CODE AND/OR RELATED INFORMATION
* DOES NOT CONVEY OR IMPLY ANY RIGHTS TO REPRODUCE, DISCLOSE OR DISTRIBUTE ITS CONTENTS,
* OR TO MANUFACTURE, USE, OR SELL ANYTHING THAT IT MAY DESCRIBE, IN WHOLE OR IN PART.
*/
package org.thingsboard.server.common.data;
public class Views {
public static class Public {}
public static class Private extends Public {}
}

View File

@ -17,7 +17,9 @@ package org.thingsboard.server.common.data.mobile;
import org.thingsboard.server.common.data.HomeDashboardInfo;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.mobile.layout.MobileLayoutConfig;
import org.thingsboard.server.common.data.mobile.layout.MobilePage;
public record UserMobileInfo(User user, HomeDashboardInfo homeDashboardInfo, MobileLayoutConfig layoutConfig) {
import java.util.List;
public record UserMobileInfo(User user, HomeDashboardInfo homeDashboardInfo, List<MobilePage> pages) {
}

View File

@ -15,16 +15,21 @@
*/
package org.thingsboard.server.common.data.mobile.layout;
import com.fasterxml.jackson.annotation.JsonView;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.thingsboard.server.common.data.Views;
@Data
public abstract class AbstractMobilePage implements MobilePage {
@Schema(description = "Page label", example = "Air quality", requiredMode = Schema.RequiredMode.REQUIRED)
@JsonView(Views.Public.class)
protected String label;
@Schema(description = "Indicates if page is visible", example = "true", requiredMode = Schema.RequiredMode.REQUIRED)
@JsonView(Views.Private.class)
protected boolean visible;
@Schema(description = "URL of the page icon", example = "home_icon")
@JsonView(Views.Public.class)
protected String icon;
}

View File

@ -15,12 +15,14 @@
*/
package org.thingsboard.server.common.data.mobile.layout;
import com.fasterxml.jackson.annotation.JsonView;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.thingsboard.server.common.data.Views;
@Data
@Builder
@ -30,6 +32,7 @@ import lombok.NoArgsConstructor;
public class CustomMobilePage extends AbstractMobilePage {
@Schema(description = "Path", example = "")
@JsonView(Views.Public.class)
private String path;
@Override

View File

@ -15,21 +15,24 @@
*/
package org.thingsboard.server.common.data.mobile.layout;
import com.fasterxml.jackson.annotation.JsonView;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.thingsboard.server.common.data.Views;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class DashdoardPage extends AbstractMobilePage {
public class DashboardPage extends AbstractMobilePage {
@Schema(description = "Dashboard id", example = "784f394c-42b6-435a-983c-b7beff2784f9")
@JsonView(Views.Public.class)
private String dashboardId;
@Override

View File

@ -15,12 +15,14 @@
*/
package org.thingsboard.server.common.data.mobile.layout;
import com.fasterxml.jackson.annotation.JsonView;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.thingsboard.server.common.data.Views;
@Data
@Builder
@ -30,6 +32,7 @@ import lombok.NoArgsConstructor;
public class DefaultMobilePage extends AbstractMobilePage {
@Schema(description = "Identifier for default page", example = "HOME")
@JsonView(Views.Public.class)
private DefaultPageId id;
@Override

View File

@ -15,6 +15,7 @@
*/
package org.thingsboard.server.common.data.mobile.layout;
import com.fasterxml.jackson.annotation.JsonView;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
@ -22,6 +23,7 @@ import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.thingsboard.server.common.data.Views;
import java.util.ArrayList;
import java.util.List;
@ -34,6 +36,7 @@ import java.util.List;
public class MobileLayoutConfig {
@Schema(description = "List of pages")
@JsonView(Views.Public.class)
@Valid
private List<MobilePage> pages = new ArrayList<>();

View File

@ -33,6 +33,8 @@ package org.thingsboard.server.common.data.mobile.layout;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonView;
import org.thingsboard.server.common.data.Views;
import java.io.Serializable;
@ -43,14 +45,16 @@ import java.io.Serializable;
property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = DefaultMobilePage.class, name = "DEFAULT"),
@JsonSubTypes.Type(value = DashdoardPage.class, name = "DASHBOARD"),
@JsonSubTypes.Type(value = DashboardPage.class, name = "DASHBOARD"),
@JsonSubTypes.Type(value = WebViewPage.class, name = "WEB_VIEW"),
@JsonSubTypes.Type(value = CustomMobilePage.class, name = "CUSTOM")
})
public interface MobilePage extends Serializable {
@JsonView(Views.Private.class)
MobilePageType getType();
@JsonView(Views.Private.class)
boolean isVisible();
}

View File

@ -15,12 +15,14 @@
*/
package org.thingsboard.server.common.data.mobile.layout;
import com.fasterxml.jackson.annotation.JsonView;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.thingsboard.server.common.data.Views;
@Data
@Builder
@ -30,6 +32,7 @@ import lombok.NoArgsConstructor;
public class WebViewPage extends AbstractMobilePage {
@Schema(description = "Url", example = "/url")
@JsonView(Views.Public.class)
private String url;
@Override

View File

@ -35,6 +35,7 @@ import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.thingsboard.server.common.data.kv.DataType;
import org.thingsboard.server.common.data.kv.KvEntry;
import org.thingsboard.server.common.data.Views;
import java.io.File;
import java.io.IOException;
@ -174,6 +175,10 @@ public class JacksonUtil {
}
}
public static String writeValueAsViewIgnoringNullFields(Object value, Class<Views.Public> serializationView) throws JsonProcessingException {
return value == null ? "" : OBJECT_MAPPER.writerWithView(serializationView).writeValueAsString(value);
}
public static String toPrettyString(Object o) {
try {
return PRETTY_SORTED_JSON_MAPPER.writeValueAsString(o);
@ -227,6 +232,14 @@ public class JacksonUtil {
}
}
public static <T> T readValue(String object, TypeReference<T> clazz) {
try {
return OBJECT_MAPPER.readValue(object, clazz);
} catch (IOException e) {
throw new IllegalArgumentException("Can't read object: " + object, e);
}
}
public static <T> T readValue(File file, TypeReference<T> clazz) {
try {
return OBJECT_MAPPER.readValue(file, clazz);