Implement version control ssh access with private key. Improve VC settings REST methods. Add tenantId field to admin settings. Add DB upgrade.
This commit is contained in:
		
							parent
							
								
									0905aff7a0
								
							
						
					
					
						commit
						0b6de71768
					
				@ -345,6 +345,10 @@
 | 
				
			|||||||
            <groupId>org.eclipse.jgit</groupId>
 | 
					            <groupId>org.eclipse.jgit</groupId>
 | 
				
			||||||
            <artifactId>org.eclipse.jgit</artifactId>
 | 
					            <artifactId>org.eclipse.jgit</artifactId>
 | 
				
			||||||
        </dependency>
 | 
					        </dependency>
 | 
				
			||||||
 | 
					        <dependency>
 | 
				
			||||||
 | 
					            <groupId>org.eclipse.jgit</groupId>
 | 
				
			||||||
 | 
					            <artifactId>org.eclipse.jgit.ssh.apache</artifactId>
 | 
				
			||||||
 | 
					        </dependency>
 | 
				
			||||||
    </dependencies>
 | 
					    </dependencies>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <build>
 | 
					    <build>
 | 
				
			||||||
 | 
				
			|||||||
@ -26,3 +26,6 @@ ALTER TABLE dashboard
 | 
				
			|||||||
    ADD COLUMN IF NOT EXISTS external_id UUID;
 | 
					    ADD COLUMN IF NOT EXISTS external_id UUID;
 | 
				
			||||||
ALTER TABLE customer
 | 
					ALTER TABLE customer
 | 
				
			||||||
    ADD COLUMN IF NOT EXISTS external_id UUID;
 | 
					    ADD COLUMN IF NOT EXISTS external_id UUID;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ALTER TABLE admin_settings
 | 
				
			||||||
 | 
					    ADD COLUMN IF NOT EXISTS tenant_id uuid NOT NULL DEFAULT '13814000-1dd2-11b2-8080-808080808080';
 | 
				
			||||||
 | 
				
			|||||||
@ -20,12 +20,7 @@ import io.swagger.annotations.ApiOperation;
 | 
				
			|||||||
import io.swagger.annotations.ApiParam;
 | 
					import io.swagger.annotations.ApiParam;
 | 
				
			||||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
					import org.springframework.beans.factory.annotation.Autowired;
 | 
				
			||||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
					import org.springframework.security.access.prepost.PreAuthorize;
 | 
				
			||||||
import org.springframework.web.bind.annotation.PathVariable;
 | 
					import org.springframework.web.bind.annotation.*;
 | 
				
			||||||
import org.springframework.web.bind.annotation.RequestBody;
 | 
					 | 
				
			||||||
import org.springframework.web.bind.annotation.RequestMapping;
 | 
					 | 
				
			||||||
import org.springframework.web.bind.annotation.RequestMethod;
 | 
					 | 
				
			||||||
import org.springframework.web.bind.annotation.ResponseBody;
 | 
					 | 
				
			||||||
import org.springframework.web.bind.annotation.RestController;
 | 
					 | 
				
			||||||
import org.thingsboard.rule.engine.api.MailService;
 | 
					import org.thingsboard.rule.engine.api.MailService;
 | 
				
			||||||
import org.thingsboard.rule.engine.api.SmsService;
 | 
					import org.thingsboard.rule.engine.api.SmsService;
 | 
				
			||||||
import org.thingsboard.server.common.data.AdminSettings;
 | 
					import org.thingsboard.server.common.data.AdminSettings;
 | 
				
			||||||
@ -34,14 +29,17 @@ import org.thingsboard.server.common.data.exception.ThingsboardException;
 | 
				
			|||||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
					import org.thingsboard.server.common.data.id.TenantId;
 | 
				
			||||||
import org.thingsboard.server.common.data.security.model.SecuritySettings;
 | 
					import org.thingsboard.server.common.data.security.model.SecuritySettings;
 | 
				
			||||||
import org.thingsboard.server.common.data.sms.config.TestSmsRequest;
 | 
					import org.thingsboard.server.common.data.sms.config.TestSmsRequest;
 | 
				
			||||||
 | 
					import org.thingsboard.server.common.data.vc.EntitiesVersionControlSettings;
 | 
				
			||||||
import org.thingsboard.server.dao.settings.AdminSettingsService;
 | 
					import org.thingsboard.server.dao.settings.AdminSettingsService;
 | 
				
			||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
 | 
					import org.thingsboard.server.queue.util.TbCoreComponent;
 | 
				
			||||||
import org.thingsboard.server.service.security.permission.Operation;
 | 
					import org.thingsboard.server.service.security.permission.Operation;
 | 
				
			||||||
import org.thingsboard.server.service.security.permission.Resource;
 | 
					import org.thingsboard.server.service.security.permission.Resource;
 | 
				
			||||||
import org.thingsboard.server.service.security.system.SystemSecurityService;
 | 
					import org.thingsboard.server.service.security.system.SystemSecurityService;
 | 
				
			||||||
 | 
					import org.thingsboard.server.service.sync.vc.EntitiesVersionControlService;
 | 
				
			||||||
import org.thingsboard.server.service.update.UpdateService;
 | 
					import org.thingsboard.server.service.update.UpdateService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_AUTHORITY_PARAGRAPH;
 | 
					import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_AUTHORITY_PARAGRAPH;
 | 
				
			||||||
 | 
					import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@RestController
 | 
					@RestController
 | 
				
			||||||
@TbCoreComponent
 | 
					@TbCoreComponent
 | 
				
			||||||
