UI: Implement git settings form
This commit is contained in:
parent
4b01aa6f1e
commit
76af741399
@ -207,10 +207,14 @@ public class AdminController extends BaseController {
|
|||||||
notes = "Creates or Updates the version control settings object. " + TENANT_AUTHORITY_PARAGRAPH)
|
notes = "Creates or Updates the version control settings object. " + TENANT_AUTHORITY_PARAGRAPH)
|
||||||
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
|
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
|
||||||
@PostMapping("/vcSettings")
|
@PostMapping("/vcSettings")
|
||||||
public void saveVersionControlSettings(@RequestBody EntitiesVersionControlSettings settings) throws ThingsboardException {
|
public EntitiesVersionControlSettings saveVersionControlSettings(@RequestBody EntitiesVersionControlSettings settings) throws ThingsboardException {
|
||||||
try {
|
try {
|
||||||
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.WRITE);
|
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.WRITE);
|
||||||
versionControlService.saveVersionControlSettings(getTenantId(), settings);
|
EntitiesVersionControlSettings versionControlSettings = checkNotNull(versionControlService.saveVersionControlSettings(getTenantId(), settings));
|
||||||
|
versionControlSettings.setPassword(null);
|
||||||
|
versionControlSettings.setPrivateKey(null);
|
||||||
|
versionControlSettings.setPrivateKeyPassword(null);
|
||||||
|
return versionControlSettings;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw handleException(e);
|
throw handleException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -291,11 +291,21 @@ public class DefaultEntitiesVersionControlService implements EntitiesVersionCont
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntitiesVersionControlSettings saveVersionControlSettings(TenantId tenantId, EntitiesVersionControlSettings versionControlSettings) {
|
public EntitiesVersionControlSettings saveVersionControlSettings(TenantId tenantId, EntitiesVersionControlSettings versionControlSettings) {
|
||||||
EntitiesVersionControlSettings storedSettings = getVersionControlSettings(tenantId);
|
AdminSettings adminSettings = adminSettingsService.findAdminSettingsByKey(tenantId, SETTINGS_KEY);
|
||||||
|
EntitiesVersionControlSettings storedSettings = null;
|
||||||
|
if (adminSettings != null) {
|
||||||
|
try {
|
||||||
|
storedSettings = JacksonUtil.convertValue(adminSettings.getJsonValue(), EntitiesVersionControlSettings.class);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Failed to load version control settings!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
versionControlSettings = this.restoreCredentials(versionControlSettings, storedSettings);
|
versionControlSettings = this.restoreCredentials(versionControlSettings, storedSettings);
|
||||||
AdminSettings adminSettings = new AdminSettings();
|
if (adminSettings == null) {
|
||||||
adminSettings.setTenantId(tenantId);
|
adminSettings = new AdminSettings();
|
||||||
adminSettings.setKey(SETTINGS_KEY);
|
adminSettings.setKey(SETTINGS_KEY);
|
||||||
|
adminSettings.setTenantId(tenantId);
|
||||||
|
}
|
||||||
adminSettings.setJsonValue(JacksonUtil.valueToTree(versionControlSettings));
|
adminSettings.setJsonValue(JacksonUtil.valueToTree(versionControlSettings));
|
||||||
AdminSettings savedAdminSettings = adminSettingsService.saveAdminSettings(tenantId, adminSettings);
|
AdminSettings savedAdminSettings = adminSettingsService.saveAdminSettings(tenantId, adminSettings);
|
||||||
EntitiesVersionControlSettings savedVersionControlSettings;
|
EntitiesVersionControlSettings savedVersionControlSettings;
|
||||||
@ -341,8 +351,7 @@ public class DefaultEntitiesVersionControlService implements EntitiesVersionCont
|
|||||||
} else if (VersionControlAuthMethod.PRIVATE_KEY.equals(authMethod) && settings.getPrivateKey() == null) {
|
} else if (VersionControlAuthMethod.PRIVATE_KEY.equals(authMethod) && settings.getPrivateKey() == null) {
|
||||||
if (storedSettings != null) {
|
if (storedSettings != null) {
|
||||||
settings.setPrivateKey(storedSettings.getPrivateKey());
|
settings.setPrivateKey(storedSettings.getPrivateKey());
|
||||||
if (StringUtils.isEmpty(settings.getPrivateKeyPassword()) &&
|
if (settings.getPrivateKeyPassword() == null) {
|
||||||
StringUtils.isNotEmpty(storedSettings.getPrivateKeyPassword())) {
|
|
||||||
settings.setPrivateKeyPassword(storedSettings.getPrivateKeyPassword());
|
settings.setPrivateKeyPassword(storedSettings.getPrivateKeyPassword());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.thingsboard.server.common.data.AdminSettings;
|
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.DaoUtil;
|
import org.thingsboard.server.dao.DaoUtil;
|
||||||
@ -51,6 +52,7 @@ public class JpaAdminSettingsDao extends JpaAbstractDao<AdminSettingsEntity, Adm
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Transactional
|
||||||
public boolean removeByTenantIdAndKey(UUID tenantId, String key) {
|
public boolean removeByTenantIdAndKey(UUID tenantId, String key) {
|
||||||
if (adminSettingsRepository.existsByTenantIdAndKey(tenantId, key)) {
|
if (adminSettingsRepository.existsByTenantIdAndKey(tenantId, key)) {
|
||||||
adminSettingsRepository.deleteByTenantIdAndKey(tenantId, key);
|
adminSettingsRepository.deleteByTenantIdAndKey(tenantId, key);
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import { Observable } from 'rxjs';
|
|||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import {
|
import {
|
||||||
AdminSettings,
|
AdminSettings,
|
||||||
|
EntitiesVersionControlSettings,
|
||||||
MailServerSettings,
|
MailServerSettings,
|
||||||
SecuritySettings,
|
SecuritySettings,
|
||||||
TestSmsRequest,
|
TestSmsRequest,
|
||||||
@ -64,6 +65,25 @@ export class AdminService {
|
|||||||
defaultHttpOptionsFromConfig(config));
|
defaultHttpOptionsFromConfig(config));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getEntitiesVersionControlSettings(config?: RequestConfig): Observable<EntitiesVersionControlSettings> {
|
||||||
|
return this.http.get<EntitiesVersionControlSettings>(`/api/admin/vcSettings`, defaultHttpOptionsFromConfig(config));
|
||||||
|
}
|
||||||
|
|
||||||
|
public saveEntitiesVersionControlSettings(versionControlSettings: EntitiesVersionControlSettings,
|
||||||
|
config?: RequestConfig): Observable<EntitiesVersionControlSettings> {
|
||||||
|
return this.http.post<EntitiesVersionControlSettings>('/api/admin/vcSettings', versionControlSettings,
|
||||||
|
defaultHttpOptionsFromConfig(config));
|
||||||
|
}
|
||||||
|
|
||||||
|
public deleteEntitiesVersionControlSettings(config?: RequestConfig) {
|
||||||
|
return this.http.delete('/api/admin/vcSettings', defaultHttpOptionsFromConfig(config));
|
||||||
|
}
|
||||||
|
|
||||||
|
public checkVersionControlAccess(versionControlSettings: EntitiesVersionControlSettings,
|
||||||
|
config?: RequestConfig): Observable<void> {
|
||||||
|
return this.http.post<void>('/api/admin/vcSettings/checkAccess', versionControlSettings, defaultHttpOptionsFromConfig(config));
|
||||||
|
}
|
||||||
|
|
||||||
public checkUpdates(config?: RequestConfig): Observable<UpdateMessage> {
|
public checkUpdates(config?: RequestConfig): Observable<UpdateMessage> {
|
||||||
return this.http.get<UpdateMessage>(`/api/admin/updates`, defaultHttpOptionsFromConfig(config));
|
return this.http.get<UpdateMessage>(`/api/admin/updates`, defaultHttpOptionsFromConfig(config));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -350,7 +350,7 @@ export class MenuService {
|
|||||||
name: 'admin.system-settings',
|
name: 'admin.system-settings',
|
||||||
type: 'toggle',
|
type: 'toggle',
|
||||||
path: '/settings',
|
path: '/settings',
|
||||||
height: '80px',
|
height: '120px',
|
||||||
icon: 'settings',
|
icon: 'settings',
|
||||||
pages: [
|
pages: [
|
||||||
{
|
{
|
||||||
@ -366,6 +366,13 @@ export class MenuService {
|
|||||||
type: 'link',
|
type: 'link',
|
||||||
path: '/settings/resources-library',
|
path: '/settings/resources-library',
|
||||||
icon: 'folder'
|
icon: 'folder'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: guid(),
|
||||||
|
name: 'admin.git-settings',
|
||||||
|
type: 'link',
|
||||||
|
path: '/settings/vc',
|
||||||
|
icon: 'manage_history'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -500,6 +507,11 @@ export class MenuService {
|
|||||||
name: 'resource.resources-library',
|
name: 'resource.resources-library',
|
||||||
icon: 'folder',
|
icon: 'folder',
|
||||||
path: '/settings/resources-library'
|
path: '/settings/resources-library'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'admin.git-settings',
|
||||||
|
icon: 'manage_history',
|
||||||
|
path: '/settings/vc',
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,6 +32,7 @@ import { ResourcesLibraryTableConfigResolver } from '@home/pages/admin/resource/
|
|||||||
import { EntityDetailsPageComponent } from '@home/components/entity/entity-details-page.component';
|
import { EntityDetailsPageComponent } from '@home/components/entity/entity-details-page.component';
|
||||||
import { entityDetailsPageBreadcrumbLabelFunction } from '@home/pages/home-pages.models';
|
import { entityDetailsPageBreadcrumbLabelFunction } from '@home/pages/home-pages.models';
|
||||||
import { BreadCrumbConfig } from '@shared/components/breadcrumb';
|
import { BreadCrumbConfig } from '@shared/components/breadcrumb';
|
||||||
|
import { VersionControlSettingsComponent } from '@home/pages/admin/version-control-settings.component';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class OAuth2LoginProcessingUrlResolver implements Resolve<string> {
|
export class OAuth2LoginProcessingUrlResolver implements Resolve<string> {
|
||||||
@ -183,6 +184,19 @@ const routes: Routes = [
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'vc',
|
||||||
|
component: VersionControlSettingsComponent,
|
||||||
|
canDeactivate: [ConfirmOnExitGuard],
|
||||||
|
data: {
|
||||||
|
auth: [Authority.TENANT_ADMIN],
|
||||||
|
title: 'admin.git-settings',
|
||||||
|
breadcrumb: {
|
||||||
|
label: 'admin.git-settings',
|
||||||
|
icon: 'manage_history'
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,6 +28,7 @@ import { SmsProviderComponent } from '@home/pages/admin/sms-provider.component';
|
|||||||
import { SendTestSmsDialogComponent } from '@home/pages/admin/send-test-sms-dialog.component';
|
import { SendTestSmsDialogComponent } from '@home/pages/admin/send-test-sms-dialog.component';
|
||||||
import { HomeSettingsComponent } from '@home/pages/admin/home-settings.component';
|
import { HomeSettingsComponent } from '@home/pages/admin/home-settings.component';
|
||||||
import { ResourcesLibraryComponent } from '@home/pages/admin/resource/resources-library.component';
|
import { ResourcesLibraryComponent } from '@home/pages/admin/resource/resources-library.component';
|
||||||
|
import { VersionControlSettingsComponent } from '@home/pages/admin/version-control-settings.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations:
|
declarations:
|
||||||
@ -39,7 +40,8 @@ import { ResourcesLibraryComponent } from '@home/pages/admin/resource/resources-
|
|||||||
SecuritySettingsComponent,
|
SecuritySettingsComponent,
|
||||||
OAuth2SettingsComponent,
|
OAuth2SettingsComponent,
|
||||||
HomeSettingsComponent,
|
HomeSettingsComponent,
|
||||||
ResourcesLibraryComponent
|
ResourcesLibraryComponent,
|
||||||
|
VersionControlSettingsComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
|
|||||||
@ -0,0 +1,110 @@
|
|||||||
|
<!--
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<div>
|
||||||
|
<mat-card class="settings-card">
|
||||||
|
<mat-card-title>
|
||||||
|
<div fxLayout="row">
|
||||||
|
<span class="mat-headline" translate>admin.git-repository-settings</span>
|
||||||
|
<span fxFlex></span>
|
||||||
|
<div tb-help="versionControlSettings"></div>
|
||||||
|
</div>
|
||||||
|
</mat-card-title>
|
||||||
|
<mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async">
|
||||||
|
</mat-progress-bar>
|
||||||
|
<div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div>
|
||||||
|
<mat-card-content style="padding-top: 16px;">
|
||||||
|
<form [formGroup]="versionControlSettingsForm" #formDirective="ngForm" (ngSubmit)="save()">
|
||||||
|
<fieldset [disabled]="isLoading$ | async">
|
||||||
|
<mat-form-field class="mat-block">
|
||||||
|
<mat-label translate>admin.repository-url</mat-label>
|
||||||
|
<input matInput required formControlName="repositoryUri">
|
||||||
|
<mat-error translate *ngIf="versionControlSettingsForm.get('repositoryUri').hasError('required')">
|
||||||
|
admin.repository-url-required
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field class="mat-block">
|
||||||
|
<mat-label translate>admin.default-branch</mat-label>
|
||||||
|
<input matInput formControlName="defaultBranch">
|
||||||
|
</mat-form-field>
|
||||||
|
<fieldset [disabled]="isLoading$ | async" class="fields-group">
|
||||||
|
<legend class="group-title" translate>admin.authentication-settings</legend>
|
||||||
|
<mat-form-field fxFlex class="mat-block">
|
||||||
|
<mat-label translate>admin.auth-method</mat-label>
|
||||||
|
<mat-select required formControlName="authMethod">
|
||||||
|
<mat-option *ngFor="let method of versionControlAuthMethods" [value]="method">
|
||||||
|
{{versionControlAuthMethodTranslations.get(method) | translate}}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
<section [fxShow]="versionControlSettingsForm.get('authMethod').value === versionControlAuthMethod.USERNAME_PASSWORD" fxLayout="column">
|
||||||
|
<mat-form-field fxFlex class="mat-block">
|
||||||
|
<mat-label translate>common.username</mat-label>
|
||||||
|
<input matInput formControlName="username" placeholder="{{ 'common.enter-username' | translate }}"
|
||||||
|
autocomplete="new-username"/>
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-checkbox *ngIf="showChangePassword" (change)="changePasswordChanged()"
|
||||||
|
[(ngModel)]="changePassword" [ngModelOptions]="{ standalone: true }" style="padding-bottom: 16px;">
|
||||||
|
{{ 'admin.change-password-access-token' | translate }}
|
||||||
|
</mat-checkbox>
|
||||||
|
<mat-form-field class="mat-block" *ngIf="changePassword || !showChangePassword">
|
||||||
|
<mat-label translate>admin.password-access-token</mat-label>
|
||||||
|
<input matInput formControlName="password" type="password"
|
||||||
|
placeholder="{{ 'common.enter-password' | translate }}" autocomplete="new-password"/>
|
||||||
|
<tb-toggle-password matSuffix></tb-toggle-password>
|
||||||
|
</mat-form-field>
|
||||||
|
</section>
|
||||||
|
<section [fxShow]="versionControlSettingsForm.get('authMethod').value === versionControlAuthMethod.PRIVATE_KEY" fxLayout="column">
|
||||||
|
<tb-file-input style="margin-bottom: 16px;"
|
||||||
|
[existingFileName]="versionControlSettingsForm.get('privateKeyFileName').value"
|
||||||
|
required
|
||||||
|
formControlName="privateKey"
|
||||||
|
dropLabel="{{ 'admin.drop-private-key-file-or' | translate }}"
|
||||||
|
[label]="'admin.private-key' | translate"
|
||||||
|
(fileNameChanged)="versionControlSettingsForm.get('privateKeyFileName').patchValue($event)">
|
||||||
|
</tb-file-input>
|
||||||
|
<mat-checkbox *ngIf="showChangePrivateKeyPassword" (change)="changePrivateKeyPasswordChanged()"
|
||||||
|
[(ngModel)]="changePrivateKeyPassword" [ngModelOptions]="{ standalone: true }" style="padding-bottom: 16px;">
|
||||||
|
{{ 'admin.change-passphrase' | translate }}
|
||||||
|
</mat-checkbox>
|
||||||
|
<mat-form-field class="mat-block" *ngIf="changePrivateKeyPassword || !showChangePrivateKeyPassword">
|
||||||
|
<mat-label translate>admin.passphrase</mat-label>
|
||||||
|
<input matInput formControlName="privateKeyPassword" type="password"
|
||||||
|
placeholder="{{ 'admin.enter-passphrase' | translate }}" autocomplete="new-password"/>
|
||||||
|
<tb-toggle-password matSuffix></tb-toggle-password>
|
||||||
|
</mat-form-field>
|
||||||
|
</section>
|
||||||
|
</fieldset>
|
||||||
|
<div fxLayout="row" fxLayoutAlign="end center" fxLayout.xs="column" fxLayoutAlign.xs="end" fxLayoutGap="16px">
|
||||||
|
<button mat-raised-button color="warn" type="button" [fxShow]="settings !== null"
|
||||||
|
[disabled]="(isLoading$ | async)" (click)="delete(formDirective)">
|
||||||
|
{{'action.delete' | translate}}
|
||||||
|
</button>
|
||||||
|
<span fxFlex></span>
|
||||||
|
<button mat-raised-button type="button"
|
||||||
|
[disabled]="(isLoading$ | async) || versionControlSettingsForm.invalid" (click)="checkAccess()">
|
||||||
|
{{'admin.check-access' | translate}}
|
||||||
|
</button>
|
||||||
|
<button mat-raised-button color="primary" [disabled]="(isLoading$ | async) || versionControlSettingsForm.invalid || !versionControlSettingsForm.dirty"
|
||||||
|
type="submit">{{'action.save' | translate}}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
:host {
|
||||||
|
.fields-group {
|
||||||
|
padding: 0 16px 8px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
border: 1px groove rgba(0, 0, 0, .25);
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
legend {
|
||||||
|
color: rgba(0, 0, 0, .7);
|
||||||
|
width: fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
legend + * {
|
||||||
|
display: block;
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,198 @@
|
|||||||
|
///
|
||||||
|
/// 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.
|
||||||
|
///
|
||||||
|
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { PageComponent } from '@shared/components/page.component';
|
||||||
|
import { HasConfirmForm } from '@core/guards/confirm-on-exit.guard';
|
||||||
|
import { FormBuilder, FormGroup, FormGroupDirective, Validators } from '@angular/forms';
|
||||||
|
import { Store } from '@ngrx/store';
|
||||||
|
import { AppState } from '@core/core.state';
|
||||||
|
import { AdminService } from '@core/http/admin.service';
|
||||||
|
import {
|
||||||
|
EntitiesVersionControlSettings,
|
||||||
|
VersionControlAuthMethod,
|
||||||
|
versionControlAuthMethodTranslationMap
|
||||||
|
} from '@shared/models/settings.models';
|
||||||
|
import { ActionNotificationShow } from '@core/notification/notification.actions';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { isNotEmptyStr } from '@core/utils';
|
||||||
|
import { DialogService } from '@core/services/dialog.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'tb-version-control-settings',
|
||||||
|
templateUrl: './version-control-settings.component.html',
|
||||||
|
styleUrls: ['./version-control-settings.component.scss', './settings-card.scss']
|
||||||
|
})
|
||||||
|
export class VersionControlSettingsComponent extends PageComponent implements OnInit, HasConfirmForm {
|
||||||
|
|
||||||
|
versionControlSettingsForm: FormGroup;
|
||||||
|
settings: EntitiesVersionControlSettings = null;
|
||||||
|
|
||||||
|
versionControlAuthMethod = VersionControlAuthMethod;
|
||||||
|
versionControlAuthMethods = Object.values(VersionControlAuthMethod);
|
||||||
|
versionControlAuthMethodTranslations = versionControlAuthMethodTranslationMap;
|
||||||
|
|
||||||
|
showChangePassword = false;
|
||||||
|
changePassword = false;
|
||||||
|
|
||||||
|
showChangePrivateKeyPassword = false;
|
||||||
|
changePrivateKeyPassword = false;
|
||||||
|
|
||||||
|
constructor(protected store: Store<AppState>,
|
||||||
|
private adminService: AdminService,
|
||||||
|
private dialogService: DialogService,
|
||||||
|
private translate: TranslateService,
|
||||||
|
public fb: FormBuilder) {
|
||||||
|
super(store);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.versionControlSettingsForm = this.fb.group({
|
||||||
|
repositoryUri: [null, [Validators.required]],
|
||||||
|
defaultBranch: [null, []],
|
||||||
|
authMethod: [VersionControlAuthMethod.USERNAME_PASSWORD, [Validators.required]],
|
||||||
|
username: [null, []],
|
||||||
|
password: [null, []],
|
||||||
|
privateKeyFileName: [null, [Validators.required]],
|
||||||
|
privateKey: [null, []],
|
||||||
|
privateKeyPassword: [null, []]
|
||||||
|
});
|
||||||
|
this.updateValidators(false);
|
||||||
|
this.versionControlSettingsForm.get('authMethod').valueChanges.subscribe(() => {
|
||||||
|
this.updateValidators(true);
|
||||||
|
});
|
||||||
|
this.versionControlSettingsForm.get('privateKeyFileName').valueChanges.subscribe(() => {
|
||||||
|
this.updateValidators(false);
|
||||||
|
});
|
||||||
|
this.adminService.getEntitiesVersionControlSettings({ignoreErrors: true}).subscribe(
|
||||||
|
(settings) => {
|
||||||
|
this.settings = settings;
|
||||||
|
if (this.settings.authMethod === VersionControlAuthMethod.USERNAME_PASSWORD) {
|
||||||
|
this.showChangePassword = true;
|
||||||
|
} else {
|
||||||
|
this.showChangePrivateKeyPassword = true;
|
||||||
|
}
|
||||||
|
this.versionControlSettingsForm.reset(this.settings);
|
||||||
|
this.updateValidators(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
checkAccess(): void {
|
||||||
|
const settings: EntitiesVersionControlSettings = this.versionControlSettingsForm.value;
|
||||||
|
this.adminService.checkVersionControlAccess(settings).subscribe(() => {
|
||||||
|
this.store.dispatch(new ActionNotificationShow({ message: this.translate.instant('admin.check-vc-access-success'),
|
||||||
|
type: 'success' }));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
save(): void {
|
||||||
|
const settings: EntitiesVersionControlSettings = this.versionControlSettingsForm.value;
|
||||||
|
this.adminService.saveEntitiesVersionControlSettings(settings).subscribe(
|
||||||
|
(savedSettings) => {
|
||||||
|
this.settings = savedSettings;
|
||||||
|
if (this.settings.authMethod === VersionControlAuthMethod.USERNAME_PASSWORD) {
|
||||||
|
this.showChangePassword = true;
|
||||||
|
this.changePassword = false;
|
||||||
|
} else {
|
||||||
|
this.showChangePrivateKeyPassword = true;
|
||||||
|
this.changePrivateKeyPassword = false;
|
||||||
|
}
|
||||||
|
this.versionControlSettingsForm.reset(this.settings);
|
||||||
|
this.updateValidators(false);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(formDirective: FormGroupDirective): void {
|
||||||
|
this.dialogService.confirm(
|
||||||
|
this.translate.instant('admin.delete-git-settings-title', ),
|
||||||
|
this.translate.instant('admin.delete-git-settings-text'), null,
|
||||||
|
this.translate.instant('action.delete')
|
||||||
|
).subscribe((data) => {
|
||||||
|
if (data) {
|
||||||
|
this.adminService.deleteEntitiesVersionControlSettings().subscribe(
|
||||||
|
() => {
|
||||||
|
this.settings = null;
|
||||||
|
this.showChangePassword = false;
|
||||||
|
this.changePassword = false;
|
||||||
|
this.showChangePrivateKeyPassword = false;
|
||||||
|
this.changePrivateKeyPassword = false;
|
||||||
|
formDirective.resetForm();
|
||||||
|
this.versionControlSettingsForm.reset({ authMethod: VersionControlAuthMethod.USERNAME_PASSWORD });
|
||||||
|
this.updateValidators(false);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
confirmForm(): FormGroup {
|
||||||
|
return this.versionControlSettingsForm;
|
||||||
|
}
|
||||||
|
|
||||||
|
changePasswordChanged() {
|
||||||
|
if (this.changePassword) {
|
||||||
|
this.versionControlSettingsForm.get('password').patchValue('');
|
||||||
|
this.versionControlSettingsForm.get('password').markAsDirty();
|
||||||
|
}
|
||||||
|
this.updateValidators(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
changePrivateKeyPasswordChanged() {
|
||||||
|
if (this.changePrivateKeyPassword) {
|
||||||
|
this.versionControlSettingsForm.get('privateKeyPassword').patchValue('');
|
||||||
|
this.versionControlSettingsForm.get('privateKeyPassword').markAsDirty();
|
||||||
|
}
|
||||||
|
this.updateValidators(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateValidators(emitEvent?: boolean): void {
|
||||||
|
const authMethod: VersionControlAuthMethod = this.versionControlSettingsForm.get('authMethod').value;
|
||||||
|
const privateKeyFileName: string = this.versionControlSettingsForm.get('privateKeyFileName').value;
|
||||||
|
if (authMethod === VersionControlAuthMethod.USERNAME_PASSWORD) {
|
||||||
|
this.versionControlSettingsForm.get('username').enable({emitEvent});
|
||||||
|
if (this.changePassword || !this.showChangePassword) {
|
||||||
|
this.versionControlSettingsForm.get('password').enable({emitEvent});
|
||||||
|
} else {
|
||||||
|
this.versionControlSettingsForm.get('password').disable({emitEvent});
|
||||||
|
}
|
||||||
|
this.versionControlSettingsForm.get('privateKeyFileName').disable({emitEvent});
|
||||||
|
this.versionControlSettingsForm.get('privateKey').disable({emitEvent});
|
||||||
|
this.versionControlSettingsForm.get('privateKeyPassword').disable({emitEvent});
|
||||||
|
} else {
|
||||||
|
this.versionControlSettingsForm.get('username').disable({emitEvent});
|
||||||
|
this.versionControlSettingsForm.get('password').disable({emitEvent});
|
||||||
|
this.versionControlSettingsForm.get('privateKeyFileName').enable({emitEvent});
|
||||||
|
this.versionControlSettingsForm.get('privateKey').enable({emitEvent});
|
||||||
|
if (this.changePrivateKeyPassword || !this.showChangePrivateKeyPassword) {
|
||||||
|
this.versionControlSettingsForm.get('privateKeyPassword').enable({emitEvent});
|
||||||
|
} else {
|
||||||
|
this.versionControlSettingsForm.get('privateKeyPassword').disable({emitEvent});
|
||||||
|
}
|
||||||
|
if (isNotEmptyStr(privateKeyFileName)) {
|
||||||
|
this.versionControlSettingsForm.get('privateKey').clearValidators();
|
||||||
|
} else {
|
||||||
|
this.versionControlSettingsForm.get('privateKey').setValidators([Validators.required]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.versionControlSettingsForm.get('username').updateValueAndValidity({emitEvent: false});
|
||||||
|
this.versionControlSettingsForm.get('password').updateValueAndValidity({emitEvent: false});
|
||||||
|
this.versionControlSettingsForm.get('privateKeyFileName').updateValueAndValidity({emitEvent: false});
|
||||||
|
this.versionControlSettingsForm.get('privateKey').updateValueAndValidity({emitEvent: false});
|
||||||
|
this.versionControlSettingsForm.get('privateKeyPassword').updateValueAndValidity({emitEvent: false});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -133,7 +133,8 @@ export const HelpLinks = {
|
|||||||
widgetsConfigAlarm: helpBaseUrl + '/docs/user-guide/ui/dashboards#alarm',
|
widgetsConfigAlarm: helpBaseUrl + '/docs/user-guide/ui/dashboards#alarm',
|
||||||
widgetsConfigStatic: helpBaseUrl + '/docs/user-guide/ui/dashboards#static',
|
widgetsConfigStatic: helpBaseUrl + '/docs/user-guide/ui/dashboards#static',
|
||||||
ruleNodePushToCloud: helpBaseUrl + '/docs/user-guide/rule-engine-2-0/action-nodes/#push-to-cloud',
|
ruleNodePushToCloud: helpBaseUrl + '/docs/user-guide/rule-engine-2-0/action-nodes/#push-to-cloud',
|
||||||
ruleNodePushToEdge: helpBaseUrl + '/docs/user-guide/rule-engine-2-0/action-nodes/#push-to-edge'
|
ruleNodePushToEdge: helpBaseUrl + '/docs/user-guide/rule-engine-2-0/action-nodes/#push-to-edge',
|
||||||
|
versionControlSettings: helpBaseUrl + '/docs/user-guide/ui/version-control-settings'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -396,3 +396,24 @@ export function createSmsProviderConfiguration(type: SmsProviderType): SmsProvid
|
|||||||
}
|
}
|
||||||
return smsProviderConfiguration;
|
return smsProviderConfiguration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum VersionControlAuthMethod {
|
||||||
|
USERNAME_PASSWORD = 'USERNAME_PASSWORD',
|
||||||
|
PRIVATE_KEY = 'PRIVATE_KEY'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const versionControlAuthMethodTranslationMap = new Map<VersionControlAuthMethod, string>([
|
||||||
|
[VersionControlAuthMethod.USERNAME_PASSWORD, 'admin.auth-method-username-password'],
|
||||||
|
[VersionControlAuthMethod.PRIVATE_KEY, 'admin.auth-method-private-key']
|
||||||
|
]);
|
||||||
|
|
||||||
|
export interface EntitiesVersionControlSettings {
|
||||||
|
repositoryUri: string;
|
||||||
|
defaultBranch: string;
|
||||||
|
authMethod: VersionControlAuthMethod;
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
privateKeyFileName: string;
|
||||||
|
privateKey: string;
|
||||||
|
privateKeyPassword: string;
|
||||||
|
}
|
||||||
|
|||||||
@ -311,7 +311,27 @@
|
|||||||
"scheme-music-codes": "10 - Music Codes (ISO-2022-JP)",
|
"scheme-music-codes": "10 - Music Codes (ISO-2022-JP)",
|
||||||
"scheme-extended-kanji-jis": "13 - Extended Kanji JIS (X 0212-1990)",
|
"scheme-extended-kanji-jis": "13 - Extended Kanji JIS (X 0212-1990)",
|
||||||
"scheme-korean-graphic-character-set": "14 - Korean Graphic Character Set (KS C 5601/KS X 1001)"
|
"scheme-korean-graphic-character-set": "14 - Korean Graphic Character Set (KS C 5601/KS X 1001)"
|
||||||
}
|
},
|
||||||
|
"git-settings": "Git settings",
|
||||||
|
"git-repository-settings": "Git repository settings",
|
||||||
|
"repository-url": "Repository URL",
|
||||||
|
"repository-url-required": "Repository URL is required.",
|
||||||
|
"default-branch": "Default branch name",
|
||||||
|
"authentication-settings": "Authentication settings",
|
||||||
|
"auth-method": "Authentication method",
|
||||||
|
"auth-method-username-password": "Password / access token",
|
||||||
|
"auth-method-private-key": "Private key",
|
||||||
|
"password-access-token": "Password / access token",
|
||||||
|
"change-password-access-token": "Change password / access token",
|
||||||
|
"private-key": "Private key",
|
||||||
|
"drop-private-key-file-or": "Drag and drop a private key file or",
|
||||||
|
"passphrase": "Passphrase",
|
||||||
|
"enter-passphrase": "Enter passphrase",
|
||||||
|
"change-passphrase": "Change passphrase",
|
||||||
|
"check-access": "Check access",
|
||||||
|
"check-vc-access-success": "Git repository access successfully verified!",
|
||||||
|
"delete-git-settings-title": "Are you sure you want to delete git settings?",
|
||||||
|
"delete-git-settings-text": "Be careful, after the confirmation the git settings will be removed and git synchronization feature will be unavailable."
|
||||||
},
|
},
|
||||||
"alarm": {
|
"alarm": {
|
||||||
"alarm": "Alarm",
|
"alarm": "Alarm",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user