Refactor config component (#16064)

Signed-off-by: AllForNothing <sshijun@vmware.com>
This commit is contained in:
孙世军 2021-12-01 10:07:46 +08:00 committed by GitHub
parent 43912674b1
commit 846d690b85
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 416 additions and 494 deletions

View File

@ -443,9 +443,9 @@
</form>
<div>
<button type="button" id="config_auth_save" class="btn btn-primary" (click)="save()"
[disabled]="!isValid() || !hasChanges()">{{'BUTTON.SAVE' | translate}}</button>
[disabled]="!isValid() || !hasChanges() || inProcess()">{{'BUTTON.SAVE' | translate}}</button>
<button type="button" class="btn btn-outline" (click)="cancel()"
[disabled]="!isValid() || !hasChanges()">{{'BUTTON.CANCEL' | translate}}</button>
[disabled]="!isValid() || !hasChanges() || inProcess()">{{'BUTTON.CANCEL' | translate}}</button>
<button type="button" id="ping-test" class="btn btn-outline" (click)="pingTestServer()" *ngIf="showTestingServerBtn"
[disabled]="!isConfigValidForTesting()">{{(showLdap?'BUTTON.TEST_LDAP':'BUTTON.TEST_OIDC') | translate}}</button>
<span id="forTestingLDAP" class="spinner spinner-inline" [hidden]="hideTestingSpinner"></span>

View File

@ -1,17 +1,16 @@
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { MessageHandlerService } from '../../../../shared/services/message-handler.service';
import { ConfirmMessageHandler } from '../config.msg.utils';
import { AppConfigService } from '../../../../services/app-config.service';
import { ConfigurationService } from '../../../../services/config.service';
import { ConfigurationAuthComponent } from './config-auth.component';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { of } from 'rxjs';
import { ErrorHandler } from "../../../../shared/units/error-handler";
import { SystemInfoService } from "../../../../shared/services";
import { clone } from '../../../../shared/units/utils';
import { CONFIG_AUTH_MODE } from '../../../../shared/entities/shared.const';
import { ConfigService } from "../config.service";
import { Configuration } from '../config';
import { SharedTestingModule } from "../../../../shared/shared.module";
describe('ConfigurationAuthComponent', () => {
let component: ConfigurationAuthComponent;
@ -27,7 +26,25 @@ describe('ConfigurationAuthComponent', () => {
let fakeAppConfigService = {
load: () => of(null)
};
let fakeConfirmMessageService = null;
const fakeConfigService = {
config: new Configuration(),
getConfig() {
return this.config;
},
setConfig(c) {
this.config = c;
},
getOriginalConfig() {
return new Configuration();
},
getLoadingConfigStatus() {
return false;
},
updateConfig() {
},
resetConfig() {
}
};
let fakeSystemInfoService = {
getSystemInfo: function () {
return of({
@ -39,17 +56,14 @@ describe('ConfigurationAuthComponent', () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
FormsModule
SharedTestingModule
],
declarations: [ConfigurationAuthComponent],
providers: [
ErrorHandler,
TranslateService,
{ provide: MessageHandlerService, useValue: fakeMessageHandlerService },
{ provide: ConfigurationService, useValue: fakeConfigurationService },
{ provide: AppConfigService, useValue: fakeAppConfigService },
{ provide: ConfirmMessageHandler, useValue: fakeConfirmMessageService },
{ provide: ConfigService, useValue: fakeConfigService },
{ provide: SystemInfoService, useValue: fakeSystemInfoService }
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
@ -59,46 +73,10 @@ describe('ConfigurationAuthComponent', () => {
beforeEach(() => {
fixture = TestBed.createComponent(ConfigurationAuthComponent);
component = fixture.componentInstance;
(component as any).originalConfig = clone(component.currentConfig);
fixture.autoDetectChanges();
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should save configuration', async () => {
const selfRegInput: HTMLInputElement = fixture.nativeElement.querySelector("#selfReg");
selfRegInput.dispatchEvent(new Event('click'));
component.currentConfig.self_registration.value = true;
await fixture.whenStable();
const configAuthSaveBtn: HTMLButtonElement = fixture.nativeElement.querySelector("#config_auth_save");
component.onGoing = true;
configAuthSaveBtn.dispatchEvent(new Event('click'));
await fixture.whenStable();
expect(component.onGoing).toBeFalsy();
});
it('should select ldap or uaa', () => {
component.handleOnChange({target: {value: 'ldap_auth'}});
expect(component.currentConfig.self_registration.value).toEqual(false);
});
it('should ping test server when ldap', async () => {
component.currentConfig.auth_mode.value = CONFIG_AUTH_MODE.LDAP_AUTH;
component.currentConfig.ldap_scope.value = 123456;
await fixture.whenStable();
const pingTestBtn = fixture.nativeElement.querySelector("#ping-test");
expect(pingTestBtn).toBeTruthy();
pingTestBtn.dispatchEvent(new Event('click'));
await fixture.whenStable();
expect(component.testingOnGoing).toBeFalsy();
});
it('should ping test server when oidc', async () => {
component.currentConfig.auth_mode.value = CONFIG_AUTH_MODE.OIDC_AUTH;
await fixture.whenStable();
const pingTestBtn = fixture.nativeElement.querySelector("#ping-test");
expect(pingTestBtn).toBeTruthy();
pingTestBtn.dispatchEvent(new Event('click'));
await fixture.whenStable();
expect(component.testingOnGoing).toBeFalsy();
});
});

View File

@ -11,68 +11,60 @@
// 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, Input, ViewChild, SimpleChanges, OnChanges, OnInit, Output, EventEmitter } from '@angular/core';
import { Component, ViewChild, OnInit } from '@angular/core';
import { NgForm } from '@angular/forms';
import { Subscription } from "rxjs";
import { MessageHandlerService } from '../../../../shared/services/message-handler.service';
import { ConfirmMessageHandler } from '../config.msg.utils';
import { AppConfigService } from '../../../../services/app-config.service';
import { ConfigurationService } from '../../../../services/config.service';
import { ErrorHandler } from "../../../../shared/units/error-handler";
import { SystemInfoService } from "../../../../shared/services";
import { clone, isEmpty, getChanges as getChangesFunc } from "../../../../shared/units/utils";
import { isEmpty, getChanges as getChangesFunc } from "../../../../shared/units/utils";
import { CONFIG_AUTH_MODE } from "../../../../shared/entities/shared.const";
import { errorHandler } from "../../../../shared/units/shared.utils";
import { Configuration } from "../config";
import { finalize } from "rxjs/operators";
const fakePass = 'aWpLOSYkIzJTTU4wMDkx';
import { ConfigService } from "../config.service";
@Component({
selector: 'config-auth',
templateUrl: 'config-auth.component.html',
styleUrls: ['./config-auth.component.scss', '../config.component.scss']
})
export class ConfigurationAuthComponent implements OnChanges, OnInit {
changeSub: Subscription;
export class ConfigurationAuthComponent implements OnInit {
testingOnGoing = false;
onGoing = false;
redirectUrl: string;
// tslint:disable-next-line:no-input-rename
@Input('allConfig') currentConfig: Configuration = new Configuration();
private originalConfig: Configuration;
@ViewChild('authConfigFrom') authForm: NgForm;
@Output() refreshAllconfig = new EventEmitter<any>();
get currentConfig(): Configuration {
return this.conf.getConfig();
}
set currentConfig(c: Configuration) {
this.conf.setConfig(c);
}
constructor(
private msgHandler: MessageHandlerService,
private configService: ConfigurationService,
private appConfigService: AppConfigService,
private confirmMessageHandler: ConfirmMessageHandler,
private conf: ConfigService,
private systemInfo: SystemInfoService,
private errorHandlerEntity: ErrorHandler,
) {
}
ngOnInit() {
this.conf.resetConfig();
this.getSystemInfo();
}
getSystemInfo(): void {
this.systemInfo.getSystemInfo()
.subscribe(systemInfo => (this.redirectUrl = systemInfo.external_url)
, error => this.errorHandlerEntity.error(error));
, error => this.msgHandler.error(error));
}
get checkable() {
return this.currentConfig &&
this.currentConfig.self_registration &&
this.currentConfig.self_registration.value === true;
}
ngOnChanges(changes: SimpleChanges): void {
if (changes && changes["currentConfig"]) {
this.originalConfig = clone(this.currentConfig);
}
}
public get showLdap(): boolean {
return this.currentConfig &&
this.currentConfig.auth_mode &&
@ -99,11 +91,15 @@ export class ConfigurationAuthComponent implements OnChanges, OnInit {
}
}
public isValid(): boolean {
isValid(): boolean {
return this.authForm && this.authForm.valid;
}
public hasChanges(): boolean {
inProcess(): boolean {
return this.onGoing || this.conf.getLoadingConfigStatus();
}
hasChanges(): boolean {
return !isEmpty(this.getChanges());
}
@ -168,7 +164,7 @@ export class ConfigurationAuthComponent implements OnChanges, OnInit {
this.msgHandler.showSuccess('CONFIG.TEST_OIDC_SUCCESS');
}, error => {
this.testingOnGoing = false;
this.errorHandlerEntity.error(error);
this.msgHandler.error(error);
});
}
}
@ -180,12 +176,15 @@ export class ConfigurationAuthComponent implements OnChanges, OnInit {
}
public isConfigValidForTesting(): boolean {
if (!this.authForm || !this.currentConfig) {
return true;
}
return this.isValid() &&
!this.testingOnGoing;
!this.testingOnGoing && !this.inProcess();
}
public getChanges() {
let allChanges = getChangesFunc(this.originalConfig, this.currentConfig);
let allChanges = getChangesFunc(this.conf.getOriginalConfig(), this.currentConfig);
let changes = {};
for (let prop in allChanges) {
if (prop.startsWith('ldap_')
@ -235,7 +234,7 @@ export class ConfigurationAuthComponent implements OnChanges, OnInit {
this.configService.saveConfiguration(changes)
.subscribe(response => {
this.onGoing = false;
this.refreshAllconfig.emit();
this.conf.updateConfig();
// Reload bootstrap option
this.appConfigService.load().subscribe(() => { }
, error => console.error('Failed to reload bootstrap option with error: ', error));
@ -259,7 +258,7 @@ export class ConfigurationAuthComponent implements OnChanges, OnInit {
public cancel(): void {
let changes = this.getChanges();
if (!isEmpty(changes)) {
this.confirmMessageHandler.confirmUnsavedChanges(changes);
this.conf.confirmUnsavedChanges(changes);
} else {
// Invalid situation, should not come here
console.error('Nothing changed');

View File

@ -1,25 +1,23 @@
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<h2 class="custom-h2 config-title">{{'CONFIG.TITLE' | translate }}<span class="spinner spinner-inline ml-1 v-mid" [hidden]="inProgress === false"></span></h2>
<clr-tabs>
<clr-tab>
<button id="config-auth" clrTabLink>{{'CONFIG.AUTH' | translate}}</button>
<clr-tab-content id="authentication" *clrIfActive>
<config-auth [allConfig]="allConfig" (refreshAllconfig)="refreshAllconfig()"></config-auth>
</clr-tab-content>
</clr-tab>
<clr-tab>
<button id="config-email" clrTabLink>{{'CONFIG.EMAIL' | translate }}</button>
<clr-tab-content id="email" *clrIfActive>
<config-email [mailConfig]="allConfig" (refreshAllconfig)="refreshAllconfig()"></config-email>
</clr-tab-content>
</clr-tab>
<clr-tab>
<button id="config-system" clrTabLink>{{'CONFIG.SYSTEM' | translate }}</button>
<clr-tab-content id="system_settings" *clrIfActive>
<system-settings [(systemSettings)]="allConfig" [hasAdminRole]="hasAdminRole" (reloadSystemConfig)="handleAppConfig($event)" (readOnlyChange)="handleReadyOnlyChange($event)" [hasCAFile]="hasCAFile"></system-settings>
</clr-tab-content>
</clr-tab>
</clr-tabs>
<ul class="nav" role="tablist">
<li role="presentation" class="nav-item" >
<button id="config-auth" class="btn btn-link nav-link" type="button"
routerLink="auth"
routerLinkActive="active">{{'CONFIG.AUTH' | translate}}</button>
</li>
<li role="presentation" class="nav-item" >
<button id="config-email" class="btn btn-link nav-link" type="button"
routerLink="email"
routerLinkActive="active">{{'CONFIG.EMAIL' | translate}}</button>
</li>
<li role="presentation" class="nav-item" >
<button id="config-system" class="btn btn-link nav-link" type="button"
routerLink="setting"
routerLinkActive="active">{{'CONFIG.SYSTEM' | translate}}</button>
</li>
</ul>
</div>
</div>
<router-outlet></router-outlet>

View File

@ -1,85 +1,44 @@
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { SessionService } from '../../../shared/services/session.service';
import { MessageHandlerService } from '../../../shared/services/message-handler.service';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { ClarityModule } from "@clr/angular";
import { AppConfigService } from '../../../services/app-config.service';
import { ConfigurationService } from '../../../services/config.service';
import { ConfigurationComponent } from './config.component';
import { of } from 'rxjs';
import { Configuration } from './config';
import { ConfirmationState, ConfirmationTargets } from "../../../shared/entities/shared.const";
import { ConfirmationDialogService } from "../../global-confirmation-dialog/confirmation-dialog.service";
import { ConfirmationAcknowledgement } from "../../global-confirmation-dialog/confirmation-state-message";
import { SharedTestingModule } from "../../../shared/shared.module";
import { ConfigService } from "./config.service";
import { Configuration } from "./config";
describe('ConfigurationComponent', () => {
let component: ConfigurationComponent;
let fixture: ComponentFixture<ConfigurationComponent>;
let confirmationConfirmFlag = true;
let confirmationConfirm = () => {
return confirmationConfirmFlag ? of(new ConfirmationAcknowledgement(ConfirmationState.CONFIRMED, {}, ConfirmationTargets.CONFIG))
: of(new ConfirmationAcknowledgement(ConfirmationState.CONFIRMED
, {change: { email_password: 'Harbor12345' }, tabId: '1'}, ConfirmationTargets.CONFIG_TAB));
};
let fakeConfirmationDialogService = {
confirmationConfirm$: confirmationConfirm()
};
let mockConfigurationService = {
getConfiguration: () => of(new Configuration()),
confirmationConfirm$: of(new ConfirmationAcknowledgement(ConfirmationState.CONFIRMED, {}, ConfirmationTargets.CONFIG))
};
let fakeSessionService = {
getCurrentUser: function () {
return {
has_admin_role: true,
user_id: 1,
username: 'admin',
email: "",
realname: "admin",
role_name: "admin",
role_id: 1,
comment: "string",
};
const fakeConfigService = {
getConfig() {
return new Configuration();
},
updateAccountSettings: () => of(null),
renameAdmin: () => of(null),
getOriginalConfig() {
return new Configuration();
},
getLoadingConfigStatus() {
return false;
},
updateConfig() {
},
initConfig() {
}
};
let initSpy: jasmine.Spy;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
ClarityModule
SharedTestingModule
],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
declarations: [ConfigurationComponent],
providers: [
TranslateService,
{
provide: SessionService, useValue: {
getCurrentUser: function () {
return "admin";
}
}
},
{ provide: ConfirmationDialogService, useValue: fakeConfirmationDialogService },
{ provide: SessionService, useValue: fakeSessionService },
{ provide: MessageHandlerService, useValue: null },
{
provide: AppConfigService, useValue: {
getConfig: function () {
return { has_ca_root: true };
}
}
},
{
provide: ConfigurationService, useValue: mockConfigurationService
}
{ provide: ConfigService, useValue: fakeConfigService },
]
}).compileComponents();
}));
beforeEach(() => {
initSpy = spyOn(fakeConfigService, "initConfig").and.returnValue(undefined);
fixture = TestBed.createComponent(ConfigurationComponent);
component = fixture.componentInstance;
fixture.detectChanges();
@ -88,16 +47,8 @@ describe('ConfigurationComponent', () => {
it('should create', () => {
expect(component).toBeTruthy();
});
it('should reset part of allConfig ', async () => {
confirmationConfirmFlag = false;
component.originalCopy.email_password.value = 'Harbor12345';
component.reset({
email_password: {
value: 'Harbor12345',
editable: true
}
});
it('should init config', async () => {
await fixture.whenStable();
expect(component.allConfig.email_password.value).toEqual('Harbor12345');
expect(initSpy.calls.count()).toEqual(1);
});
});

View File

@ -11,155 +11,25 @@
// 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, OnDestroy, ViewChild } from '@angular/core';
import { Subscription } from "rxjs";
import { SessionService } from '../../../shared/services/session.service';
import { MessageHandlerService } from '../../../shared/services/message-handler.service';
import { AppConfigService } from '../../../services/app-config.service';
import { ConfigurationAuthComponent } from './auth/config-auth.component';
import { ConfigurationEmailComponent } from './email/config-email.component';
import { ConfigurationService } from '../../../services/config.service';
import { Configuration, StringValueItem } from "./config";
import { SystemSettingsComponent } from "./system/system-settings.component";
import { clone, isEmpty } from "../../../shared/units/utils";
import { ConfirmationDialogService } from "../../global-confirmation-dialog/confirmation-dialog.service";
import { ConfirmationState, ConfirmationTargets } from "../../../shared/entities/shared.const";
const fakePass = 'aWpLOSYkIzJTTU4wMDkx';
const TabLinkContentMap = {
'config-auth': 'authentication',
'config-replication': 'replication',
'config-email': 'email',
'config-system': 'system_settings',
'config-label': 'system_label',
};
import { Component, OnInit } from '@angular/core';
import { ConfigService } from "./config.service";
@Component({
selector: 'config',
templateUrl: 'config.component.html',
styleUrls: ['config.component.scss']
})
export class ConfigurationComponent implements OnInit, OnDestroy {
allConfig: Configuration = new Configuration();
onGoing = false;
currentTabId = 'config-auth'; // default tab
originalCopy: Configuration = new Configuration();
confirmSub: Subscription;
@ViewChild(SystemSettingsComponent) systemSettingsConfig: SystemSettingsComponent;
@ViewChild(ConfigurationEmailComponent) mailConfig: ConfigurationEmailComponent;
@ViewChild(ConfigurationAuthComponent) authConfig: ConfigurationAuthComponent;
constructor(
private msgHandler: MessageHandlerService,
private configService: ConfigurationService,
private confirmService: ConfirmationDialogService,
private appConfigService: AppConfigService,
private session: SessionService) { }
public get hasAdminRole(): boolean {
return this.session.getCurrentUser() &&
this.session.getCurrentUser().has_admin_role;
export class ConfigurationComponent implements OnInit {
get inProgress(): boolean {
return this.conf.getLoadingConfigStatus();
}
public get hasCAFile(): boolean {
return this.appConfigService.getConfig().has_ca_root;
constructor(private conf: ConfigService) {
}
public get withAdmiral(): boolean {
return this.appConfigService.getConfig().with_admiral;
}
refreshAllconfig() {
this.retrieveConfig();
}
ngOnInit(): void {
// First load
// Double confirm the current use has admin role
let currentUser = this.session.getCurrentUser();
if (currentUser && currentUser.has_admin_role) {
this.retrieveConfig();
}
this.confirmSub = this.confirmService.confirmationConfirm$.subscribe(confirmation => {
if (confirmation &&
confirmation.state === ConfirmationState.CONFIRMED) {
if (confirmation.source === ConfirmationTargets.CONFIG) {
this.reset(confirmation.data);
} else if (confirmation.source === ConfirmationTargets.CONFIG_TAB) {
this.reset(confirmation.data['changes']);
this.currentTabId = confirmation.data['tabId'];
}
}
});
this.conf.initConfig();
}
ngOnDestroy(): void {
if (this.confirmSub) {
this.confirmSub.unsubscribe();
}
}
public get inProgress(): boolean {
return this.onGoing;
}
handleReadyOnlyChange(event) {
this.msgHandler.handleReadOnly();
if (!event) {
this.msgHandler.clear();
}
}
handleAppConfig(event) {
// Reload bootstrap option
this.appConfigService.load().subscribe(() => {}
, error => console.error('Failed to reload bootstrap option with error: ', error));
}
retrieveConfig(): void {
this.onGoing = true;
this.configService.getConfiguration()
.subscribe((configurations: Configuration) => {
this.onGoing = false;
// Add two password fields
configurations.email_password = new StringValueItem(fakePass, true);
configurations.ldap_search_password = new StringValueItem(fakePass, true);
configurations.uaa_client_secret = new StringValueItem(fakePass, true);
configurations.oidc_client_secret = new StringValueItem(fakePass, true);
this.allConfig = configurations;
// Keep the original copy of the data
this.originalCopy = clone(configurations);
}, error => {
this.onGoing = false;
this.msgHandler.handleError(error);
});
}
/**
*
* Reset the configuration form
*
* @private
* ** deprecated param {*} changes
*
* @memberOf ConfigurationComponent
*/
reset(changes: any): void {
if (!isEmpty(changes)) {
for (let prop in changes) {
if (this.originalCopy[prop]) {
this.allConfig[prop] = clone(this.originalCopy[prop]);
}
}
} else {
// force reset
this.retrieveConfig();
}
}
disabled(prop: any): boolean {
return !(prop && prop.editable);
}
}

View File

@ -15,16 +15,35 @@
import { NgModule } from "@angular/core";
import { SharedModule } from "../../../shared/shared.module";
import { ConfigurationComponent } from "./config.component";
import { ConfirmMessageHandler } from "./config.msg.utils";
import { ConfigurationAuthComponent } from "./auth/config-auth.component";
import { ConfigurationEmailComponent } from "./email/config-email.component";
import { SystemSettingsComponent } from "./system/system-settings.component";
import { RouterModule, Routes } from "@angular/router";
import { ConfigService } from "./config.service";
const routes: Routes = [
{
path: '',
component: ConfigurationComponent
component: ConfigurationComponent,
children: [
{
path: 'auth',
component: ConfigurationAuthComponent
},
{
path: 'email',
component: ConfigurationEmailComponent
},
{
path: 'setting',
component: SystemSettingsComponent
},
{
path: '',
redirectTo: 'auth',
pathMatch: 'full'
}
]
}
];
@NgModule({
@ -39,7 +58,7 @@ const routes: Routes = [
SystemSettingsComponent
],
providers: [
ConfirmMessageHandler,
ConfigService,
]
})
export class ConfigurationModule {

View File

@ -1,22 +0,0 @@
import { Injectable } from '@angular/core';
import { ConfirmationDialogService } from "../../global-confirmation-dialog/confirmation-dialog.service";
import { ConfirmationTargets } from "../../../shared/entities/shared.const";
import { ConfirmationMessage } from "../../global-confirmation-dialog/confirmation-message";
@Injectable()
export class ConfirmMessageHandler {
constructor(private confirmService: ConfirmationDialogService) {
}
public confirmUnsavedChanges(changes: any) {
let msg = new ConfirmationMessage(
'CONFIG.CONFIRM_TITLE',
'CONFIG.CONFIRM_SUMMARY',
'',
changes,
ConfirmationTargets.CONFIG
);
this.confirmService.openComfirmDialog(msg);
}
}

View File

@ -0,0 +1,41 @@
import { TestBed, inject } from '@angular/core/testing';
import { ConfigureService } from 'ng-swagger-gen/services/configure.service';
import { of } from 'rxjs';
import { SharedTestingModule } from "../../../shared/shared.module";
import { Configuration } from './config';
import { ConfigService } from "./config.service";
describe('ConfigService', () => {
const fakedConfigureService = {
getConfigurations() {
return of(null);
}
};
let getConfigSpy: jasmine.Spy;
beforeEach(() => {
getConfigSpy = spyOn(fakedConfigureService, 'getConfigurations').and.returnValue(of(new Configuration()));
TestBed.configureTestingModule({
imports: [
SharedTestingModule
],
providers: [
ConfigService,
{ provide: ConfigureService, useValue: fakedConfigureService },
]
});
});
it('should be created', inject([ConfigService], (service: ConfigService) => {
expect(service).toBeTruthy();
}));
it('should init config', inject([ConfigService], (service: ConfigService) => {
expect(getConfigSpy.calls.count()).toEqual(0);
service.initConfig();
expect(getConfigSpy.calls.count()).toEqual(1);
// only init once
service.initConfig();
expect(getConfigSpy.calls.count()).toEqual(1);
expect(service).toBeTruthy();
}));
});

View File

@ -0,0 +1,102 @@
import { Injectable } from '@angular/core';
import { ConfirmationDialogService } from "../../global-confirmation-dialog/confirmation-dialog.service";
import { ConfirmationState, ConfirmationTargets } from "../../../shared/entities/shared.const";
import { ConfirmationMessage } from "../../global-confirmation-dialog/confirmation-message";
import { Configuration, StringValueItem } from "./config";
import { ConfigureService } from 'ng-swagger-gen/services/configure.service';
import { clone } from "../../../shared/units/utils";
import { MessageHandlerService } from "../../../shared/services/message-handler.service";
import { finalize } from "rxjs/operators";
import { Subscription } from "rxjs";
const fakePass = 'aWpLOSYkIzJTTU4wMDkx';
@Injectable()
export class ConfigService {
private _loadingConfig: boolean = false;
private _hasInit: boolean = false;
private _confirmSub: Subscription;
private _currentConfig: Configuration = new Configuration();
private _originalConfig: Configuration;
constructor(private confirmService: ConfirmationDialogService,
private configureService: ConfigureService,
private msgHandler: MessageHandlerService) {
this._confirmSub = this.confirmService.confirmationConfirm$.subscribe(confirmation => {
if (confirmation &&
confirmation.state === ConfirmationState.CONFIRMED) {
this.resetConfig();
}
});
}
getConfig(): Configuration {
return this._currentConfig;
}
setConfig(c: Configuration) {
this._currentConfig = c;
}
getOriginalConfig(): Configuration {
return this._originalConfig;
}
setOriginalConfig(c: Configuration) {
this._originalConfig = c;
}
getLoadingConfigStatus(): boolean {
return this._loadingConfig;
}
initConfig() {
if (!this._hasInit) {
this.updateConfig();
this._hasInit = true;
}
}
updateConfig() {
this._loadingConfig = true;
this.configureService.getConfigurations()
.pipe(finalize(() => this._loadingConfig = false))
.subscribe(res => {
this._currentConfig = res as Configuration;
// Add password fields
this._currentConfig.email_password = new StringValueItem(fakePass, true);
this._currentConfig.ldap_search_password = new StringValueItem(fakePass, true);
this._currentConfig.uaa_client_secret = new StringValueItem(fakePass, true);
this._currentConfig.oidc_client_secret = new StringValueItem(fakePass, true);
// Keep the original copy of the data
this._originalConfig = clone(this._currentConfig);
// Handle read only
if (this._originalConfig?.read_only?.value) {
this.msgHandler.handleReadOnly();
} else {
this.msgHandler.clear();
}
}, error => {
this.msgHandler.handleError(error);
});
}
resetConfig() {
if (this._originalConfig) {
this._currentConfig = clone(this._originalConfig);
}
}
confirmUnsavedChanges(changes: any) {
let msg = new ConfirmationMessage(
'CONFIG.CONFIRM_TITLE',
'CONFIG.CONFIRM_SUMMARY',
'',
changes,
ConfirmationTargets.CONFIG
);
this.confirmService.openComfirmDialog(msg);
}
}

View File

@ -76,9 +76,9 @@
</form>
<div>
<button type="button" id="config_email_save" class="btn btn-primary" (click)="save()"
[disabled]="!isValid() || !hasChanges()">{{'BUTTON.SAVE'
[disabled]="!isValid() || !hasChanges() || inProgress()">{{'BUTTON.SAVE'
| translate}}</button>
<button type="button" class="btn btn-outline" (click)="cancel()" [disabled]="!isValid() || !hasChanges()">{{'BUTTON.CANCEL'
<button type="button" class="btn btn-outline" (click)="cancel()" [disabled]="!isValid() || !hasChanges() || inProgress()">{{'BUTTON.CANCEL'
| translate}}</button>
<button type="button" id="ping-test" class="btn btn-outline" (click)="testMailServer()" [disabled]="!isMailConfigValid()">{{'BUTTON.TEST_MAIL'
| translate}}</button>

View File

@ -1,13 +1,13 @@
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { MessageHandlerService } from '../../../../shared/services/message-handler.service';
import { ConfirmMessageHandler } from '../config.msg.utils';
import { ConfigurationService } from '../../../../services/config.service';
import { ConfigurationEmailComponent } from './config-email.component';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { clone } from '../../../../shared/units/utils';
import { of } from 'rxjs';
import { ConfigService } from "../config.service";
import { SharedTestingModule } from "../../../../shared/shared.module";
import { Configuration } from "../config";
describe('ConfigurationEmailComponent', () => {
let component: ConfigurationEmailComponent;
@ -19,17 +19,34 @@ describe('ConfigurationEmailComponent', () => {
let fakeMessageHandlerService = {
showSuccess: () => null
};
const fakeConfigService = {
config: new Configuration(),
getConfig() {
return this.config;
},
setConfig(c) {
this.config = c;
},
getOriginalConfig() {
return new Configuration();
},
getLoadingConfigStatus() {
return false;
},
updateConfig() {
},
resetConfig() {
}
};
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
FormsModule
SharedTestingModule
],
declarations: [ConfigurationEmailComponent],
providers: [
{ provide: MessageHandlerService, useValue: fakeMessageHandlerService },
TranslateService,
{ provide: ConfirmMessageHandler, useValue: null },
{ provide: ConfigService, useValue: fakeConfigService },
{ provide: ConfigurationService, useValue: fakeConfigurationService }
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
@ -39,7 +56,6 @@ describe('ConfigurationEmailComponent', () => {
beforeEach(() => {
fixture = TestBed.createComponent(ConfigurationEmailComponent);
component = fixture.componentInstance;
(component as any).originalConfig = clone(component.currentConfig);
fixture.detectChanges();
});

View File

@ -11,33 +11,40 @@
// 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, Input, ViewChild, SimpleChanges, OnChanges, Output, EventEmitter } from '@angular/core';
import { Component, OnInit, ViewChild } from '@angular/core';
import { NgForm } from '@angular/forms';
import { MessageHandlerService } from '../../../../shared/services/message-handler.service';
import { ConfirmMessageHandler } from '../config.msg.utils';
import { ConfigurationService } from '../../../../services/config.service';
import { Configuration } from "../config";
import { isEmpty, getChanges as getChangesFunc, clone } from "../../../../shared/units/utils";
import { isEmpty, getChanges as getChangesFunc } from "../../../../shared/units/utils";
import { errorHandler } from "../../../../shared/units/shared.utils";
import { ConfigService } from "../config.service";
@Component({
selector: 'config-email',
templateUrl: "config-email.component.html",
styleUrls: ['./config-email.component.scss', '../config.component.scss']
})
export class ConfigurationEmailComponent implements OnChanges {
// tslint:disable-next-line:no-input-rename
@Input("mailConfig") currentConfig: Configuration = new Configuration();
@Output() refreshAllconfig = new EventEmitter<any>();
private originalConfig: Configuration;
export class ConfigurationEmailComponent implements OnInit {
testingMailOnGoing = false;
onGoing = false;
@ViewChild("mailConfigFrom", {static: true}) mailForm: NgForm;
get currentConfig(): Configuration {
return this.conf.getConfig();
}
set currentConfig(c: Configuration) {
this.conf.setConfig(c);
}
constructor(
private msgHandler: MessageHandlerService,
private configService: ConfigurationService,
private confirmMessageHandler: ConfirmMessageHandler) {
private conf: ConfigService) {
}
ngOnInit(): void {
this.conf.resetConfig();
}
disabled(prop: any): boolean {
@ -48,16 +55,20 @@ export class ConfigurationEmailComponent implements OnChanges {
this.currentConfig.email_insecure.value = !$event;
}
public isValid(): boolean {
isValid(): boolean {
return this.mailForm && this.mailForm.valid;
}
inProgress(): boolean {
return this.onGoing || this.conf.getLoadingConfigStatus();
}
public hasChanges(): boolean {
return !isEmpty(this.getChanges());
}
public getChanges() {
let allChanges = getChangesFunc(this.originalConfig, this.currentConfig);
let allChanges = getChangesFunc(this.conf.getOriginalConfig(), this.currentConfig);
let changes = {};
for (let prop in allChanges) {
if (prop.startsWith('email_')) {
@ -66,13 +77,6 @@ export class ConfigurationEmailComponent implements OnChanges {
}
return changes;
}
ngOnChanges(changes: SimpleChanges): void {
if (changes && changes["currentConfig"]) {
this.originalConfig = clone(this.currentConfig);
}
}
/**
*
* Test the connection of specified mail server
@ -121,7 +125,7 @@ export class ConfigurationEmailComponent implements OnChanges {
public isMailConfigValid(): boolean {
return this.isValid() &&
!this.testingMailOnGoing;
!this.testingMailOnGoing && !this.inProgress();
}
/**
@ -138,7 +142,7 @@ export class ConfigurationEmailComponent implements OnChanges {
.subscribe(response => {
this.onGoing = false;
// refresh allConfig
this.refreshAllconfig.emit();
this.conf.updateConfig();
this.msgHandler.showSuccess('CONFIG.SAVE_SUCCESS');
}, error => {
this.onGoing = false;
@ -159,7 +163,7 @@ export class ConfigurationEmailComponent implements OnChanges {
public cancel(): void {
let changes = this.getChanges();
if (!isEmpty(changes)) {
this.confirmMessageHandler.confirmUnsavedChanges(changes);
this.conf.confirmUnsavedChanges(changes);
} else {
// Invalid situation, should not come here
console.error('Nothing changed');

View File

@ -1,6 +1,5 @@
<form #systemConfigFrom="ngForm" class="clr-form clr-form-horizontal">
<section>
<label class="subtitle" *ngIf="showSubTitle">{{'CONFIG.SYSTEM' | translate}}</label>
<clr-select-container>
<label for="proCreation">{{'CONFIG.PRO_CREATION_RESTRICTION' | translate}}
<clr-tooltip>
@ -11,8 +10,8 @@
</clr-tooltip>
</label>
<select clrSelect id="proCreation" name="proCreation"
[(ngModel)]="systemSettings.project_creation_restriction.value"
[disabled]="disabled(systemSettings.project_creation_restriction)">
[(ngModel)]="currentConfig.project_creation_restriction.value"
[disabled]="disabled(currentConfig.project_creation_restriction)">
<option value="everyone">{{'CONFIG.PRO_CREATION_EVERYONE' | translate }}</option>
<option value="adminonly">{{'CONFIG.PRO_CREATION_ADMIN' | translate }}</option>
</select>
@ -42,7 +41,7 @@
</clr-tooltip>
</label>
<input clrInput name="robotNamePrefix" type="text"
[(ngModel)]="systemSettings.robot_name_prefix.value"
[(ngModel)]="currentConfig.robot_name_prefix.value"
required
autocomplete="off"
id="robotNamePrefix" size="20" [disabled]="!robotNamePrefixEditable()" />
@ -73,7 +72,7 @@
</clr-tooltip>
<a rel='noopener noreferrer' #certDownloadLink class="cert-down" [href]="downloadLink" target="_blank">{{'CONFIG.ROOT_CERT_LINK' | translate}}</a>
</label>
<clr-checkbox-container *ngIf="!withAdmiral">
<clr-checkbox-container>
<label id="repo_read_only_lbl" for="repoReadOnly">{{'CONFIG.REPO_READ_ONLY' | translate}}
<clr-tooltip>
<clr-icon clrTooltipTrigger shape="info-circle" size="24"></clr-icon>
@ -83,8 +82,8 @@
</clr-tooltip>
</label>
<clr-checkbox-wrapper>
<input type="checkbox" [disabled]="!systemSettings.read_only.editable" clrCheckbox name="repoReadOnly" id="repoReadOnly"
[ngModel]="systemSettings.read_only.value" (ngModelChange)="setRepoReadOnlyValue($event)" />
<input type="checkbox" [disabled]="!currentConfig.read_only.editable" clrCheckbox name="repoReadOnly" id="repoReadOnly"
[ngModel]="currentConfig.read_only.value" (ngModelChange)="setRepoReadOnlyValue($event)" />
</clr-checkbox-wrapper>
</clr-checkbox-container>
@ -162,7 +161,7 @@
</div>
</div>
</div>
<clr-checkbox-container *ngIf="!withAdmiral">
<clr-checkbox-container>
<label for="webhookNotificationEnabled">{{'CONFIG.WEBHOOK_NOTIFICATION_ENABLED' | translate}}
<clr-tooltip>
<clr-icon clrTooltipTrigger shape="info-circle" size="24"></clr-icon>
@ -173,9 +172,9 @@
</label>
<clr-checkbox-wrapper>
<input type="checkbox" clrCheckbox name="webhookNotificationEnabled" id="webhookNotificationEnabled"
[ngModel]="systemSettings.notification_enable.value"
[ngModel]="currentConfig.notification_enable.value"
(ngModelChange)="setWebhookNotificationEnabledValue($event)"
[disabled]="!systemSettings.notification_enable.editable" />
[disabled]="!currentConfig.notification_enable.editable" />
</clr-checkbox-wrapper>
</clr-checkbox-container>
</section>
@ -188,4 +187,3 @@
[disabled]="(!isValid() || !hasChanges()) && (!hasAllowlistChanged) || inProgress">{{'BUTTON.CANCEL'
| translate}}</button>
</div>
<confirmation-dialog #cfgConfirmationDialog (confirmAction)="confirmCancel($event)"></confirmation-dialog>

View File

@ -3,9 +3,10 @@ import { SystemSettingsComponent } from "./system-settings.component";
import { SystemInfoService } from "../../../../shared/services";
import { ErrorHandler } from "../../../../shared/units/error-handler";
import { of } from "rxjs";
import { StringValueItem } from "../config";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { Configuration, StringValueItem } from "../config";
import { SharedTestingModule } from "../../../../shared/shared.module";
import { ConfigService } from "../config.service";
import { AppConfigService } from "../../../../services/app-config.service";
describe('SystemSettingsComponent', () => {
let component: SystemSettingsComponent;
let fixture: ComponentFixture<SystemSettingsComponent>;
@ -33,13 +34,43 @@ describe('SystemSettingsComponent', () => {
return null;
}
};
const fakeConfigService = {
config: new Configuration(),
getConfig() {
return this.config;
},
setConfig(c) {
this.config = c;
},
getOriginalConfig() {
return new Configuration();
},
getLoadingConfigStatus() {
return false;
},
confirmUnsavedChanges() {
},
updateConfig() {
},
resetConfig() {
}
};
const fakedAppConfigService = {
getConfig() {
return {};
},
load() {
return of(null);
}
};
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
SharedTestingModule,
BrowserAnimationsModule
],
providers: [
{ provide: AppConfigService, useValue: fakedAppConfigService },
{ provide: ConfigService, useValue: fakeConfigService },
{ provide: ErrorHandler, useValue: fakedErrorHandler },
{ provide: SystemInfoService, useValue: fakedSystemInfoService },
// open auto detect
@ -53,7 +84,7 @@ describe('SystemSettingsComponent', () => {
beforeEach(() => {
fixture = TestBed.createComponent(SystemSettingsComponent);
component = fixture.componentInstance;
component.config.auth_mode = new StringValueItem("db_auth", false );
component.currentConfig.auth_mode = new StringValueItem("db_auth", false );
fixture.detectChanges();
});
@ -61,6 +92,7 @@ describe('SystemSettingsComponent', () => {
expect(component).toBeTruthy();
});
it('cancel button should works', () => {
const spy: jasmine.Spy = spyOn(fakeConfigService, 'confirmUnsavedChanges').and.returnValue(undefined);
component.systemAllowlist.items.push({cve_id: 'CVE-2019-456'});
const readOnly: HTMLElement = fixture.nativeElement.querySelector('#repoReadOnly');
readOnly.click();
@ -68,7 +100,7 @@ describe('SystemSettingsComponent', () => {
const cancel: HTMLButtonElement = fixture.nativeElement.querySelector('#config_system_cancel');
cancel.click();
fixture.detectChanges();
expect(component.confirmationDlg.opened).toBeTruthy();
expect(spy.calls.count()).toEqual(1);
});
it('save button should works', () => {
component.systemAllowlist.items[0].cve_id = 'CVE-2019-789';

View File

@ -1,28 +1,16 @@
import {
Component,
Input,
OnInit,
Output,
EventEmitter,
ViewChild,
OnChanges,
SimpleChanges,
ElementRef
} from '@angular/core';
import {NgForm} from '@angular/forms';
import {Configuration, StringValueItem} from '../config';
import { clone, isEmpty, getChanges, compareValue, CURRENT_BASE_HREF } from '../../../../shared/units/utils';
import {ErrorHandler} from '../../../../shared/units/error-handler';
import {ConfirmationMessage} from '../../../global-confirmation-dialog/confirmation-message';
import {ConfirmationDialogComponent} from '../../../../shared/components/confirmation-dialog';
import {ConfirmationState, ConfirmationTargets} from '../../../../shared/entities/shared.const';
import {ConfirmationAcknowledgement} from '../../../global-confirmation-dialog/confirmation-state-message';
import { SystemCVEAllowlist, SystemInfo, SystemInfoService,
} from '../../../../shared/services';
import {forkJoin} from "rxjs";
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { NgForm } from '@angular/forms';
import { Configuration } from '../config';
import { clone, compareValue, CURRENT_BASE_HREF, getChanges, isEmpty } from '../../../../shared/units/utils';
import { ErrorHandler } from '../../../../shared/units/error-handler';
import { ConfirmationState, ConfirmationTargets } from '../../../../shared/entities/shared.const';
import { ConfirmationAcknowledgement } from '../../../global-confirmation-dialog/confirmation-state-message';
import { SystemCVEAllowlist, SystemInfo, SystemInfoService, } from '../../../../shared/services';
import { forkJoin } from "rxjs";
import { ConfigurationService } from "../../../../services/config.service";
import { ConfigService } from "../config.service";
import { AppConfigService } from "../../../../services/app-config.service";
const fakePass = 'aWpLOSYkIzJTTU4wMDkx';
const ONE_THOUSAND: number = 1000;
const CVE_DETAIL_PRE_URL = `https://nvd.nist.gov/vuln/detail/`;
const TARGET_BLANK = "_blank";
@ -32,70 +20,58 @@ const TARGET_BLANK = "_blank";
templateUrl: './system-settings.component.html',
styleUrls: ['./system-settings.component.scss']
})
export class SystemSettingsComponent implements OnChanges, OnInit {
config: Configuration = new Configuration();
export class SystemSettingsComponent implements OnInit {
onGoing = false;
private originalConfig: Configuration;
downloadLink: string;
robotTokenExpiration: string;
systemAllowlist: SystemCVEAllowlist;
systemAllowlistOrigin: SystemCVEAllowlist;
cveIds: string;
showAddModal: boolean = false;
systemInfo: SystemInfo;
@Output() configChange: EventEmitter<Configuration> = new EventEmitter<Configuration>();
@Output() readOnlyChange: EventEmitter<boolean> = new EventEmitter<boolean>();
@Output() reloadSystemConfig: EventEmitter<any> = new EventEmitter<any>();
@Input()
get systemSettings(): Configuration {
return this.config;
get currentConfig(): Configuration {
return this.conf.getConfig();
}
set systemSettings(cfg: Configuration) {
this.config = cfg;
this.configChange.emit(this.config);
set currentConfig(cfg: Configuration) {
this.conf.setConfig(cfg);
}
@Input() showSubTitle: boolean = false;
@Input() hasAdminRole: boolean = false;
@Input() hasCAFile: boolean = false;
@Input() withAdmiral = false;
@ViewChild("systemConfigFrom") systemSettingsForm: NgForm;
@ViewChild("cfgConfirmationDialog") confirmationDlg: ConfirmationDialogComponent;
@ViewChild('dateInput') dateInput: ElementRef;
get editable(): boolean {
return this.systemSettings &&
this.systemSettings.token_expiration &&
this.systemSettings.token_expiration.editable;
return this.currentConfig &&
this.currentConfig.token_expiration &&
this.currentConfig.token_expiration.editable;
}
get robotExpirationEditable(): boolean {
return this.systemSettings &&
this.systemSettings.robot_token_duration &&
this.systemSettings.robot_token_duration.editable;
return this.currentConfig &&
this.currentConfig.robot_token_duration &&
this.currentConfig.robot_token_duration.editable;
}
get tokenExpirationValue() {
return this.systemSettings.token_expiration.value;
return this.currentConfig.token_expiration.value;
}
set tokenExpirationValue(v) {
// convert string to number
this.systemSettings.token_expiration.value = +v;
this.currentConfig.token_expiration.value = +v;
}
get robotTokenExpirationValue() {
return this.systemSettings.robot_token_duration.value;
return this.currentConfig.robot_token_duration.value;
}
set robotTokenExpirationValue(v) {
// convert string to number
this.systemSettings.robot_token_duration.value = +v;
this.currentConfig.robot_token_duration.value = +v;
}
robotNamePrefixEditable(): boolean {
return this.systemSettings &&
this.systemSettings.robot_name_prefix &&
this.systemSettings.robot_name_prefix.editable;
return this.currentConfig &&
this.currentConfig.robot_name_prefix &&
this.currentConfig.robot_name_prefix.editable;
}
public isValid(): boolean {
@ -107,19 +83,13 @@ export class SystemSettingsComponent implements OnChanges, OnInit {
}
public getChanges() {
let allChanges = getChanges(this.originalConfig, this.config);
let allChanges = getChanges(this.conf.getOriginalConfig(), this.currentConfig);
if (allChanges) {
return this.getSystemChanges(allChanges);
}
return null;
}
ngOnChanges(changes: SimpleChanges): void {
if (changes && changes["systemSettings"]) {
this.originalConfig = clone(this.config);
}
}
public getSystemChanges(allChanges: any) {
let changes = {};
for (let prop in allChanges) {
@ -132,11 +102,11 @@ export class SystemSettingsComponent implements OnChanges, OnInit {
}
setRepoReadOnlyValue($event: any) {
this.systemSettings.read_only.value = $event;
this.currentConfig.read_only.value = $event;
}
setWebhookNotificationEnabledValue($event: any) {
this.systemSettings.notification_enable.value = $event;
this.currentConfig.notification_enable.value = $event;
}
disabled(prop: any): boolean {
@ -144,7 +114,7 @@ export class SystemSettingsComponent implements OnChanges, OnInit {
}
get canDownloadCert(): boolean {
return this.hasAdminRole && this.hasCAFile;
return this.appConfigService.getConfig().has_ca_root;
}
/**
@ -172,12 +142,11 @@ export class SystemSettingsComponent implements OnChanges, OnInit {
// To refresh the view, we can clone the original data copy
// or force refresh by calling service.
// HERE we choose force way
this.retrieveConfig();
if ('read_only' in changes) {
this.readOnlyChange.emit(changes['read_only']);
}
this.reloadSystemConfig.emit();
this.conf.updateConfig();
// Reload bootstrap option
this.appConfigService.load().subscribe(() => {
}
, error => console.error('Failed to reload bootstrap option with error: ', error));
}
if (!compareValue(this.systemAllowlistOrigin, this.systemAllowlist)) {
this.systemAllowlistOrigin = clone(this.systemAllowlist);
@ -193,40 +162,10 @@ export class SystemSettingsComponent implements OnChanges, OnInit {
}
}
retrieveConfig(): void {
this.onGoing = true;
this.configService.getConfiguration()
.subscribe((configurations: Configuration) => {
this.onGoing = false;
// Add two password fields
configurations.email_password = new StringValueItem(fakePass, true);
this.config = configurations;
// Keep the original copy of the data
this.originalConfig = clone(configurations);
}, error => {
this.onGoing = false;
this.errorHandler.error(error);
});
}
reset(changes: any): void {
if (!isEmpty(changes)) {
for (let prop in changes) {
if (this.originalConfig[prop]) {
this.config[prop] = clone(this.originalConfig[prop]);
}
}
} else {
// force reset
this.retrieveConfig();
}
}
confirmCancel(ack: ConfirmationAcknowledgement): void {
if (ack && ack.source === ConfirmationTargets.CONFIG &&
ack.state === ConfirmationState.CONFIRMED) {
let changes = this.getChanges();
this.reset(changes);
this.conf.resetConfig();
if (!compareValue(this.systemAllowlistOrigin, this.systemAllowlist)) {
this.systemAllowlist = clone(this.systemAllowlistOrigin);
}
@ -235,7 +174,7 @@ export class SystemSettingsComponent implements OnChanges, OnInit {
public get inProgress(): boolean {
return this.onGoing;
return this.onGoing || this.conf.getLoadingConfigStatus();
}
/**
@ -247,28 +186,23 @@ export class SystemSettingsComponent implements OnChanges, OnInit {
public cancel(): void {
let changes = this.getChanges();
if (!isEmpty(changes) || !compareValue(this.systemAllowlistOrigin, this.systemAllowlist)) {
let msg = new ConfirmationMessage(
'CONFIG.CONFIRM_TITLE',
'CONFIG.CONFIRM_SUMMARY',
'',
{},
ConfirmationTargets.CONFIG
);
this.confirmationDlg.open(msg);
this.conf.confirmUnsavedChanges(changes);
} else {
// Invalid situation, should not come here
console.error('Nothing changed');
}
}
constructor(
constructor(private appConfigService: AppConfigService,
private configService: ConfigurationService,
private errorHandler: ErrorHandler,
private systemInfoService: SystemInfoService) {
private systemInfoService: SystemInfoService,
private conf: ConfigService) {
this.downloadLink = CURRENT_BASE_HREF + "/systeminfo/getcert";
}
ngOnInit() {
this.conf.resetConfig();
this.getSystemAllowlist();
this.getSystemInfo();
}
@ -278,6 +212,7 @@ export class SystemSettingsComponent implements OnChanges, OnInit {
.subscribe(systemInfo => this.systemInfo = systemInfo
, error => this.errorHandler.error(error));
}
getSystemAllowlist() {
this.onGoing = true;
this.systemInfoService.getSystemAllowlist()
@ -298,6 +233,7 @@ export class SystemSettingsComponent implements OnChanges, OnInit {
}
);
}
deleteItem(index: number) {
this.systemAllowlist.items.splice(index, 1);
}