@ -60,6 +58,9 @@ public class AdminController extends BaseController {
 | 
				
			|||||||
    @Autowired
 | 
					    @Autowired
 | 
				
			||||||
    private SystemSecurityService systemSecurityService;
 | 
					    private SystemSecurityService systemSecurityService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Autowired
 | 
				
			||||||
 | 
					    private EntitiesVersionControlService versionControlService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Autowired
 | 
					    @Autowired
 | 
				
			||||||
    private UpdateService updateService;
 | 
					    private UpdateService updateService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -96,6 +97,7 @@ public class AdminController extends BaseController {
 | 
				
			|||||||
            @RequestBody AdminSettings adminSettings) throws ThingsboardException {
 | 
					            @RequestBody AdminSettings adminSettings) throws ThingsboardException {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.WRITE);
 | 
					            accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.WRITE);
 | 
				
			||||||
 | 
					            adminSettings.setTenantId(getTenantId());
 | 
				
			||||||
            adminSettings = checkNotNull(adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, adminSettings));
 | 
					            adminSettings = checkNotNull(adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, adminSettings));
 | 
				
			||||||
            if (adminSettings.getKey().equals("mail")) {
 | 
					            if (adminSettings.getKey().equals("mail")) {
 | 
				
			||||||
                mailService.updateMailConfiguration();
 | 
					                mailService.updateMailConfiguration();
 | 
				
			||||||
@ -180,6 +182,53 @@ public class AdminController extends BaseController {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ApiOperation(value = "Get version control settings (getVersionControlSettings)",
 | 
				
			||||||
 | 
					            notes = "Get the version control settings object. " + TENANT_AUTHORITY_PARAGRAPH)
 | 
				
			||||||
 | 
					    @PreAuthorize("hasAuthority('TENANT_ADMIN')")
 | 
				
			||||||
 | 
					    @GetMapping("/vcSettings")
 | 
				
			||||||
 | 
					    @ResponseBody
 | 
				
			||||||
 | 
					    public EntitiesVersionControlSettings getVersionControlSettings() throws ThingsboardException {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ);
 | 
				
			||||||
 | 
					            EntitiesVersionControlSettings versionControlSettings = checkNotNull(versionControlService.getVersionControlSettings(getTenantId()));
 | 
				
			||||||
 | 
					            versionControlSettings.setPassword(null);
 | 
				
			||||||
 | 
					            versionControlSettings.setPrivateKey(null);
 | 
				
			||||||
 | 
					            versionControlSettings.setPrivateKeyPassword(null);
 | 
				
			||||||
 | 
					            return versionControlSettings;
 | 
				
			||||||
 | 
					        } catch (Exception e) {
 | 
				
			||||||
 | 
					            throw handleException(e);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ApiOperation(value = "Creates or Updates the version control settings (saveVersionControlSettings)",
 | 
				
			||||||
 | 
					            notes = "Creates or Updates the version control settings object. " + TENANT_AUTHORITY_PARAGRAPH)
 | 
				
			||||||
 | 
					    @PreAuthorize("hasAuthority('TENANT_ADMIN')")
 | 
				
			||||||
 | 
					    @PostMapping("/vsSettings")
 | 
				
			||||||
 | 
					    public void saveVersionControlSettings(@RequestBody EntitiesVersionControlSettings settings) throws ThingsboardException {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.WRITE);
 | 
				
			||||||
 | 
					            versionControlService.saveVersionControlSettings(getTenantId(), settings);
 | 
				
			||||||
 | 
					        } catch (Exception e) {
 | 
				
			||||||
 | 
					            throw handleException(e);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ApiOperation(value = "Check version control access (checkVersionControlAccess)",
 | 
				
			||||||
 | 
					            notes = "Attempts to check version control access. " + TENANT_AUTHORITY_PARAGRAPH)
 | 
				
			||||||
 | 
					    @PreAuthorize("hasAuthority('TENANT_ADMIN')")
 | 
				
			||||||
 | 
					    @RequestMapping(value = "/vcSettings/checkAccess", method = RequestMethod.POST)
 | 
				
			||||||
 | 
					    public void checkVersionControlAccess(
 | 
				
			||||||
 | 
					            @ApiParam(value = "A JSON value representing the Entities Version Control Settings.")
 | 
				
			||||||
 | 
					            @RequestBody EntitiesVersionControlSettings settings) throws ThingsboardException {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ);
 | 
				
			||||||
 | 
					            settings = checkNotNull(settings);
 | 
				
			||||||
 | 
					            versionControlService.checkVersionControlAccess(getTenantId(), settings);
 | 
				
			||||||
 | 
					        } catch (Exception e) {
 | 
				
			||||||
 | 
					            throw handleException(e);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @ApiOperation(value = "Check for new Platform Releases (checkUpdates)",
 | 
					    @ApiOperation(value = "Check for new Platform Releases (checkUpdates)",
 | 
				
			||||||
            notes = "Check notifications about new platform releases. "
 | 
					            notes = "Check notifications about new platform releases. "
 | 
				
			||||||
                    + SYSTEM_AUTHORITY_PARAGRAPH)
 | 
					                    + SYSTEM_AUTHORITY_PARAGRAPH)
 | 
				
			||||||
 | 
				
			|||||||
@ -15,25 +15,18 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
package org.thingsboard.server.controller;
 | 
					package org.thingsboard.server.controller;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import io.swagger.annotations.ApiModelProperty;
 | 
					 | 
				
			||||||
import io.swagger.annotations.ApiOperation;
 | 
					import io.swagger.annotations.ApiOperation;
 | 
				
			||||||
import lombok.Data;
 | 
					import lombok.Data;
 | 
				
			||||||
import lombok.RequiredArgsConstructor;
 | 
					import lombok.RequiredArgsConstructor;
 | 
				
			||||||
import org.apache.commons.lang3.StringUtils;
 | 
					 | 
				
			||||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
					import org.springframework.security.access.prepost.PreAuthorize;
 | 
				
			||||||
import org.springframework.web.bind.annotation.GetMapping;
 | 
					import org.springframework.web.bind.annotation.*;
 | 
				
			||||||
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.RequestMapping;
 | 
					 | 
				
			||||||
import org.springframework.web.bind.annotation.RestController;
 | 
					 | 
				
			||||||
import org.thingsboard.server.common.data.EntityType;
 | 
					import org.thingsboard.server.common.data.EntityType;
 | 
				
			||||||
 | 
					import org.thingsboard.server.common.data.StringUtils;
 | 
				
			||||||
import org.thingsboard.server.common.data.exception.ThingsboardException;
 | 
					import org.thingsboard.server.common.data.exception.ThingsboardException;
 | 
				
			||||||
import org.thingsboard.server.common.data.id.EntityId;
 | 
					import org.thingsboard.server.common.data.id.EntityId;
 | 
				
			||||||
import org.thingsboard.server.common.data.id.EntityIdFactory;
 | 
					import org.thingsboard.server.common.data.id.EntityIdFactory;
 | 
				
			||||||
import org.thingsboard.server.service.security.model.SecurityUser;
 | 
					import org.thingsboard.server.service.security.model.SecurityUser;
 | 
				
			||||||
import org.thingsboard.server.service.sync.vc.EntitiesVersionControlService;
 | 
					import org.thingsboard.server.service.sync.vc.EntitiesVersionControlService;
 | 
				
			||||||
import org.thingsboard.server.service.sync.vc.data.EntitiesVersionControlSettings;
 | 
					 | 
				
			||||||
import org.thingsboard.server.service.sync.vc.data.EntityVersion;
 | 
					import org.thingsboard.server.service.sync.vc.data.EntityVersion;
 | 
				
			||||||
import org.thingsboard.server.service.sync.vc.data.VersionCreationResult;
 | 
					import org.thingsboard.server.service.sync.vc.data.VersionCreationResult;
 | 
				
			||||||
import org.thingsboard.server.service.sync.vc.data.VersionLoadResult;
 | 
					import org.thingsboard.server.service.sync.vc.data.VersionLoadResult;
 | 
				
			||||||
@ -280,7 +273,7 @@ public class EntitiesVersionControlController extends BaseController {
 | 
				
			|||||||
            List<String> remoteBranches = versionControlService.listBranches(getTenantId());
 | 
					            List<String> remoteBranches = versionControlService.listBranches(getTenantId());
 | 
				
			||||||
            List<BranchInfo> infos = new ArrayList<>();
 | 
					            List<BranchInfo> infos = new ArrayList<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            String defaultBranch = getSettings().getDefaultBranch();
 | 
					            String defaultBranch = versionControlService.getVersionControlSettings(getTenantId()).getDefaultBranch();
 | 
				
			||||||
            if (StringUtils.isNotEmpty(defaultBranch)) {
 | 
					            if (StringUtils.isNotEmpty(defaultBranch)) {
 | 
				
			||||||
                remoteBranches.remove(defaultBranch);
 | 
					                remoteBranches.remove(defaultBranch);
 | 
				
			||||||
                infos.add(new BranchInfo(defaultBranch, true));
 | 
					                infos.add(new BranchInfo(defaultBranch, true));
 | 
				
			||||||
@ -293,40 +286,6 @@ public class EntitiesVersionControlController extends BaseController {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    @ApiOperation(value = "", notes = "" +
 | 
					 | 
				
			||||||
            "```\n{\n" +
 | 
					 | 
				
			||||||
            "  \"repositoryUri\": \"https://github.com/User/repo.git\",\n" +
 | 
					 | 
				
			||||||
            "  \"username\": \"User\",\n" +
 | 
					 | 
				
			||||||
            "  \"password\": \"api_key\",\n" +
 | 
					 | 
				
			||||||
            "  \"defaultBranch\": \"master\"\n" +
 | 
					 | 
				
			||||||
            "}\n```")
 | 
					 | 
				
			||||||
    @GetMapping("/settings")
 | 
					 | 
				
			||||||
    public EntitiesVersionControlSettings getSettings() throws ThingsboardException {
 | 
					 | 
				
			||||||
        try {
 | 
					 | 
				
			||||||
            return versionControlService.getSettings(getTenantId());
 | 
					 | 
				
			||||||
        } catch (Exception e) {
 | 
					 | 
				
			||||||
            throw handleException(e);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @ApiOperation(value = "", notes = "" +
 | 
					 | 
				
			||||||
            "```\n{\n" +
 | 
					 | 
				
			||||||
            "  \"repositoryUri\": \"https://github.com/User/repo.git\",\n" +
 | 
					 | 
				
			||||||
            "  \"username\": \"User\",\n" +
 | 
					 | 
				
			||||||
            "  \"password\": \"api_key\",\n" +
 | 
					 | 
				
			||||||
            "  \"defaultBranch\": \"master\"\n" +
 | 
					 | 
				
			||||||
            "}\n```")
 | 
					 | 
				
			||||||
    @PostMapping("/settings")
 | 
					 | 
				
			||||||
    public void saveSettings(@RequestBody EntitiesVersionControlSettings settings) throws ThingsboardException {
 | 
					 | 
				
			||||||
        try {
 | 
					 | 
				
			||||||
            versionControlService.saveSettings(getTenantId(), settings);
 | 
					 | 
				
			||||||
        } catch (Exception e) {
 | 
					 | 
				
			||||||
            throw handleException(e);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Data
 | 
					    @Data
 | 
				
			||||||
    public static class BranchInfo {
 | 
					    public static class BranchInfo {
 | 
				
			||||||
        private final String name;
 | 
					        private final String name;
 | 
				
			||||||
 | 
				
			|||||||
@ -219,6 +219,7 @@ public class ThingsboardInstallService {
 | 
				
			|||||||
                            databaseEntitiesUpgradeService.upgradeDatabase("3.3.3");
 | 
					                            databaseEntitiesUpgradeService.upgradeDatabase("3.3.3");
 | 
				
			||||||
                        case "3.3.4":
 | 
					                        case "3.3.4":
 | 
				
			||||||
                            log.info("Upgrading ThingsBoard from version 3.3.4 to 3.4.0 ...");
 | 
					                            log.info("Upgrading ThingsBoard from version 3.3.4 to 3.4.0 ...");
 | 
				
			||||||
 | 
					                            databaseEntitiesUpgradeService.upgradeDatabase("3.3.4");
 | 
				
			||||||
                            log.info("Updating system data...");
 | 
					                            log.info("Updating system data...");
 | 
				
			||||||
                            systemDataLoaderService.updateSystemWidgets();
 | 
					                            systemDataLoaderService.updateSystemWidgets();
 | 
				
			||||||
                            break;
 | 
					                            break;
 | 
				
			||||||
 | 
				
			|||||||
@ -83,7 +83,7 @@ public class AdminSettingsEdgeEventFetcher implements EdgeEventFetcher {
 | 
				
			|||||||
        result.add(EdgeUtils.constructEdgeEvent(tenantId, edge.getId(), EdgeEventType.ADMIN_SETTINGS,
 | 
					        result.add(EdgeUtils.constructEdgeEvent(tenantId, edge.getId(), EdgeEventType.ADMIN_SETTINGS,
 | 
				
			||||||
                EdgeEventActionType.UPDATED, null, mapper.valueToTree(systemMailSettings)));
 | 
					                EdgeEventActionType.UPDATED, null, mapper.valueToTree(systemMailSettings)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        AdminSettings tenantMailSettings = convertToTenantAdminSettings(systemMailSettings.getKey(), (ObjectNode) systemMailSettings.getJsonValue());
 | 
					        AdminSettings tenantMailSettings = convertToTenantAdminSettings(tenantId, systemMailSettings.getKey(), (ObjectNode) systemMailSettings.getJsonValue());
 | 
				
			||||||
        result.add(EdgeUtils.constructEdgeEvent(tenantId, edge.getId(), EdgeEventType.ADMIN_SETTINGS,
 | 
					        result.add(EdgeUtils.constructEdgeEvent(tenantId, edge.getId(), EdgeEventType.ADMIN_SETTINGS,
 | 
				
			||||||
                EdgeEventActionType.UPDATED, null, mapper.valueToTree(tenantMailSettings)));
 | 
					                EdgeEventActionType.UPDATED, null, mapper.valueToTree(tenantMailSettings)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -91,7 +91,7 @@ public class AdminSettingsEdgeEventFetcher implements EdgeEventFetcher {
 | 
				
			|||||||
        result.add(EdgeUtils.constructEdgeEvent(tenantId, edge.getId(), EdgeEventType.ADMIN_SETTINGS,
 | 
					        result.add(EdgeUtils.constructEdgeEvent(tenantId, edge.getId(), EdgeEventType.ADMIN_SETTINGS,
 | 
				
			||||||
                EdgeEventActionType.UPDATED, null, mapper.valueToTree(systemMailTemplates)));
 | 
					                EdgeEventActionType.UPDATED, null, mapper.valueToTree(systemMailTemplates)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        AdminSettings tenantMailTemplates = convertToTenantAdminSettings(systemMailTemplates.getKey(), (ObjectNode) systemMailTemplates.getJsonValue());
 | 
					        AdminSettings tenantMailTemplates = convertToTenantAdminSettings(tenantId, systemMailTemplates.getKey(), (ObjectNode) systemMailTemplates.getJsonValue());
 | 
				
			||||||
        result.add(EdgeUtils.constructEdgeEvent(tenantId, edge.getId(), EdgeEventType.ADMIN_SETTINGS,
 | 
					        result.add(EdgeUtils.constructEdgeEvent(tenantId, edge.getId(), EdgeEventType.ADMIN_SETTINGS,
 | 
				
			||||||
                EdgeEventActionType.UPDATED, null, mapper.valueToTree(tenantMailTemplates)));
 | 
					                EdgeEventActionType.UPDATED, null, mapper.valueToTree(tenantMailTemplates)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -151,8 +151,9 @@ public class AdminSettingsEdgeEventFetcher implements EdgeEventFetcher {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private AdminSettings convertToTenantAdminSettings(String key, ObjectNode jsonValue) {
 | 
					    private AdminSettings convertToTenantAdminSettings(TenantId tenantId, String key, ObjectNode jsonValue) {
 | 
				
			||||||
        AdminSettings tenantMailSettings = new AdminSettings();
 | 
					        AdminSettings tenantMailSettings = new AdminSettings();
 | 
				
			||||||
 | 
					        tenantMailSettings.setTenantId(tenantId);
 | 
				
			||||||
        jsonValue.put("useSystemMailSettings", true);
 | 
					        jsonValue.put("useSystemMailSettings", true);
 | 
				
			||||||
        tenantMailSettings.setJsonValue(jsonValue);
 | 
					        tenantMailSettings.setJsonValue(jsonValue);
 | 
				
			||||||
        tenantMailSettings.setKey(key);
 | 
					        tenantMailSettings.setKey(key);
 | 
				
			||||||
 | 
				
			|||||||
@ -231,6 +231,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
 | 
				
			|||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void createAdminSettings() throws Exception {
 | 
					    public void createAdminSettings() throws Exception {
 | 
				
			||||||
        AdminSettings generalSettings = new AdminSettings();
 | 
					        AdminSettings generalSettings = new AdminSettings();
 | 
				
			||||||
 | 
					        generalSettings.setTenantId(TenantId.SYS_TENANT_ID);
 | 
				
			||||||
        generalSettings.setKey("general");
 | 
					        generalSettings.setKey("general");
 | 
				
			||||||
        ObjectNode node = objectMapper.createObjectNode();
 | 
					        ObjectNode node = objectMapper.createObjectNode();
 | 
				
			||||||
        node.put("baseUrl", "http://localhost:8080");
 | 
					        node.put("baseUrl", "http://localhost:8080");
 | 
				
			||||||
@ -239,6 +240,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
 | 
				
			|||||||
        adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, generalSettings);
 | 
					        adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, generalSettings);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        AdminSettings mailSettings = new AdminSettings();
 | 
					        AdminSettings mailSettings = new AdminSettings();
 | 
				
			||||||
 | 
					        mailSettings.setTenantId(TenantId.SYS_TENANT_ID);
 | 
				
			||||||
        mailSettings.setKey("mail");
 | 
					        mailSettings.setKey("mail");
 | 
				
			||||||
        node = objectMapper.createObjectNode();
 | 
					        node = objectMapper.createObjectNode();
 | 
				
			||||||
        node.put("mailFrom", "ThingsBoard <sysadmin@localhost.localdomain>");
 | 
					        node.put("mailFrom", "ThingsBoard <sysadmin@localhost.localdomain>");
 | 
				
			||||||
 | 
				
			|||||||
@ -534,6 +534,18 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService
 | 
				
			|||||||
                    log.error("Failed updating schema!!!", e);
 | 
					                    log.error("Failed updating schema!!!", e);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
 | 
					            case "3.3.4":
 | 
				
			||||||
 | 
					                try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) {
 | 
				
			||||||
 | 
					                    log.info("Updating schema ...");
 | 
				
			||||||
 | 
					                    schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "3.3.4", SCHEMA_UPDATE_SQL);
 | 
				
			||||||
 | 
					                    loadSql(schemaUpdateFile, conn);
 | 
				
			||||||
 | 
					                    log.info("Updating schema settings...");
 | 
				
			||||||
 | 
					                    conn.createStatement().execute("UPDATE tb_schema_settings SET schema_version = 3004000;");
 | 
				
			||||||
 | 
					                    log.info("Schema updated.");
 | 
				
			||||||
 | 
					                } catch (Exception e) {
 | 
				
			||||||
 | 
					                    log.error("Failed updating schema!!!", e);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
            default:
 | 
					            default:
 | 
				
			||||||
                throw new RuntimeException("Unable to upgrade SQL database, unsupported fromVersion: " + fromVersion);
 | 
					                throw new RuntimeException("Unable to upgrade SQL database, unsupported fromVersion: " + fromVersion);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -28,6 +28,7 @@ public class TenantAdminPermissions extends AbstractPermissions {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public TenantAdminPermissions() {
 | 
					    public TenantAdminPermissions() {
 | 
				
			||||||
        super();
 | 
					        super();
 | 
				
			||||||
 | 
					        put(Resource.ADMIN_SETTINGS, PermissionChecker.allowAllPermissionChecker);
 | 
				
			||||||
        put(Resource.ALARM, tenantEntityPermissionChecker);
 | 
					        put(Resource.ALARM, tenantEntityPermissionChecker);
 | 
				
			||||||
        put(Resource.ASSET, tenantEntityPermissionChecker);
 | 
					        put(Resource.ASSET, tenantEntityPermissionChecker);
 | 
				
			||||||
        put(Resource.DEVICE, tenantEntityPermissionChecker);
 | 
					        put(Resource.DEVICE, tenantEntityPermissionChecker);
 | 
				
			||||||
 | 
				
			|||||||
@ -107,6 +107,7 @@ public class DefaultSystemSecurityService implements SystemSecurityService {
 | 
				
			|||||||
        AdminSettings adminSettings = adminSettingsService.findAdminSettingsByKey(tenantId, "securitySettings");
 | 
					        AdminSettings adminSettings = adminSettingsService.findAdminSettingsByKey(tenantId, "securitySettings");
 | 
				
			||||||
        if (adminSettings == null) {
 | 
					        if (adminSettings == null) {
 | 
				
			||||||
            adminSettings = new AdminSettings();
 | 
					            adminSettings = new AdminSettings();
 | 
				
			||||||
 | 
					            adminSettings.setTenantId(tenantId);
 | 
				
			||||||
            adminSettings.setKey("securitySettings");
 | 
					            adminSettings.setKey("securitySettings");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        adminSettings.setJsonValue(JacksonUtil.valueToTree(securitySettings));
 | 
					        adminSettings.setJsonValue(JacksonUtil.valueToTree(securitySettings));
 | 
				
			||||||
 | 
				
			|||||||
@ -19,34 +19,29 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 | 
				
			|||||||
import com.fasterxml.jackson.databind.ObjectWriter;
 | 
					import com.fasterxml.jackson.databind.ObjectWriter;
 | 
				
			||||||
import com.fasterxml.jackson.databind.SerializationFeature;
 | 
					import com.fasterxml.jackson.databind.SerializationFeature;
 | 
				
			||||||
import lombok.RequiredArgsConstructor;
 | 
					import lombok.RequiredArgsConstructor;
 | 
				
			||||||
import lombok.SneakyThrows;
 | 
					 | 
				
			||||||
import lombok.extern.slf4j.Slf4j;
 | 
					import lombok.extern.slf4j.Slf4j;
 | 
				
			||||||
import org.apache.commons.io.FileUtils;
 | 
					import org.apache.commons.io.FileUtils;
 | 
				
			||||||
import org.apache.commons.lang3.StringUtils;
 | 
					import org.eclipse.jgit.api.errors.GitAPIException;
 | 
				
			||||||
import org.springframework.beans.factory.annotation.Value;
 | 
					import org.springframework.beans.factory.annotation.Value;
 | 
				
			||||||
import org.springframework.stereotype.Service;
 | 
					import org.springframework.stereotype.Service;
 | 
				
			||||||
import org.springframework.transaction.support.TransactionTemplate;
 | 
					import org.springframework.transaction.support.TransactionTemplate;
 | 
				
			||||||
import org.thingsboard.common.util.JacksonUtil;
 | 
					import org.thingsboard.common.util.JacksonUtil;
 | 
				
			||||||
import org.thingsboard.server.common.data.DataConstants;
 | 
					import org.thingsboard.server.common.data.AdminSettings;
 | 
				
			||||||
import org.thingsboard.server.common.data.EntityType;
 | 
					import org.thingsboard.server.common.data.EntityType;
 | 
				
			||||||
import org.thingsboard.server.common.data.ExportableEntity;
 | 
					import org.thingsboard.server.common.data.ExportableEntity;
 | 
				
			||||||
 | 
					import org.thingsboard.server.common.data.StringUtils;
 | 
				
			||||||
 | 
					import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
 | 
				
			||||||
import org.thingsboard.server.common.data.exception.ThingsboardException;
 | 
					import org.thingsboard.server.common.data.exception.ThingsboardException;
 | 
				
			||||||
import org.thingsboard.server.common.data.id.CustomerId;
 | 
					import org.thingsboard.server.common.data.id.CustomerId;
 | 
				
			||||||
import org.thingsboard.server.common.data.id.EntityId;
 | 
					import org.thingsboard.server.common.data.id.EntityId;
 | 
				
			||||||
import org.thingsboard.server.common.data.id.EntityIdFactory;
 | 
					import org.thingsboard.server.common.data.id.EntityIdFactory;
 | 
				
			||||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
					import org.thingsboard.server.common.data.id.TenantId;
 | 
				
			||||||
import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry;
 | 
					import org.thingsboard.server.common.data.query.*;
 | 
				
			||||||
import org.thingsboard.server.common.data.kv.JsonDataEntry;
 | 
					import org.thingsboard.server.common.data.vc.EntitiesVersionControlSettings;
 | 
				
			||||||
import org.thingsboard.server.common.data.kv.KvEntry;
 | 
					import org.thingsboard.server.common.data.vc.VersionControlAuthMethod;
 | 
				
			||||||
import org.thingsboard.server.common.data.query.EntityDataPageLink;
 | 
					 | 
				
			||||||
import org.thingsboard.server.common.data.query.EntityDataQuery;
 | 
					 | 
				
			||||||
import org.thingsboard.server.common.data.query.EntityDataSortOrder;
 | 
					 | 
				
			||||||
import org.thingsboard.server.common.data.query.EntityKey;
 | 
					 | 
				
			||||||
import org.thingsboard.server.common.data.query.EntityKeyType;
 | 
					 | 
				
			||||||
import org.thingsboard.server.common.data.query.EntityTypeFilter;
 | 
					 | 
				
			||||||
import org.thingsboard.server.dao.DaoUtil;
 | 
					import org.thingsboard.server.dao.DaoUtil;
 | 
				
			||||||
import org.thingsboard.server.dao.attributes.AttributesService;
 | 
					 | 
				
			||||||
import org.thingsboard.server.dao.entity.EntityService;
 | 
					import org.thingsboard.server.dao.entity.EntityService;
 | 
				
			||||||
 | 
					import org.thingsboard.server.dao.settings.AdminSettingsService;
 | 
				
			||||||
import org.thingsboard.server.dao.tenant.TenantDao;
 | 
					import org.thingsboard.server.dao.tenant.TenantDao;
 | 
				
			||||||
import org.thingsboard.server.queue.util.AfterStartUp;
 | 
					import org.thingsboard.server.queue.util.AfterStartUp;
 | 
				
			||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
 | 
					import org.thingsboard.server.queue.util.TbCoreComponent;
 | 
				
			||||||
@ -58,17 +53,11 @@ import org.thingsboard.server.service.sync.exportimport.exporting.data.EntityExp
 | 
				
			|||||||
import org.thingsboard.server.service.sync.exportimport.exporting.data.EntityExportSettings;
 | 
					import org.thingsboard.server.service.sync.exportimport.exporting.data.EntityExportSettings;
 | 
				
			||||||
import org.thingsboard.server.service.sync.exportimport.importing.data.EntityImportResult;
 | 
					import org.thingsboard.server.service.sync.exportimport.importing.data.EntityImportResult;
 | 
				
			||||||
import org.thingsboard.server.service.sync.exportimport.importing.data.EntityImportSettings;
 | 
					import org.thingsboard.server.service.sync.exportimport.importing.data.EntityImportSettings;
 | 
				
			||||||
import org.thingsboard.server.service.sync.vc.data.EntitiesVersionControlSettings;
 | 
					 | 
				
			||||||
import org.thingsboard.server.service.sync.vc.data.EntityVersion;
 | 
					import org.thingsboard.server.service.sync.vc.data.EntityVersion;
 | 
				
			||||||
import org.thingsboard.server.service.sync.vc.data.VersionCreationResult;
 | 
					import org.thingsboard.server.service.sync.vc.data.VersionCreationResult;
 | 
				
			||||||
import org.thingsboard.server.service.sync.vc.data.VersionLoadResult;
 | 
					import org.thingsboard.server.service.sync.vc.data.VersionLoadResult;
 | 
				
			||||||
import org.thingsboard.server.service.sync.vc.data.VersionedEntityInfo;
 | 
					import org.thingsboard.server.service.sync.vc.data.VersionedEntityInfo;
 | 
				
			||||||
import org.thingsboard.server.service.sync.vc.data.request.create.EntityListVersionCreateRequest;
 | 
					import org.thingsboard.server.service.sync.vc.data.request.create.*;
 | 
				
			||||||
import org.thingsboard.server.service.sync.vc.data.request.create.ComplexVersionCreateRequest;
 | 
					 | 
				
			||||||
import org.thingsboard.server.service.sync.vc.data.request.create.SingleEntityVersionCreateRequest;
 | 
					 | 
				
			||||||
import org.thingsboard.server.service.sync.vc.data.request.create.SyncStrategy;
 | 
					 | 
				
			||||||
import org.thingsboard.server.service.sync.vc.data.request.create.VersionCreateConfig;
 | 
					 | 
				
			||||||
import org.thingsboard.server.service.sync.vc.data.request.create.VersionCreateRequest;
 | 
					 | 
				
			||||||
import org.thingsboard.server.service.sync.vc.data.request.load.EntityTypeVersionLoadRequest;
 | 
					import org.thingsboard.server.service.sync.vc.data.request.load.EntityTypeVersionLoadRequest;
 | 
				
			||||||
import org.thingsboard.server.service.sync.vc.data.request.load.SingleEntityVersionLoadRequest;
 | 
					import org.thingsboard.server.service.sync.vc.data.request.load.SingleEntityVersionLoadRequest;
 | 
				
			||||||
import org.thingsboard.server.service.sync.vc.data.request.load.VersionLoadConfig;
 | 
					import org.thingsboard.server.service.sync.vc.data.request.load.VersionLoadConfig;
 | 
				
			||||||
@ -81,13 +70,7 @@ import java.io.IOException;
 | 
				
			|||||||
import java.nio.charset.StandardCharsets;
 | 
					import java.nio.charset.StandardCharsets;
 | 
				
			||||||
import java.nio.file.Files;
 | 
					import java.nio.file.Files;
 | 
				
			||||||
import java.nio.file.Path;
 | 
					import java.nio.file.Path;
 | 
				
			||||||
import java.util.ArrayList;
 | 
					import java.util.*;
 | 
				
			||||||
import java.util.Collections;
 | 
					 | 
				
			||||||
import java.util.HashMap;
 | 
					 | 
				
			||||||
import java.util.List;
 | 
					 | 
				
			||||||
import java.util.Map;
 | 
					 | 
				
			||||||
import java.util.Optional;
 | 
					 | 
				
			||||||
import java.util.Set;
 | 
					 | 
				
			||||||
import java.util.concurrent.ConcurrentHashMap;
 | 
					import java.util.concurrent.ConcurrentHashMap;
 | 
				
			||||||
import java.util.concurrent.Executors;
 | 
					import java.util.concurrent.Executors;
 | 
				
			||||||
import java.util.concurrent.TimeUnit;
 | 
					import java.util.concurrent.TimeUnit;
 | 
				
			||||||
@ -104,7 +87,7 @@ public class DefaultEntitiesVersionControlService implements EntitiesVersionCont
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private final EntitiesExportImportService exportImportService;
 | 
					    private final EntitiesExportImportService exportImportService;
 | 
				
			||||||
    private final ExportableEntitiesService exportableEntitiesService;
 | 
					    private final ExportableEntitiesService exportableEntitiesService;
 | 
				
			||||||
    private final AttributesService attributesService;
 | 
					    private final AdminSettingsService adminSettingsService;
 | 
				
			||||||
    private final EntityService entityService;
 | 
					    private final EntityService entityService;
 | 
				
			||||||
    private final TenantDao tenantDao;
 | 
					    private final TenantDao tenantDao;
 | 
				
			||||||
    private final TransactionTemplate transactionTemplate;
 | 
					    private final TransactionTemplate transactionTemplate;
 | 
				
			||||||
@ -114,14 +97,14 @@ public class DefaultEntitiesVersionControlService implements EntitiesVersionCont
 | 
				
			|||||||
    @Value("${java.io.tmpdir}/repositories")
 | 
					    @Value("${java.io.tmpdir}/repositories")
 | 
				
			||||||
    private String repositoriesFolder;
 | 
					    private String repositoriesFolder;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private static final String SETTINGS_KEY = "vc";
 | 
					    private static final String SETTINGS_KEY = "entitiesVersionControl";
 | 
				
			||||||
    private final ObjectWriter jsonWriter = new ObjectMapper().writer(SerializationFeature.INDENT_OUTPUT);
 | 
					    private final ObjectWriter jsonWriter = new ObjectMapper().writer(SerializationFeature.INDENT_OUTPUT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @AfterStartUp
 | 
					    @AfterStartUp
 | 
				
			||||||
    public void init() {
 | 
					    public void init() {
 | 
				
			||||||
        DaoUtil.processInBatches(tenantDao::findTenantsIds, 100, tenantId -> {
 | 
					        DaoUtil.processInBatches(tenantDao::findTenantsIds, 100, tenantId -> {
 | 
				
			||||||
            EntitiesVersionControlSettings settings = getSettings(tenantId);
 | 
					            EntitiesVersionControlSettings settings = getVersionControlSettings(tenantId);
 | 
				
			||||||
            if (settings != null) {
 | 
					            if (settings != null) {
 | 
				
			||||||
                try {
 | 
					                try {
 | 
				
			||||||
                    initRepository(tenantId, settings);
 | 
					                    initRepository(tenantId, settings);
 | 
				
			||||||
@ -412,6 +395,73 @@ public class DefaultEntitiesVersionControlService implements EntitiesVersionCont
 | 
				
			|||||||
        return repository.listBranches();
 | 
					        return repository.listBranches();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public EntitiesVersionControlSettings getVersionControlSettings(TenantId tenantId) {
 | 
				
			||||||
 | 
					        AdminSettings adminSettings = adminSettingsService.findAdminSettingsByKey(tenantId, SETTINGS_KEY);
 | 
				
			||||||
 | 
					        if (adminSettings != null) {
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                return JacksonUtil.convertValue(adminSettings.getJsonValue(), EntitiesVersionControlSettings.class);
 | 
				
			||||||
 | 
					            } catch (Exception e) {
 | 
				
			||||||
 | 
					                throw new RuntimeException("Failed to load version control settings!", e);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public EntitiesVersionControlSettings saveVersionControlSettings(TenantId tenantId, EntitiesVersionControlSettings versionControlSettings) {
 | 
				
			||||||
 | 
					        EntitiesVersionControlSettings storedSettings = getVersionControlSettings(tenantId);
 | 
				
			||||||
 | 
					        versionControlSettings = this.restoreCredentials(versionControlSettings, storedSettings);
 | 
				
			||||||
 | 
					        AdminSettings adminSettings = new AdminSettings();
 | 
				
			||||||
 | 
					        adminSettings.setTenantId(tenantId);
 | 
				
			||||||
 | 
					        adminSettings.setKey(SETTINGS_KEY);
 | 
				
			||||||
 | 
					        adminSettings.setJsonValue(JacksonUtil.valueToTree(versionControlSettings));
 | 
				
			||||||
 | 
					        AdminSettings savedAdminSettings = adminSettingsService.saveAdminSettings(tenantId, adminSettings);
 | 
				
			||||||
 | 
					        EntitiesVersionControlSettings savedVersionControlSettings;
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            savedVersionControlSettings = JacksonUtil.convertValue(savedAdminSettings.getJsonValue(), EntitiesVersionControlSettings.class);
 | 
				
			||||||
 | 
					        } catch (Exception e) {
 | 
				
			||||||
 | 
					            throw new RuntimeException("Failed to load version control settings!", e);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            clearRepository(tenantId);
 | 
				
			||||||
 | 
					            initRepository(tenantId, savedVersionControlSettings);
 | 
				
			||||||
 | 
					        } catch (Exception e) {
 | 
				
			||||||
 | 
					            throw new RuntimeException("Failed to init repository!", e);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return savedVersionControlSettings;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void checkVersionControlAccess(TenantId tenantId, EntitiesVersionControlSettings settings) throws ThingsboardException {
 | 
				
			||||||
 | 
					        EntitiesVersionControlSettings storedSettings = getVersionControlSettings(tenantId);
 | 
				
			||||||
 | 
					        settings = this.restoreCredentials(settings, storedSettings);
 | 
				
			||||||
 | 
					        Path repositoryDirectory = Path.of(repositoriesFolder, tenantId.getId().toString());
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            GitRepository.test(settings, repositoryDirectory.toFile());
 | 
				
			||||||
 | 
					        } catch (GitAPIException e) {
 | 
				
			||||||
 | 
					            throw new ThingsboardException(String.format("Unable to access repository: %s", e.getMessage()),
 | 
				
			||||||
 | 
					                    ThingsboardErrorCode.GENERAL);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private EntitiesVersionControlSettings restoreCredentials(EntitiesVersionControlSettings settings, EntitiesVersionControlSettings storedSettings) {
 | 
				
			||||||
 | 
					        VersionControlAuthMethod authMethod = settings.getAuthMethod();
 | 
				
			||||||
 | 
					        if (VersionControlAuthMethod.USERNAME_PASSWORD.equals(authMethod) && settings.getPassword() == null) {
 | 
				
			||||||
 | 
					            if (storedSettings != null) {
 | 
				
			||||||
 | 
					                settings.setPassword(storedSettings.getPassword());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else if (VersionControlAuthMethod.PRIVATE_KEY.equals(authMethod) && settings.getPrivateKey() == null) {
 | 
				
			||||||
 | 
					            if (storedSettings != null) {
 | 
				
			||||||
 | 
					                settings.setPrivateKey(storedSettings.getPrivateKey());
 | 
				
			||||||
 | 
					                if (StringUtils.isEmpty(settings.getPrivateKeyPassword()) &&
 | 
				
			||||||
 | 
					                        StringUtils.isNotEmpty(storedSettings.getPrivateKeyPassword())) {
 | 
				
			||||||
 | 
					                    settings.setPrivateKeyPassword(storedSettings.getPrivateKeyPassword());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return settings;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private EntityVersion checkVersion(TenantId tenantId, String branch, String versionId) throws Exception {
 | 
					    private EntityVersion checkVersion(TenantId tenantId, String branch, String versionId) throws Exception {
 | 
				
			||||||
        return listVersions(tenantId, branch, null).stream()
 | 
					        return listVersions(tenantId, branch, null).stream()
 | 
				
			||||||
@ -426,11 +476,12 @@ public class DefaultEntitiesVersionControlService implements EntitiesVersionCont
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private void initRepository(TenantId tenantId, EntitiesVersionControlSettings settings) throws Exception {
 | 
					    private void initRepository(TenantId tenantId, EntitiesVersionControlSettings settings) throws Exception {
 | 
				
			||||||
        Path repositoryDirectory = Path.of(repositoriesFolder, tenantId.getId().toString());
 | 
					        Path repositoryDirectory = Path.of(repositoriesFolder, tenantId.getId().toString());
 | 
				
			||||||
        GitRepository repository;
 | 
					 | 
				
			||||||
        FileUtils.forceDelete(repositoryDirectory.toFile());
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        FileUtils.forceDelete(repositoryDirectory.toFile());
 | 
				
			||||||
        Files.createDirectories(repositoryDirectory);
 | 
					        Files.createDirectories(repositoryDirectory);
 | 
				
			||||||
        repository = GitRepository.clone(settings.getRepositoryUri(), settings.getUsername(), settings.getPassword(), repositoryDirectory.toFile());
 | 
					
 | 
				
			||||||
 | 
					        GitRepository repository = GitRepository.clone(settings, repositoryDirectory.toFile());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        repositories.put(tenantId, repository);
 | 
					        repositories.put(tenantId, repository);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -442,34 +493,6 @@ public class DefaultEntitiesVersionControlService implements EntitiesVersionCont
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    @SneakyThrows
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public void saveSettings(TenantId tenantId, EntitiesVersionControlSettings settings) {
 | 
					 | 
				
			||||||
        attributesService.save(tenantId, tenantId, DataConstants.SERVER_SCOPE, List.of(
 | 
					 | 
				
			||||||
                new BaseAttributeKvEntry(System.currentTimeMillis(), new JsonDataEntry(SETTINGS_KEY, JacksonUtil.toString(settings)))
 | 
					 | 
				
			||||||
        )).get();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        clearRepository(tenantId);
 | 
					 | 
				
			||||||
        initRepository(tenantId, settings);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @SneakyThrows
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public EntitiesVersionControlSettings getSettings(TenantId tenantId) {
 | 
					 | 
				
			||||||
        return attributesService.find(tenantId, tenantId, DataConstants.SERVER_SCOPE, SETTINGS_KEY).get()
 | 
					 | 
				
			||||||
                .flatMap(KvEntry::getJsonValue)
 | 
					 | 
				
			||||||
                .map(json -> {
 | 
					 | 
				
			||||||
                    try {
 | 
					 | 
				
			||||||
                        return JacksonUtil.fromString(json, EntitiesVersionControlSettings.class);
 | 
					 | 
				
			||||||
                    } catch (IllegalArgumentException e) {
 | 
					 | 
				
			||||||
                        return null;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
                .orElse(null);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private EntityVersion toVersion(GitRepository.Commit commit) {
 | 
					    private EntityVersion toVersion(GitRepository.Commit commit) {
 | 
				
			||||||
        return new EntityVersion(commit.getId(), commit.getMessage());
 | 
					        return new EntityVersion(commit.getId(), commit.getMessage());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -16,16 +16,17 @@
 | 
				
			|||||||
package org.thingsboard.server.service.sync.vc;
 | 
					package org.thingsboard.server.service.sync.vc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.thingsboard.server.common.data.EntityType;
 | 
					import org.thingsboard.server.common.data.EntityType;
 | 
				
			||||||
 | 
					import org.thingsboard.server.common.data.exception.ThingsboardException;
 | 
				
			||||||
import org.thingsboard.server.common.data.id.EntityId;
 | 
					import org.thingsboard.server.common.data.id.EntityId;
 | 
				
			||||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
					import org.thingsboard.server.common.data.id.TenantId;
 | 
				
			||||||
 | 
					import org.thingsboard.server.common.data.vc.EntitiesVersionControlSettings;
 | 
				
			||||||
import org.thingsboard.server.service.security.model.SecurityUser;
 | 
					import org.thingsboard.server.service.security.model.SecurityUser;
 | 
				
			||||||
import org.thingsboard.server.service.sync.vc.data.EntitiesVersionControlSettings;
 | 
					 | 
				
			||||||
import org.thingsboard.server.service.sync.vc.data.EntityVersion;
 | 
					import org.thingsboard.server.service.sync.vc.data.EntityVersion;
 | 
				
			||||||
import org.thingsboard.server.service.sync.vc.data.VersionCreationResult;
 | 
					import org.thingsboard.server.service.sync.vc.data.VersionCreationResult;
 | 
				
			||||||
import org.thingsboard.server.service.sync.vc.data.VersionLoadResult;
 | 
					import org.thingsboard.server.service.sync.vc.data.VersionLoadResult;
 | 
				
			||||||
import org.thingsboard.server.service.sync.vc.data.VersionedEntityInfo;
 | 
					import org.thingsboard.server.service.sync.vc.data.VersionedEntityInfo;
 | 
				
			||||||
import org.thingsboard.server.service.sync.vc.data.request.load.VersionLoadRequest;
 | 
					 | 
				
			||||||
import org.thingsboard.server.service.sync.vc.data.request.create.VersionCreateRequest;
 | 
					import org.thingsboard.server.service.sync.vc.data.request.create.VersionCreateRequest;
 | 
				
			||||||
 | 
					import org.thingsboard.server.service.sync.vc.data.request.load.VersionLoadRequest;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -51,9 +52,12 @@ public interface EntitiesVersionControlService {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    List<String> listBranches(TenantId tenantId) throws Exception;
 | 
					    List<String> listBranches(TenantId tenantId) throws Exception;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    EntitiesVersionControlSettings getVersionControlSettings(TenantId tenantId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    EntitiesVersionControlSettings saveVersionControlSettings(TenantId tenantId, EntitiesVersionControlSettings versionControlSettings);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void checkVersionControlAccess(TenantId tenantId, EntitiesVersionControlSettings settings) throws ThingsboardException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void saveSettings(TenantId tenantId, EntitiesVersionControlSettings settings);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    EntitiesVersionControlSettings getSettings(TenantId tenantId);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -18,14 +18,8 @@ package org.thingsboard.server.utils;
 | 
				
			|||||||
import com.google.common.collect.Streams;
 | 
					import com.google.common.collect.Streams;
 | 
				
			||||||
import lombok.Data;
 | 
					import lombok.Data;
 | 
				
			||||||
import lombok.Getter;
 | 
					import lombok.Getter;
 | 
				
			||||||
import org.apache.commons.lang3.StringUtils;
 | 
					import org.apache.sshd.common.util.security.SecurityUtils;
 | 
				
			||||||
import org.eclipse.jgit.api.Git;
 | 
					import org.eclipse.jgit.api.*;
 | 
				
			||||||
import org.eclipse.jgit.api.GitCommand;
 | 
					 | 
				
			||||||
import org.eclipse.jgit.api.ListBranchCommand;
 | 
					 | 
				
			||||||
import org.eclipse.jgit.api.LogCommand;
 | 
					 | 
				
			||||||
import org.eclipse.jgit.api.RmCommand;
 | 
					 | 
				
			||||||
import org.eclipse.jgit.api.Status;
 | 
					 | 
				
			||||||
import org.eclipse.jgit.api.TransportCommand;
 | 
					 | 
				
			||||||
import org.eclipse.jgit.api.errors.GitAPIException;
 | 
					import org.eclipse.jgit.api.errors.GitAPIException;
 | 
				
			||||||
import org.eclipse.jgit.lib.Constants;
 | 
					import org.eclipse.jgit.lib.Constants;
 | 
				
			||||||
import org.eclipse.jgit.lib.ObjectId;
 | 
					import org.eclipse.jgit.lib.ObjectId;
 | 
				
			||||||
@ -34,50 +28,88 @@ import org.eclipse.jgit.lib.ObjectReader;
 | 
				
			|||||||
import org.eclipse.jgit.revwalk.RevCommit;
 | 
					import org.eclipse.jgit.revwalk.RevCommit;
 | 
				
			||||||
import org.eclipse.jgit.revwalk.filter.RevFilter;
 | 
					import org.eclipse.jgit.revwalk.filter.RevFilter;
 | 
				
			||||||
import org.eclipse.jgit.transport.CredentialsProvider;
 | 
					import org.eclipse.jgit.transport.CredentialsProvider;
 | 
				
			||||||
 | 
					import org.eclipse.jgit.transport.SshTransport;
 | 
				
			||||||
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
 | 
					import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
 | 
				
			||||||
 | 
					import org.eclipse.jgit.transport.sshd.JGitKeyCache;
 | 
				
			||||||
 | 
					import org.eclipse.jgit.transport.sshd.ServerKeyDatabase;
 | 
				
			||||||
 | 
					import org.eclipse.jgit.transport.sshd.SshdSessionFactory;
 | 
				
			||||||
 | 
					import org.eclipse.jgit.transport.sshd.SshdSessionFactoryBuilder;
 | 
				
			||||||
import org.eclipse.jgit.treewalk.TreeWalk;
 | 
					import org.eclipse.jgit.treewalk.TreeWalk;
 | 
				
			||||||
import org.eclipse.jgit.treewalk.filter.PathFilter;
 | 
					import org.eclipse.jgit.treewalk.filter.PathFilter;
 | 
				
			||||||
 | 
					import org.thingsboard.server.common.data.StringUtils;
 | 
				
			||||||
 | 
					import org.thingsboard.server.common.data.vc.EntitiesVersionControlSettings;
 | 
				
			||||||
 | 
					import org.thingsboard.server.common.data.vc.VersionControlAuthMethod;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.io.ByteArrayInputStream;
 | 
				
			||||||
import java.io.File;
 | 
					import java.io.File;
 | 
				
			||||||
import java.io.IOException;
 | 
					import java.io.IOException;
 | 
				
			||||||
 | 
					import java.net.InetSocketAddress;
 | 
				
			||||||
import java.nio.charset.StandardCharsets;
 | 
					import java.nio.charset.StandardCharsets;
 | 
				
			||||||
 | 
					import java.security.KeyPair;
 | 
				
			||||||
 | 
					import java.security.PublicKey;
 | 
				
			||||||
import java.util.ArrayList;
 | 
					import java.util.ArrayList;
 | 
				
			||||||
 | 
					import java.util.Collections;
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
import java.util.Set;
 | 
					import java.util.Set;
 | 
				
			||||||
import java.util.concurrent.locks.ReadWriteLock;
 | 
					 | 
				
			||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
 | 
					 | 
				
			||||||
import java.util.stream.Collectors;
 | 
					import java.util.stream.Collectors;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class GitRepository {
 | 
					public class GitRepository {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private final Git git;
 | 
					    private final Git git;
 | 
				
			||||||
    private final CredentialsProvider credentialsProvider;
 | 
					    private final CredentialsProvider credentialsProvider;
 | 
				
			||||||
 | 
					    private final SshdSessionFactory sshSessionFactory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Getter
 | 
					    @Getter
 | 
				
			||||||
    private final String directory;
 | 
					    private final String directory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private GitRepository(Git git, CredentialsProvider credentialsProvider, String directory) {
 | 
					    private GitRepository(Git git, CredentialsProvider credentialsProvider, SshdSessionFactory sshSessionFactory, String directory) {
 | 
				
			||||||
        this.git = git;
 | 
					        this.git = git;
 | 
				
			||||||
        this.credentialsProvider = credentialsProvider;
 | 
					        this.credentialsProvider = credentialsProvider;
 | 
				
			||||||
 | 
					        this.sshSessionFactory = sshSessionFactory;
 | 
				
			||||||
        this.directory = directory;
 | 
					        this.directory = directory;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static GitRepository clone(String uri, String username, String password, File directory) throws GitAPIException {
 | 
					    public static GitRepository clone(EntitiesVersionControlSettings settings, File directory) throws GitAPIException {
 | 
				
			||||||
        CredentialsProvider credentialsProvider = newCredentialsProvider(username, password);
 | 
					        CredentialsProvider credentialsProvider = null;
 | 
				
			||||||
        Git git = Git.cloneRepository()
 | 
					        SshdSessionFactory sshSessionFactory = null;
 | 
				
			||||||
                .setURI(uri)
 | 
					        if (VersionControlAuthMethod.USERNAME_PASSWORD.equals(settings.getAuthMethod())) {
 | 
				
			||||||
 | 
					            credentialsProvider = newCredentialsProvider(settings.getUsername(), settings.getPassword());
 | 
				
			||||||
 | 
					        } else if (VersionControlAuthMethod.PRIVATE_KEY.equals(settings.getAuthMethod())) {
 | 
				
			||||||
 | 
					            sshSessionFactory = newSshdSessionFactory(settings.getPrivateKey(), settings.getPrivateKeyPassword(), directory);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        CloneCommand cloneCommand = Git.cloneRepository()
 | 
				
			||||||
 | 
					                .setURI(settings.getRepositoryUri())
 | 
				
			||||||
                .setDirectory(directory)
 | 
					                .setDirectory(directory)
 | 
				
			||||||
                .setNoCheckout(true)
 | 
					                .setNoCheckout(true);
 | 
				
			||||||
                .setCredentialsProvider(credentialsProvider)
 | 
					        configureTransportCommand(cloneCommand, credentialsProvider, sshSessionFactory);
 | 
				
			||||||
                .call();
 | 
					        Git git = cloneCommand.call();
 | 
				
			||||||
        return new GitRepository(git, credentialsProvider, directory.getAbsolutePath());
 | 
					        return new GitRepository(git, credentialsProvider, sshSessionFactory, directory.getAbsolutePath());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static GitRepository open(File directory, String username, String password) throws IOException {
 | 
					    public static GitRepository open(File directory, EntitiesVersionControlSettings settings) throws IOException {
 | 
				
			||||||
        Git git = Git.open(directory);
 | 
					        Git git = Git.open(directory);
 | 
				
			||||||
        return new GitRepository(git, newCredentialsProvider(username, password), directory.getAbsolutePath());
 | 
					        CredentialsProvider credentialsProvider = null;
 | 
				
			||||||
 | 
					        SshdSessionFactory sshSessionFactory = null;
 | 
				
			||||||
 | 
					        if (VersionControlAuthMethod.USERNAME_PASSWORD.equals(settings.getAuthMethod())) {
 | 
				
			||||||
 | 
					            credentialsProvider = newCredentialsProvider(settings.getUsername(), settings.getPassword());
 | 
				
			||||||
 | 
					        } else if (VersionControlAuthMethod.PRIVATE_KEY.equals(settings.getAuthMethod())) {
 | 
				
			||||||
 | 
					            sshSessionFactory = newSshdSessionFactory(settings.getPrivateKey(), settings.getPrivateKeyPassword(), directory);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return new GitRepository(git, credentialsProvider, sshSessionFactory, directory.getAbsolutePath());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static void test(EntitiesVersionControlSettings settings, File directory) throws GitAPIException {
 | 
				
			||||||
 | 
					        CredentialsProvider credentialsProvider = null;
 | 
				
			||||||
 | 
					        SshdSessionFactory sshSessionFactory = null;
 | 
				
			||||||
 | 
					        if (VersionControlAuthMethod.USERNAME_PASSWORD.equals(settings.getAuthMethod())) {
 | 
				
			||||||
 | 
					            credentialsProvider = newCredentialsProvider(settings.getUsername(), settings.getPassword());
 | 
				
			||||||
 | 
					        } else if (VersionControlAuthMethod.PRIVATE_KEY.equals(settings.getAuthMethod())) {
 | 
				
			||||||
 | 
					            sshSessionFactory = newSshdSessionFactory(settings.getPrivateKey(), settings.getPrivateKeyPassword(), directory);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        LsRemoteCommand lsRemoteCommand = Git.lsRemoteRepository().setRemote(settings.getRepositoryUri());
 | 
				
			||||||
 | 
					        configureTransportCommand(lsRemoteCommand, credentialsProvider, sshSessionFactory);
 | 
				
			||||||
 | 
					        lsRemoteCommand.call();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void fetch() throws GitAPIException {
 | 
					    public void fetch() throws GitAPIException {
 | 
				
			||||||
        execute(git.fetch()
 | 
					        execute(git.fetch()
 | 
				
			||||||
@ -108,7 +140,6 @@ public class GitRepository {
 | 
				
			|||||||
                .distinct().collect(Collectors.toList());
 | 
					                .distinct().collect(Collectors.toList());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    public List<Commit> listCommits(String branch, int limit) throws IOException, GitAPIException {
 | 
					    public List<Commit> listCommits(String branch, int limit) throws IOException, GitAPIException {
 | 
				
			||||||
        return listCommits(branch, null, limit);
 | 
					        return listCommits(branch, null, limit);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -246,16 +277,66 @@ public class GitRepository {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private <C extends GitCommand<T>, T> T execute(C command) throws GitAPIException {
 | 
					    private <C extends GitCommand<T>, T> T execute(C command) throws GitAPIException {
 | 
				
			||||||
        if (command instanceof TransportCommand && credentialsProvider != null) {
 | 
					        if (command instanceof TransportCommand) {
 | 
				
			||||||
            ((TransportCommand<?, ?>) command).setCredentialsProvider(credentialsProvider);
 | 
					            configureTransportCommand((TransportCommand) command, credentialsProvider, sshSessionFactory);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return command.call();
 | 
					        return command.call();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private static CredentialsProvider newCredentialsProvider(String username, String password) {
 | 
					    private static void configureTransportCommand(TransportCommand transportCommand, CredentialsProvider credentialsProvider, SshdSessionFactory sshSessionFactory) {
 | 
				
			||||||
        return new UsernamePasswordCredentialsProvider(username, password);
 | 
					        if (credentialsProvider != null) {
 | 
				
			||||||
 | 
					            transportCommand.setCredentialsProvider(credentialsProvider);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (sshSessionFactory != null) {
 | 
				
			||||||
 | 
					            transportCommand.setTransportConfigCallback(transport -> {
 | 
				
			||||||
 | 
					                if (transport instanceof SshTransport) {
 | 
				
			||||||
 | 
					                    SshTransport sshTransport = (SshTransport) transport;
 | 
				
			||||||
 | 
					                    sshTransport.setSshSessionFactory(sshSessionFactory);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static CredentialsProvider newCredentialsProvider(String username, String password) {
 | 
				
			||||||
 | 
					        return new UsernamePasswordCredentialsProvider(username, password == null ? "" : password);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static SshdSessionFactory newSshdSessionFactory(String privateKey, String password, File directory) {
 | 
				
			||||||
 | 
					        SshdSessionFactory sshSessionFactory = null;
 | 
				
			||||||
 | 
					        if (StringUtils.isNotBlank(privateKey)) {
 | 
				
			||||||
 | 
					            Iterable<KeyPair> keyPairs = loadKeyPairs(privateKey, password);
 | 
				
			||||||
 | 
					            sshSessionFactory = new SshdSessionFactoryBuilder()
 | 
				
			||||||
 | 
					                    .setPreferredAuthentications("publickey")
 | 
				
			||||||
 | 
					                    .setDefaultKeysProvider(file -> keyPairs)
 | 
				
			||||||
 | 
					                    .setHomeDirectory(directory)
 | 
				
			||||||
 | 
					                    .setSshDirectory(directory)
 | 
				
			||||||
 | 
					                    .setServerKeyDatabase((file, file2) -> new ServerKeyDatabase() {
 | 
				
			||||||
 | 
					                        @Override
 | 
				
			||||||
 | 
					                        public List<PublicKey> lookup(String connectAddress, InetSocketAddress remoteAddress, Configuration config) {
 | 
				
			||||||
 | 
					                            return Collections.emptyList();
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        @Override
 | 
				
			||||||
 | 
					                        public boolean accept(String connectAddress, InetSocketAddress remoteAddress, PublicKey serverKey, Configuration config, CredentialsProvider provider) {
 | 
				
			||||||
 | 
					                            return true;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                    .build(new JGitKeyCache());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return sshSessionFactory;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static Iterable<KeyPair> loadKeyPairs(String privateKeyContent, String password) {
 | 
				
			||||||
 | 
					        Iterable<KeyPair> keyPairs = null;
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            keyPairs = SecurityUtils.loadKeyPairIdentities(null,
 | 
				
			||||||
 | 
					                    null, new ByteArrayInputStream(privateKeyContent.getBytes()), (session, resourceKey, retryIndex) -> password);
 | 
				
			||||||
 | 
					        } catch (Exception e) {}
 | 
				
			||||||
 | 
					        if (keyPairs == null) {
 | 
				
			||||||
 | 
					            throw new IllegalArgumentException("Failed to load ssh private key");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return keyPairs;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Data
 | 
					    @Data
 | 
				
			||||||
    public static class Commit {
 | 
					    public static class Commit {
 | 
				
			||||||
 | 
				
			|||||||
@ -21,14 +21,17 @@ import org.thingsboard.server.common.data.id.AdminSettingsId;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import com.fasterxml.jackson.databind.JsonNode;
 | 
					import com.fasterxml.jackson.databind.JsonNode;
 | 
				
			||||||
import org.thingsboard.server.common.data.id.DeviceId;
 | 
					import org.thingsboard.server.common.data.id.DeviceId;
 | 
				
			||||||
 | 
					import org.thingsboard.server.common.data.id.TenantId;
 | 
				
			||||||
import org.thingsboard.server.common.data.validation.Length;
 | 
					import org.thingsboard.server.common.data.validation.Length;
 | 
				
			||||||
import org.thingsboard.server.common.data.validation.NoXss;
 | 
					import org.thingsboard.server.common.data.validation.NoXss;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ApiModel
 | 
					@ApiModel
 | 
				
			||||||
public class AdminSettings extends BaseData<AdminSettingsId> {
 | 
					public class AdminSettings extends BaseData<AdminSettingsId> implements HasTenantId {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private static final long serialVersionUID = -7670322981725511892L;
 | 
					    private static final long serialVersionUID = -7670322981725511892L;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private TenantId tenantId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @NoXss
 | 
					    @NoXss
 | 
				
			||||||
    @Length(fieldName = "key")
 | 
					    @Length(fieldName = "key")
 | 
				
			||||||
    private String key;
 | 
					    private String key;
 | 
				
			||||||
@ -44,6 +47,7 @@ public class AdminSettings extends BaseData<AdminSettingsId> {
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    public AdminSettings(AdminSettings adminSettings) {
 | 
					    public AdminSettings(AdminSettings adminSettings) {
 | 
				
			||||||
        super(adminSettings);
 | 
					        super(adminSettings);
 | 
				
			||||||
 | 
					        this.tenantId = adminSettings.getTenantId();
 | 
				
			||||||
        this.key = adminSettings.getKey();
 | 
					        this.key = adminSettings.getKey();
 | 
				
			||||||
        this.jsonValue = adminSettings.getJsonValue();
 | 
					        this.jsonValue = adminSettings.getJsonValue();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -60,7 +64,16 @@ public class AdminSettings extends BaseData<AdminSettingsId> {
 | 
				
			|||||||
        return super.getCreatedTime();
 | 
					        return super.getCreatedTime();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @ApiModelProperty(position = 3, value = "The Administration Settings key, (e.g. 'general' or 'mail')", example = "mail")
 | 
					    @ApiModelProperty(position = 3, value = "JSON object with Tenant Id.", readOnly = true)
 | 
				
			||||||
 | 
					    public TenantId getTenantId() {
 | 
				
			||||||
 | 
					        return tenantId;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void setTenantId(TenantId tenantId) {
 | 
				
			||||||
 | 
					        this.tenantId = tenantId;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ApiModelProperty(position = 4, value = "The Administration Settings key, (e.g. 'general' or 'mail')", example = "mail")
 | 
				
			||||||
    public String getKey() {
 | 
					    public String getKey() {
 | 
				
			||||||
        return key;
 | 
					        return key;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -69,7 +82,7 @@ public class AdminSettings extends BaseData<AdminSettingsId> {
 | 
				
			|||||||
        this.key = key;
 | 
					        this.key = key;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @ApiModelProperty(position = 4, value = "JSON representation of the Administration Settings value")
 | 
					    @ApiModelProperty(position = 5, value = "JSON representation of the Administration Settings value")
 | 
				
			||||||
    public JsonNode getJsonValue() {
 | 
					    public JsonNode getJsonValue() {
 | 
				
			||||||
        return jsonValue;
 | 
					        return jsonValue;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -17,6 +17,10 @@ package org.thingsboard.server.common.data;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
public class StringUtils {
 | 
					public class StringUtils {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static final String EMPTY = "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static final int INDEX_NOT_FOUND = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static boolean isEmpty(String source) {
 | 
					    public static boolean isEmpty(String source) {
 | 
				
			||||||
        return source == null || source.isEmpty();
 | 
					        return source == null || source.isEmpty();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -32,4 +36,42 @@ public class StringUtils {
 | 
				
			|||||||
    public static boolean isNotBlank(String source) {
 | 
					    public static boolean isNotBlank(String source) {
 | 
				
			||||||
        return source != null && !source.isEmpty() && !source.trim().isEmpty();
 | 
					        return source != null && !source.isEmpty() && !source.trim().isEmpty();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static String removeStart(final String str, final String remove) {
 | 
				
			||||||
 | 
					        if (isEmpty(str) || isEmpty(remove)) {
 | 
				
			||||||
 | 
					            return str;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (str.startsWith(remove)){
 | 
				
			||||||
 | 
					            return str.substring(remove.length());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return str;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static String substringBefore(final String str, final String separator) {
 | 
				
			||||||
 | 
					        if (isEmpty(str) || separator == null) {
 | 
				
			||||||
 | 
					            return str;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (separator.isEmpty()) {
 | 
				
			||||||
 | 
					            return EMPTY;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        final int pos = str.indexOf(separator);
 | 
				
			||||||
 | 
					        if (pos == INDEX_NOT_FOUND) {
 | 
				
			||||||
 | 
					            return str;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return str.substring(0, pos);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static String substringBetween(final String str, final String open, final String close) {
 | 
				
			||||||
 | 
					        if (str == null || open == null || close == null) {
 | 
				
			||||||
 | 
					            return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        final int start = str.indexOf(open);
 | 
				
			||||||
 | 
					        if (start != INDEX_NOT_FOUND) {
 | 
				
			||||||
 | 
					            final int end = str.indexOf(close, start + open.length());
 | 
				
			||||||
 | 
					            if (end != INDEX_NOT_FOUND) {
 | 
				
			||||||
 | 
					                return str.substring(start + open.length(), end);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -13,14 +13,18 @@
 | 
				
			|||||||
 * See the License for the specific language governing permissions and
 | 
					 * See the License for the specific language governing permissions and
 | 
				
			||||||
 * limitations under the License.
 | 
					 * limitations under the License.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
package org.thingsboard.server.service.sync.vc.data;
 | 
					package org.thingsboard.server.common.data.vc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import lombok.Data;
 | 
					import lombok.Data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Data
 | 
					@Data
 | 
				
			||||||
public class EntitiesVersionControlSettings {
 | 
					public class EntitiesVersionControlSettings {
 | 
				
			||||||
    private String repositoryUri;
 | 
					    private String repositoryUri;
 | 
				
			||||||
 | 
					    private VersionControlAuthMethod authMethod;
 | 
				
			||||||
    private String username;
 | 
					    private String username;
 | 
				
			||||||
    private String password;
 | 
					    private String password;
 | 
				
			||||||
 | 
					    private String privateKeyFileName;
 | 
				
			||||||
 | 
					    private String privateKey;
 | 
				
			||||||
 | 
					    private String privateKeyPassword;
 | 
				
			||||||
    private String defaultBranch;
 | 
					    private String defaultBranch;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Copyright © 2016-2022 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.vc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public enum VersionControlAuthMethod {
 | 
				
			||||||
 | 
					    USERNAME_PASSWORD,
 | 
				
			||||||
 | 
					    PRIVATE_KEY
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -90,6 +90,8 @@ public class ModelConstants {
 | 
				
			|||||||
     * Cassandra admin_settings constants.
 | 
					     * Cassandra admin_settings constants.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public static final String ADMIN_SETTINGS_COLUMN_FAMILY_NAME = "admin_settings";
 | 
					    public static final String ADMIN_SETTINGS_COLUMN_FAMILY_NAME = "admin_settings";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static final String ADMIN_SETTINGS_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY;
 | 
				
			||||||
    public static final String ADMIN_SETTINGS_KEY_PROPERTY = "key";
 | 
					    public static final String ADMIN_SETTINGS_KEY_PROPERTY = "key";
 | 
				
			||||||
    public static final String ADMIN_SETTINGS_JSON_VALUE_PROPERTY = "json_value";
 | 
					    public static final String ADMIN_SETTINGS_JSON_VALUE_PROPERTY = "json_value";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -22,14 +22,18 @@ import org.hibernate.annotations.Type;
 | 
				
			|||||||
import org.hibernate.annotations.TypeDef;
 | 
					import org.hibernate.annotations.TypeDef;
 | 
				
			||||||
import org.thingsboard.server.common.data.AdminSettings;
 | 
					import org.thingsboard.server.common.data.AdminSettings;
 | 
				
			||||||
import org.thingsboard.server.common.data.id.AdminSettingsId;
 | 
					import org.thingsboard.server.common.data.id.AdminSettingsId;
 | 
				
			||||||
 | 
					import org.thingsboard.server.common.data.id.TenantId;
 | 
				
			||||||
import org.thingsboard.server.dao.model.BaseEntity;
 | 
					import org.thingsboard.server.dao.model.BaseEntity;
 | 
				
			||||||
import org.thingsboard.server.dao.model.BaseSqlEntity;
 | 
					import org.thingsboard.server.dao.model.BaseSqlEntity;
 | 
				
			||||||
 | 
					import org.thingsboard.server.dao.model.ModelConstants;
 | 
				
			||||||
import org.thingsboard.server.dao.util.mapping.JsonStringType;
 | 
					import org.thingsboard.server.dao.util.mapping.JsonStringType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import javax.persistence.Column;
 | 
					import javax.persistence.Column;
 | 
				
			||||||
import javax.persistence.Entity;
 | 
					import javax.persistence.Entity;
 | 
				
			||||||
import javax.persistence.Table;
 | 
					import javax.persistence.Table;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.UUID;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static org.thingsboard.server.dao.model.ModelConstants.ADMIN_SETTINGS_COLUMN_FAMILY_NAME;
 | 
					import static org.thingsboard.server.dao.model.ModelConstants.ADMIN_SETTINGS_COLUMN_FAMILY_NAME;
 | 
				
			||||||
import static org.thingsboard.server.dao.model.ModelConstants.ADMIN_SETTINGS_JSON_VALUE_PROPERTY;
 | 
					import static org.thingsboard.server.dao.model.ModelConstants.ADMIN_SETTINGS_JSON_VALUE_PROPERTY;
 | 
				
			||||||
import static org.thingsboard.server.dao.model.ModelConstants.ADMIN_SETTINGS_KEY_PROPERTY;
 | 
					import static org.thingsboard.server.dao.model.ModelConstants.ADMIN_SETTINGS_KEY_PROPERTY;
 | 
				
			||||||
@ -41,6 +45,9 @@ import static org.thingsboard.server.dao.model.ModelConstants.ADMIN_SETTINGS_KEY
 | 
				
			|||||||
@Table(name = ADMIN_SETTINGS_COLUMN_FAMILY_NAME)
 | 
					@Table(name = ADMIN_SETTINGS_COLUMN_FAMILY_NAME)
 | 
				
			||||||
public final class AdminSettingsEntity extends BaseSqlEntity<AdminSettings> implements BaseEntity<AdminSettings> {
 | 
					public final class AdminSettingsEntity extends BaseSqlEntity<AdminSettings> implements BaseEntity<AdminSettings> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Column(name = ModelConstants.ADMIN_SETTINGS_TENANT_ID_PROPERTY)
 | 
				
			||||||
 | 
					    private UUID tenantId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Column(name = ADMIN_SETTINGS_KEY_PROPERTY)
 | 
					    @Column(name = ADMIN_SETTINGS_KEY_PROPERTY)
 | 
				
			||||||
    private String key;
 | 
					    private String key;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -57,6 +64,7 @@ public final class AdminSettingsEntity extends BaseSqlEntity<AdminSettings> impl
 | 
				
			|||||||
            this.setUuid(adminSettings.getId().getId());
 | 
					            this.setUuid(adminSettings.getId().getId());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        this.setCreatedTime(adminSettings.getCreatedTime());
 | 
					        this.setCreatedTime(adminSettings.getCreatedTime());
 | 
				
			||||||
 | 
					        this.tenantId = adminSettings.getTenantId().getId();
 | 
				
			||||||
        this.key = adminSettings.getKey();
 | 
					        this.key = adminSettings.getKey();
 | 
				
			||||||
        this.jsonValue = adminSettings.getJsonValue();
 | 
					        this.jsonValue = adminSettings.getJsonValue();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -65,6 +73,7 @@ public final class AdminSettingsEntity extends BaseSqlEntity<AdminSettings> impl
 | 
				
			|||||||
    public AdminSettings toData() {
 | 
					    public AdminSettings toData() {
 | 
				
			||||||
        AdminSettings adminSettings = new AdminSettings(new AdminSettingsId(id));
 | 
					        AdminSettings adminSettings = new AdminSettings(new AdminSettingsId(id));
 | 
				
			||||||
        adminSettings.setCreatedTime(createdTime);
 | 
					        adminSettings.setCreatedTime(createdTime);
 | 
				
			||||||
 | 
					        adminSettings.setTenantId(TenantId.fromUUID(tenantId));
 | 
				
			||||||
        adminSettings.setKey(key);
 | 
					        adminSettings.setKey(key);
 | 
				
			||||||
        adminSettings.setJsonValue(jsonValue);
 | 
					        adminSettings.setJsonValue(jsonValue);
 | 
				
			||||||
        return adminSettings;
 | 
					        return adminSettings;
 | 
				
			||||||
 | 
				
			|||||||
@ -19,6 +19,8 @@ import org.thingsboard.server.common.data.AdminSettings;
 | 
				
			|||||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
					import org.thingsboard.server.common.data.id.TenantId;
 | 
				
			||||||
import org.thingsboard.server.dao.Dao;
 | 
					import org.thingsboard.server.dao.Dao;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.UUID;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public interface AdminSettingsDao extends Dao<AdminSettings> {
 | 
					public interface AdminSettingsDao extends Dao<AdminSettings> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -35,6 +37,6 @@ public interface AdminSettingsDao extends Dao<AdminSettings> {
 | 
				
			|||||||
     * @param key the key
 | 
					     * @param key the key
 | 
				
			||||||
     * @return the admin settings object
 | 
					     * @return the admin settings object
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    AdminSettings findByKey(TenantId tenantId, String key);
 | 
					    AdminSettings findByTenantIdAndKey(UUID tenantId, String key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -22,6 +22,7 @@ import org.springframework.stereotype.Service;
 | 
				
			|||||||
import org.thingsboard.server.common.data.AdminSettings;
 | 
					import org.thingsboard.server.common.data.AdminSettings;
 | 
				
			||||||
import org.thingsboard.server.common.data.id.AdminSettingsId;
 | 
					import org.thingsboard.server.common.data.id.AdminSettingsId;
 | 
				
			||||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
					import org.thingsboard.server.common.data.id.TenantId;
 | 
				
			||||||
 | 
					import org.thingsboard.server.common.data.vc.VersionControlAuthMethod;
 | 
				
			||||||
import org.thingsboard.server.dao.service.DataValidator;
 | 
					import org.thingsboard.server.dao.service.DataValidator;
 | 
				
			||||||
import org.thingsboard.server.dao.service.Validator;
 | 
					import org.thingsboard.server.dao.service.Validator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -46,20 +47,35 @@ public class AdminSettingsServiceImpl implements AdminSettingsService {
 | 
				
			|||||||
    public AdminSettings findAdminSettingsByKey(TenantId tenantId, String key) {
 | 
					    public AdminSettings findAdminSettingsByKey(TenantId tenantId, String key) {
 | 
				
			||||||
        log.trace("Executing findAdminSettingsByKey [{}]", key);
 | 
					        log.trace("Executing findAdminSettingsByKey [{}]", key);
 | 
				
			||||||
        Validator.validateString(key, "Incorrect key " + key);
 | 
					        Validator.validateString(key, "Incorrect key " + key);
 | 
				
			||||||
        return adminSettingsDao.findByKey(tenantId, key);
 | 
					        return adminSettingsDao.findByTenantIdAndKey(tenantId.getId(), key);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public AdminSettings saveAdminSettings(TenantId tenantId, AdminSettings adminSettings) {
 | 
					    public AdminSettings saveAdminSettings(TenantId tenantId, AdminSettings adminSettings) {
 | 
				
			||||||
        log.trace("Executing saveAdminSettings [{}]", adminSettings);
 | 
					        log.trace("Executing saveAdminSettings [{}]", adminSettings);
 | 
				
			||||||
        adminSettingsValidator.validate(adminSettings, data -> tenantId);
 | 
					        adminSettingsValidator.validate(adminSettings, data -> tenantId);
 | 
				
			||||||
        if(adminSettings.getKey().equals("mail") && !adminSettings.getJsonValue().has("password")) {
 | 
					        if (adminSettings.getKey().equals("mail") && !adminSettings.getJsonValue().has("password")) {
 | 
				
			||||||
            AdminSettings mailSettings = findAdminSettingsByKey(tenantId, "mail");
 | 
					            AdminSettings mailSettings = findAdminSettingsByKey(tenantId, "mail");
 | 
				
			||||||
            if (mailSettings != null) {
 | 
					            if (mailSettings != null) {
 | 
				
			||||||
                ((ObjectNode) adminSettings.getJsonValue()).put("password", mailSettings.getJsonValue().get("password").asText());
 | 
					                ((ObjectNode) adminSettings.getJsonValue()).put("password", mailSettings.getJsonValue().get("password").asText());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					        } else if (adminSettings.getKey().equals("entitiesVersionControl")) {
 | 
				
			||||||
 | 
					            VersionControlAuthMethod authMethod = VersionControlAuthMethod.valueOf(adminSettings.getJsonValue().get("authMethod").asText());
 | 
				
			||||||
 | 
					            if (VersionControlAuthMethod.USERNAME_PASSWORD.equals(authMethod) && !adminSettings.getJsonValue().has("password")) {
 | 
				
			||||||
 | 
					                AdminSettings vcSettings = findAdminSettingsByKey(tenantId, "entitiesVersionControl");
 | 
				
			||||||
 | 
					                if (vcSettings != null) {
 | 
				
			||||||
 | 
					                    ((ObjectNode) adminSettings.getJsonValue()).put("password", vcSettings.getJsonValue().get("password").asText());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } else if (VersionControlAuthMethod.PRIVATE_KEY.equals(authMethod) && !adminSettings.getJsonValue().has("privateKey")) {
 | 
				
			||||||
 | 
					                AdminSettings vcSettings = findAdminSettingsByKey(tenantId, "entitiesVersionControl");
 | 
				
			||||||
 | 
					                if (vcSettings != null) {
 | 
				
			||||||
 | 
					                    ((ObjectNode) adminSettings.getJsonValue()).put("privateKey", vcSettings.getJsonValue().get("privateKey").asText());
 | 
				
			||||||
 | 
					                    if (!adminSettings.getJsonValue().has("privateKeyPassword") && vcSettings.getJsonValue().has("privateKeyPassword")) {
 | 
				
			||||||
 | 
					                        ((ObjectNode) adminSettings.getJsonValue()).put("privateKeyPassword", vcSettings.getJsonValue().get("privateKeyPassword").asText());
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        return adminSettingsDao.save(tenantId, adminSettings);
 | 
					        return adminSettingsDao.save(tenantId, adminSettings);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -25,5 +25,6 @@ import java.util.UUID;
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
public interface AdminSettingsRepository extends JpaRepository<AdminSettingsEntity, UUID> {
 | 
					public interface AdminSettingsRepository extends JpaRepository<AdminSettingsEntity, UUID> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    AdminSettingsEntity findByKey(String key);
 | 
					    AdminSettingsEntity findByTenantIdAndKey(UUID tenantId, String key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -46,7 +46,7 @@ public class JpaAdminSettingsDao extends JpaAbstractDao<AdminSettingsEntity, Adm
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public AdminSettings findByKey(TenantId tenantId, String key) {
 | 
					    public AdminSettings findByTenantIdAndKey(UUID tenantId, String key) {
 | 
				
			||||||
        return DaoUtil.getData(adminSettingsRepository.findByKey(key));
 | 
					        return DaoUtil.getData(adminSettingsRepository.findByTenantIdAndKey(tenantId, key));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -34,6 +34,7 @@ call insert_tb_schema_settings();
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
CREATE TABLE IF NOT EXISTS admin_settings (
 | 
					CREATE TABLE IF NOT EXISTS admin_settings (
 | 
				
			||||||
    id uuid NOT NULL CONSTRAINT admin_settings_pkey PRIMARY KEY,
 | 
					    id uuid NOT NULL CONSTRAINT admin_settings_pkey PRIMARY KEY,
 | 
				
			||||||
 | 
					    tenant_id uuid NOT NULL,
 | 
				
			||||||
    created_time bigint NOT NULL,
 | 
					    created_time bigint NOT NULL,
 | 
				
			||||||
    json_value varchar,
 | 
					    json_value varchar,
 | 
				
			||||||
    key varchar(255)
 | 
					    key varchar(255)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										5
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								pom.xml
									
									
									
									
									
								
							@ -1887,6 +1887,11 @@
 | 
				
			|||||||
                <artifactId>org.eclipse.jgit</artifactId>
 | 
					                <artifactId>org.eclipse.jgit</artifactId>
 | 
				
			||||||
                <version>${jgit.version}</version>
 | 
					                <version>${jgit.version}</version>
 | 
				
			||||||
            </dependency>
 | 
					            </dependency>
 | 
				
			||||||
 | 
					            <dependency>
 | 
				
			||||||
 | 
					                <groupId>org.eclipse.jgit</groupId>
 | 
				
			||||||
 | 
					                <artifactId>org.eclipse.jgit.ssh.apache</artifactId>
 | 
				
			||||||
 | 
					                <version>${jgit.version}</version>
 | 
				
			||||||
 | 
					            </dependency>
 | 
				
			||||||
        </dependencies>
 | 
					        </dependencies>
 | 
				
			||||||
    </dependencyManagement>
 | 
					    </dependencyManagement>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user