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)
 | 
			
		||||
    @PreAuthorize("hasAuthority('TENANT_ADMIN')")
 | 
			
		||||
    @PostMapping("/vcSettings")
 | 
			
		||||
    public void saveVersionControlSettings(@RequestBody EntitiesVersionControlSettings settings) throws ThingsboardException {
 | 
			
		||||
    public EntitiesVersionControlSettings saveVersionControlSettings(@RequestBody EntitiesVersionControlSettings settings) throws ThingsboardException {
 | 
			
		||||
        try {
 | 
			
		||||
            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) {
 | 
			
		||||
            throw handleException(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -291,11 +291,21 @@ public class DefaultEntitiesVersionControlService implements EntitiesVersionCont
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    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);
 | 
			
		||||
        AdminSettings adminSettings = new AdminSettings();
 | 
			
		||||
        adminSettings.setTenantId(tenantId);
 | 
			
		||||
        adminSettings.setKey(SETTINGS_KEY);
 | 
			
		||||
        if (adminSettings == null) {
 | 
			
		||||
            adminSettings = new AdminSettings();
 | 
			
		||||
            adminSettings.setKey(SETTINGS_KEY);
 | 
			
		||||
            adminSettings.setTenantId(tenantId);
 | 
			
		||||
        }
 | 
			
		||||
        adminSettings.setJsonValue(JacksonUtil.valueToTree(versionControlSettings));
 | 
			
		||||
        AdminSettings savedAdminSettings = adminSettingsService.saveAdminSettings(tenantId, adminSettings);
 | 
			
		||||
        EntitiesVersionControlSettings savedVersionControlSettings;
 | 
			
		||||
@ -341,8 +351,7 @@ public class DefaultEntitiesVersionControlService implements EntitiesVersionCont
 | 
			
		||||
        } 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())) {
 | 
			
		||||
                if (settings.getPrivateKeyPassword() == null) {
 | 
			
		||||
                    settings.setPrivateKeyPassword(storedSettings.getPrivateKeyPassword());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -19,6 +19,7 @@ import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.data.jpa.repository.JpaRepository;
 | 
			
		||||
import org.springframework.stereotype.Component;
 | 
			
		||||
import org.springframework.transaction.annotation.Transactional;
 | 
			
		||||
import org.thingsboard.server.common.data.AdminSettings;
 | 
			
		||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
			
		||||
import org.thingsboard.server.dao.DaoUtil;
 | 
			
		||||
@ -51,6 +52,7 @@ public class JpaAdminSettingsDao extends JpaAbstractDao<AdminSettingsEntity, Adm
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    @Transactional
 | 
			
		||||
    public boolean removeByTenantIdAndKey(UUID tenantId, String key) {
 | 
			
		||||
        if (adminSettingsRepository.existsByTenantIdAndKey(tenantId, key)) {
 | 
			
		||||
            adminSettingsRepository.deleteByTenantIdAndKey(tenantId, key);
 | 
			
		||||
 | 
			
		||||
@ -20,6 +20,7 @@ import { Observable } from 'rxjs';
 | 
			
		||||
import { HttpClient } from '@angular/common/http';
 | 
			
		||||
import {
 | 
			
		||||
  AdminSettings,
 | 
			
		||||
  EntitiesVersionControlSettings,
 | 
			
		||||
  MailServerSettings,
 | 
			
		||||
  SecuritySettings,
 | 
			
		||||
  TestSmsRequest,
 | 
			
		||||
@ -64,6 +65,25 @@ export class AdminService {
 | 
			
		||||
      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> {
 | 
			
		||||
    return this.http.get<UpdateMessage>(`/api/admin/updates`, defaultHttpOptionsFromConfig(config));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -350,7 +350,7 @@ export class MenuService {
 | 
			
		||||
        name: 'admin.system-settings',
 | 
			
		||||
        type: 'toggle',
 | 
			
		||||
        path: '/settings',
 | 
			
		||||
        height: '80px',
 | 
			
		||||
        height: '120px',
 | 
			
		||||
        icon: 'settings',
 | 
			
		||||
        pages: [
 | 
			
		||||
          {
 | 
			
		||||
@ -366,6 +366,13 @@ export class MenuService {
 | 
			
		||||
            type: 'link',
 | 
			
		||||
            path: '/settings/resources-library',
 | 
			
		||||
            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',
 | 
			
		||||
            icon: 'folder',
 | 
			
		||||
            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 { entityDetailsPageBreadcrumbLabelFunction } from '@home/pages/home-pages.models';
 | 
			
		||||
import { BreadCrumbConfig } from '@shared/components/breadcrumb';
 | 
			
		||||
import { VersionControlSettingsComponent } from '@home/pages/admin/version-control-settings.component';
 | 
			
		||||
 | 
			
		||||
@Injectable()
 | 
			
		||||
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 { HomeSettingsComponent } from '@home/pages/admin/home-settings.component';
 | 
			
		||||
import { ResourcesLibraryComponent } from '@home/pages/admin/resource/resources-library.component';
 | 
			
		||||
import { VersionControlSettingsComponent } from '@home/pages/admin/version-control-settings.component';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
  declarations:
 | 
			
		||||
@ -39,7 +40,8 @@ import { ResourcesLibraryComponent } from '@home/pages/admin/resource/resources-
 | 
			
		||||
      SecuritySettingsComponent,
 | 
			
		||||
      OAuth2SettingsComponent,
 | 
			
		||||
      HomeSettingsComponent,
 | 
			
		||||
      ResourcesLibraryComponent
 | 
			
		||||
      ResourcesLibraryComponent,
 | 
			
		||||
      VersionControlSettingsComponent
 | 
			
		||||
    ],
 | 
			
		||||
  imports: [
 | 
			
		||||
    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',
 | 
			
		||||
    widgetsConfigStatic: helpBaseUrl +  '/docs/user-guide/ui/dashboards#static',
 | 
			
		||||
    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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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,8 +311,28 @@
 | 
			
		||||
            "scheme-music-codes": "10 - Music Codes (ISO-2022-JP)",
 | 
			
		||||
            "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)"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
        },
 | 
			
		||||
        "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",
 | 
			
		||||
        "alarms": "Alarms",
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user