835 changed files with 38107 additions and 7934 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,16 @@ |
|||
-- |
|||
-- 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. |
|||
-- |
|||
|
|||
@ -0,0 +1,78 @@ |
|||
/** |
|||
* 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.config; |
|||
|
|||
import jakarta.servlet.FilterChain; |
|||
import jakarta.servlet.ServletException; |
|||
import jakarta.servlet.http.HttpServletRequest; |
|||
import jakarta.servlet.http.HttpServletResponse; |
|||
import lombok.RequiredArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.stereotype.Component; |
|||
import org.springframework.util.AntPathMatcher; |
|||
import org.springframework.web.filter.OncePerRequestFilter; |
|||
import org.thingsboard.server.common.msg.tools.MaxPayloadSizeExceededException; |
|||
import org.thingsboard.server.exception.ThingsboardErrorResponseHandler; |
|||
|
|||
import java.io.IOException; |
|||
import java.util.List; |
|||
|
|||
@Slf4j |
|||
@Component |
|||
@RequiredArgsConstructor |
|||
public class RequestSizeFilter extends OncePerRequestFilter { |
|||
|
|||
private final List<String> urls = List.of("/api/plugins/rpc/**", "/api/rpc/**"); |
|||
private final AntPathMatcher pathMatcher = new AntPathMatcher(); |
|||
private final ThingsboardErrorResponseHandler errorResponseHandler; |
|||
|
|||
@Value("${transport.http.max_payload_size:65536}") |
|||
private int maxPayloadSize; |
|||
|
|||
@Override |
|||
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { |
|||
if (request.getContentLength() > maxPayloadSize) { |
|||
if (log.isDebugEnabled()) { |
|||
log.debug("Too large payload size. Url: {}, client ip: {}, content length: {}", request.getRequestURL(), |
|||
request.getRemoteAddr(), request.getContentLength()); |
|||
} |
|||
errorResponseHandler.handle(new MaxPayloadSizeExceededException(), response); |
|||
return; |
|||
} |
|||
chain.doFilter(request, response); |
|||
} |
|||
|
|||
@Override |
|||
protected boolean shouldNotFilter(HttpServletRequest request) { |
|||
for (String url : urls) { |
|||
if (pathMatcher.match(url, request.getRequestURI())) { |
|||
return false; |
|||
} |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
@Override |
|||
protected boolean shouldNotFilterAsyncDispatch() { |
|||
return false; |
|||
} |
|||
|
|||
@Override |
|||
protected boolean shouldNotFilterErrorDispatch() { |
|||
return false; |
|||
} |
|||
} |
|||
@ -0,0 +1,191 @@ |
|||
/** |
|||
* 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.controller; |
|||
|
|||
import com.fasterxml.jackson.databind.JsonNode; |
|||
import io.swagger.v3.oas.annotations.Parameter; |
|||
import jakarta.servlet.http.HttpServletRequest; |
|||
import lombok.RequiredArgsConstructor; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.http.HttpStatus; |
|||
import org.springframework.http.ResponseEntity; |
|||
import org.springframework.security.access.prepost.PreAuthorize; |
|||
import org.springframework.web.bind.annotation.GetMapping; |
|||
import org.springframework.web.bind.annotation.PathVariable; |
|||
import org.springframework.web.bind.annotation.PostMapping; |
|||
import org.springframework.web.bind.annotation.RequestBody; |
|||
import org.springframework.web.bind.annotation.RequestHeader; |
|||
import org.springframework.web.bind.annotation.RestController; |
|||
import org.thingsboard.common.util.JacksonUtil; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.mobile.AndroidConfig; |
|||
import org.thingsboard.server.common.data.mobile.IosConfig; |
|||
import org.thingsboard.server.common.data.mobile.MobileAppSettings; |
|||
import org.thingsboard.server.common.data.security.model.JwtPair; |
|||
import org.thingsboard.server.config.annotations.ApiOperation; |
|||
import org.thingsboard.server.dao.mobile.MobileAppSettingsService; |
|||
import org.thingsboard.server.queue.util.TbCoreComponent; |
|||
import org.thingsboard.server.service.mobile.secret.MobileAppSecretService; |
|||
import org.thingsboard.server.service.security.model.SecurityUser; |
|||
import org.thingsboard.server.service.security.permission.Operation; |
|||
import org.thingsboard.server.service.security.permission.Resource; |
|||
import org.thingsboard.server.service.security.system.SystemSecurityService; |
|||
|
|||
import java.net.URI; |
|||
import java.net.URISyntaxException; |
|||
|
|||
import static org.thingsboard.server.controller.ControllerConstants.AVAILABLE_FOR_ANY_AUTHORIZED_USER; |
|||
import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_AUTHORITY_PARAGRAPH; |
|||
|
|||
@RequiredArgsConstructor |
|||
@RestController |
|||
@TbCoreComponent |
|||
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" + |
|||
" \"target\": {\n" + |
|||
" \"namespace\": \"android_app\",\n" + |
|||
" \"package_name\": \"%s\",\n" + |
|||
" \"sha256_cert_fingerprints\":\n" + |
|||
" [\"%s\"]\n" + |
|||
" }\n" + |
|||
"}]"; |
|||
|
|||
public static final String APPLE_APP_SITE_ASSOCIATION_PATTERN = "{\n" + |
|||
" \"applinks\": {\n" + |
|||
" \"apps\": [],\n" + |
|||
" \"details\": [\n" + |
|||
" {\n" + |
|||
" \"appID\": \"%s\",\n" + |
|||
" \"paths\": [ \"/api/noauth/qr\" ]\n" + |
|||
" }\n" + |
|||
" ]\n" + |
|||
" }\n" + |
|||
"}"; |
|||
|
|||
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 DEEP_LINK_PATTERN = "https://%s/api/noauth/qr?secret=%s&ttl=%s"; |
|||
|
|||
private final SystemSecurityService systemSecurityService; |
|||
private final MobileAppSecretService mobileAppSecretService; |
|||
private final MobileAppSettingsService mobileAppSettingsService; |
|||
|
|||
@ApiOperation(value = "Get associated android applications (getAssetLinks)") |
|||
@GetMapping(value = "/.well-known/assetlinks.json") |
|||
public ResponseEntity<JsonNode> getAssetLinks() { |
|||
MobileAppSettings mobileAppSettings = mobileAppSettingsService.getMobileAppSettings(TenantId.SYS_TENANT_ID); |
|||
AndroidConfig androidConfig = mobileAppSettings.getAndroidConfig(); |
|||
if (androidConfig != null && androidConfig.isEnabled() && androidConfig.getAppPackage() != null && androidConfig.getSha256CertFingerprints() != null) { |
|||
return ResponseEntity.ok(JacksonUtil.toJsonNode(String.format(ASSET_LINKS_PATTERN, androidConfig.getAppPackage(), androidConfig.getSha256CertFingerprints()))); |
|||
} else { |
|||
return ResponseEntity.notFound().build(); |
|||
} |
|||
} |
|||
|
|||
@ApiOperation(value = "Get associated ios applications (getAppleAppSiteAssociation)") |
|||
@GetMapping(value = "/.well-known/apple-app-site-association") |
|||
public ResponseEntity<JsonNode> getAppleAppSiteAssociation() { |
|||
MobileAppSettings mobileAppSettings = mobileAppSettingsService.getMobileAppSettings(TenantId.SYS_TENANT_ID); |
|||
IosConfig iosConfig = mobileAppSettings.getIosConfig(); |
|||
if (iosConfig != null && iosConfig.isEnabled() && iosConfig.getAppId() != null) { |
|||
return ResponseEntity.ok(JacksonUtil.toJsonNode(String.format(APPLE_APP_SITE_ASSOCIATION_PATTERN, iosConfig.getAppId()))); |
|||
} else { |
|||
return ResponseEntity.notFound().build(); |
|||
} |
|||
} |
|||
|
|||
@ApiOperation(value = "Create Or Update the Mobile application settings (saveMobileAppSettings)", |
|||
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/app/settings") |
|||
public MobileAppSettings saveMobileAppSettings(@Parameter(description = "A JSON value representing the mobile apps configuration") |
|||
@RequestBody MobileAppSettings mobileAppSettings) throws ThingsboardException { |
|||
SecurityUser currentUser = getCurrentUser(); |
|||
accessControlService.checkPermission(currentUser, Resource.MOBILE_APP_SETTINGS, Operation.WRITE); |
|||
mobileAppSettings.setTenantId(getTenantId()); |
|||
return mobileAppSettingsService.saveMobileAppSettings(currentUser.getTenantId(), mobileAppSettings); |
|||
} |
|||
|
|||
@ApiOperation(value = "Get Mobile application settings (getMobileAppSettings)", |
|||
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/app/settings") |
|||
public MobileAppSettings getMobileAppSettings() throws ThingsboardException { |
|||
SecurityUser currentUser = getCurrentUser(); |
|||
accessControlService.checkPermission(currentUser, Resource.MOBILE_APP_SETTINGS, Operation.READ); |
|||
return mobileAppSettingsService.getMobileAppSettings(TenantId.SYS_TENANT_ID); |
|||
} |
|||
|
|||
@ApiOperation(value = "Get the deep link to the associated mobile application (getMobileAppDeepLink)", |
|||
notes = "Fetch the url that takes user to linked mobile application " + AVAILABLE_FOR_ANY_AUTHORIZED_USER) |
|||
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
|||
@GetMapping(value = "/api/mobile/deepLink", produces = "text/plain") |
|||
public String getMobileAppDeepLink(HttpServletRequest request) throws ThingsboardException, URISyntaxException { |
|||
String secret = mobileAppSecretService.generateMobileAppSecret(getCurrentUser()); |
|||
String baseUrl = systemSecurityService.getBaseUrl(TenantId.SYS_TENANT_ID, null, request); |
|||
String platformDomain = new URI(baseUrl).getHost(); |
|||
MobileAppSettings mobileAppSettings = mobileAppSettingsService.getMobileAppSettings(TenantId.SYS_TENANT_ID); |
|||
String appDomain; |
|||
if (!mobileAppSettings.isUseDefaultApp()) { |
|||
appDomain = platformDomain; |
|||
} else { |
|||
appDomain = defaultAppDomain; |
|||
} |
|||
String deepLink = String.format(DEEP_LINK_PATTERN, appDomain, secret, mobileSecretKeyTtl); |
|||
if (!appDomain.equals(platformDomain)) { |
|||
deepLink = deepLink + "&host=" + baseUrl; |
|||
} |
|||
return "\"" + deepLink + "\""; |
|||
} |
|||
|
|||
@ApiOperation(value = "Get User Token (getUserTokenByMobileSecret)", |
|||
notes = "Returns the token of the User based on the provided secret key.") |
|||
@GetMapping(value = "/api/noauth/qr/{secret}") |
|||
public JwtPair getUserTokenByMobileSecret(@Parameter(description = SECRET_PARAM_DESCRIPTION) |
|||
@PathVariable(SECRET) String secret) throws ThingsboardException { |
|||
checkParameter(SECRET, secret); |
|||
return mobileAppSecretService.getJwtPair(secret); |
|||
} |
|||
|
|||
@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.getDefaultAppStoreLink() : mobileAppSettings.getIosConfig().getStoreLink(); |
|||
if (userAgent.contains("Android")) { |
|||
return ResponseEntity.status(HttpStatus.FOUND) |
|||
.header("Location", googlePlayLink) |
|||
.build(); |
|||
} else if (userAgent.contains("iPhone") || userAgent.contains("iPad")) { |
|||
return ResponseEntity.status(HttpStatus.FOUND) |
|||
.header("Location", appStoreLink) |
|||
.build(); |
|||
} else { |
|||
return ResponseEntity.status(HttpStatus.NOT_FOUND) |
|||
.build(); |
|||
} |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,102 @@ |
|||
/** |
|||
* 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.controller; |
|||
|
|||
import io.swagger.v3.oas.annotations.Parameter; |
|||
import io.swagger.v3.oas.annotations.media.ArraySchema; |
|||
import io.swagger.v3.oas.annotations.media.Schema; |
|||
import lombok.RequiredArgsConstructor; |
|||
import org.springframework.security.access.prepost.PreAuthorize; |
|||
import org.springframework.web.bind.annotation.GetMapping; |
|||
import org.springframework.web.bind.annotation.PathVariable; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import org.springframework.web.bind.annotation.RequestParam; |
|||
import org.springframework.web.bind.annotation.RestController; |
|||
import org.thingsboard.server.common.data.exception.ThingsboardException; |
|||
import org.thingsboard.server.common.data.id.QueueStatsId; |
|||
import org.thingsboard.server.common.data.page.PageData; |
|||
import org.thingsboard.server.common.data.page.PageLink; |
|||
import org.thingsboard.server.common.data.queue.QueueStats; |
|||
import org.thingsboard.server.config.annotations.ApiOperation; |
|||
import org.thingsboard.server.dao.queue.QueueStatsService; |
|||
import org.thingsboard.server.queue.util.TbCoreComponent; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
import java.util.UUID; |
|||
|
|||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; |
|||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; |
|||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; |
|||
import static org.thingsboard.server.controller.ControllerConstants.QUEUE_STATS_ID_PARAM_DESCRIPTION; |
|||
import static org.thingsboard.server.controller.ControllerConstants.QUEUE_STATS_TEXT_SEARCH_DESCRIPTION; |
|||
import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; |
|||
import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION; |
|||
import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH; |
|||
|
|||
@RestController |
|||
@TbCoreComponent |
|||
@RequestMapping("/api") |
|||
@RequiredArgsConstructor |
|||
public class QueueStatsController extends BaseController { |
|||
|
|||
private final QueueStatsService queueStatsService; |
|||
|
|||
@ApiOperation(value = "Get Queue Stats entities (getTenantQueueStats)", |
|||
notes = "Returns a page of queue stats objects that are designed to collect queue statistics for every service. " + |
|||
PAGE_DATA_PARAMETERS + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) |
|||
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") |
|||
@GetMapping(value = "/queueStats", params = {"pageSize", "page"}) |
|||
public PageData<QueueStats> getTenantQueueStats(@Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) |
|||
@RequestParam int pageSize, |
|||
@Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) |
|||
@RequestParam int page, |
|||
@Parameter(description = QUEUE_STATS_TEXT_SEARCH_DESCRIPTION) |
|||
@RequestParam(required = false) String textSearch, |
|||
@Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime"})) |
|||
@RequestParam(required = false) String sortProperty, |
|||
@Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) |
|||
@RequestParam(required = false) String sortOrder) throws ThingsboardException { |
|||
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); |
|||
return queueStatsService.findByTenantId(getTenantId(), pageLink); |
|||
} |
|||
|
|||
@ApiOperation(value = "Get Queue stats entity by id (getQueueStatsById)", |
|||
notes = "Fetch the Queue stats object based on the provided Queue stats id. " + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) |
|||
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") |
|||
@GetMapping(value = "/queueStats/{queueStatsId}") |
|||
public QueueStats getQueueStatsById(@Parameter(description = QUEUE_STATS_ID_PARAM_DESCRIPTION) |
|||
@PathVariable("queueStatsId") String queueStatsIdStr) throws ThingsboardException { |
|||
checkParameter("queueStatsId", queueStatsIdStr); |
|||
QueueStatsId queueStatsId = new QueueStatsId(UUID.fromString(queueStatsIdStr)); |
|||
return checkNotNull(queueStatsService.findQueueStatsById(getTenantId(), queueStatsId)); |
|||
} |
|||
|
|||
@ApiOperation(value = "Get QueueStats By Ids (getQueueStatsByIds)", |
|||
notes = "Fetch the Queue stats objects based on the provided ids. ") |
|||
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") |
|||
@GetMapping(value = "/queueStats", params = {"queueStatsIds"}) |
|||
public List<QueueStats> getQueueStatsByIds( |
|||
@Parameter(description = "A list of queue stats ids, separated by comma ','", array = @ArraySchema(schema = @Schema(type = "string")), required = true) |
|||
@RequestParam("queueStatsIds") String[] strQueueStatsIds) throws ThingsboardException { |
|||
checkArrayParameter("queueStatsIds", strQueueStatsIds); |
|||
List<QueueStatsId> queueStatsIds = new ArrayList<>(); |
|||
for (String queueStatsId : strQueueStatsIds) { |
|||
queueStatsIds.add(new QueueStatsId(toUUID(queueStatsId))); |
|||
} |
|||
return queueStatsService.findQueueStatsByIds(getTenantId(), queueStatsIds); |
|||
} |
|||
} |
|||
@ -0,0 +1,65 @@ |
|||
/** |
|||
* 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.service.edge.instructions; |
|||
|
|||
import lombok.RequiredArgsConstructor; |
|||
import lombok.Setter; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.thingsboard.server.service.install.InstallScripts; |
|||
|
|||
import java.io.IOException; |
|||
import java.nio.file.Files; |
|||
import java.nio.file.Path; |
|||
import java.nio.file.Paths; |
|||
|
|||
@Slf4j |
|||
@RequiredArgsConstructor |
|||
public abstract class BaseEdgeInstallUpgradeInstructionsService { |
|||
|
|||
private static final String EDGE_DIR = "edge"; |
|||
private static final String INSTRUCTIONS_DIR = "instructions"; |
|||
|
|||
private final InstallScripts installScripts; |
|||
|
|||
@Value("${app.version:unknown}") |
|||
@Setter |
|||
protected String appVersion; |
|||
|
|||
protected String readFile(Path file) { |
|||
try { |
|||
return Files.readString(file); |
|||
} catch (IOException e) { |
|||
log.warn("Failed to read file: {}", file, e); |
|||
throw new RuntimeException(e); |
|||
} |
|||
} |
|||
|
|||
protected String getTagVersion(String version) { |
|||
return version.endsWith(".0") ? version.substring(0, version.length() - 2) : version; |
|||
} |
|||
|
|||
protected Path resolveFile(String subDir, String... subDirs) { |
|||
return getEdgeInstructionsDir().resolve(Paths.get(subDir, subDirs)); |
|||
} |
|||
|
|||
protected Path getEdgeInstructionsDir() { |
|||
return Paths.get(installScripts.getDataDir(), InstallScripts.JSON_DIR, EDGE_DIR, INSTRUCTIONS_DIR, getBaseDirName()); |
|||
} |
|||
|
|||
protected abstract String getBaseDirName(); |
|||
|
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue