Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the killswitch and secure options to the manager #617

Merged
merged 3 commits into from
Dec 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,16 @@ export class ButtonComponent implements OnDestroy {
}
}

reset() {
/**
* Puts the button in the normal state.
* @param changeDisabledState If true, the button is enabled.
*/
reset(changeDisabledState = true) {
this.state = ButtonStates.Normal;
this.disabled = false;

if (changeDisabledState) {
this.disabled = false;
}
}

focus() {
Expand All @@ -61,13 +68,27 @@ export class ButtonComponent implements OnDestroy {
this.disabled = true;
}

showLoading() {
/**
* Puts the button in the loading state.
* @param changeDisabledState If true, the button is disabled.
*/
showLoading(changeDisabledState = true) {
this.state = ButtonStates.Loading;
this.disabled = true;

if (changeDisabledState) {
this.disabled = true;
}
}

showError() {
/**
* Puts the button in the error state.
* @param changeDisabledState If true, the button is enabled.
*/
showError(changeDisabledState = true) {
this.state = ButtonStates.Error;
this.disabled = false;

if (changeDisabledState) {
this.disabled = false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
<app-button
#button
(action)="saveChanges()"
[disabled]="!form.valid"
[disabled]="!form.valid || working"
color="primary"
class="float-right"
>
Expand Down Expand Up @@ -226,5 +226,36 @@
</ng-template>
</div>
</mat-tab>
<!-- Settings. -->
<mat-tab [label]="'apps.vpn-socks-client-settings.settings-tab' | translate">
<!-- Killswitch option. -->
<div class="main-theme settings-option">
<mat-checkbox
color="primary"
[checked]="killswitch"
(change)="setKillswitch($event)"
>
{{ 'apps.vpn-socks-client-settings.killswitch-check' | translate }}
<mat-icon [inline]="true" class="help-icon" [matTooltip]="'apps.vpn-socks-client-settings.killswitch-info' | translate">help</mat-icon>
</mat-checkbox>
</div>

<!-- Settings changed alert. -->
<div class="settings-changed-warning" *ngIf="killswitch !== initialKillswitchSetting">
<mat-icon [inline]="true">warning</mat-icon>
{{ 'apps.vpn-socks-client-settings.settings-changed-alert' | translate }}
</div>

<!-- Save button. -->
<app-button
#settingsButton
color="primary"
class="float-right"
[disabled]="killswitch === initialKillswitchSetting || working"
(action)="saveSettings()"
>
{{ 'apps.vpn-socks-client-settings.save-settings' | translate }}
</app-button>
</mat-tab>
</mat-tab-group>
</app-dialog>
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,15 @@ form {
margin-left: 5px;
}
}

.settings-option {
margin: 15px 12px 10px 12px;
}

.settings-changed-warning {
font-size: 0.7rem;
opacity: 0.7;
position: relative;
top: -5px;
padding: 0px 12px;
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export class SkysocksClientSettingsComponent implements OnInit, OnDestroy {
readonly maxElementsPerPage = 10;

@ViewChild('button') button: ButtonComponent;
@ViewChild('settingsButton') settingsButton: ButtonComponent;
@ViewChild('firstInput') firstInput: ElementRef;
form: FormGroup;
// Entries to show on the history.
Expand Down Expand Up @@ -102,8 +103,14 @@ export class SkysocksClientSettingsComponent implements OnInit, OnDestroy {
// True if configuring Vpn-Client, false if configuring Skysocks-Client.
configuringVpn = false;

// Indicates if the killswitch option is selected in the UI or not.
killswitch = false;
// Indicates if the killswitch is active in the backend or not.
initialKillswitchSetting = false;

// If the operation in currently being made.
private working = false;
working = false;

private operationSubscription: Subscription;
private discoverySubscription: Subscription;

Expand Down Expand Up @@ -165,6 +172,10 @@ export class SkysocksClientSettingsComponent implements OnInit, OnDestroy {
if (this.data.args[i] === '-srv' && i + 1 < this.data.args.length) {
currentVal = this.data.args[i + 1];
}
if (this.data.args[i] === '-killswitch' && i + 1 < this.data.args.length) {
this.killswitch = (this.data.args[i + 1] as string).toLowerCase() === 'true';
this.initialKillswitchSetting = this.killswitch;
}
}
}

Expand All @@ -188,6 +199,13 @@ export class SkysocksClientSettingsComponent implements OnInit, OnDestroy {
}
}

// Used by the checkbox for the killswitch setting.
setKillswitch(event) {
if (!this.working) {
this.killswitch = event.checked ? true : false;
}
}

// Opens the modal window for selecting the filters.
changeFilters() {
const countries: string[] = [];
Expand Down Expand Up @@ -472,6 +490,50 @@ export class SkysocksClientSettingsComponent implements OnInit, OnDestroy {
});
}

/**
* Updates the app with the changes made in the settings tab.
*/
saveSettings() {
// The operation can not continue if the component is already working.
if (this.working) {
return;
}

const data = { killswitch: this.killswitch };

this.settingsButton.showLoading(false);
this.button.showLoading(false);
this.working = true;

this.operationSubscription = this.appsService.changeAppSettings(
NodeComponent.getCurrentNodeKey(),
this.data.name,
data,
).subscribe(
() => {
this.initialKillswitchSetting = this.killswitch;

this.snackbarService.showDone('apps.vpn-socks-client-settings.changes-made');

// Allow to continue using the component.
this.working = false;
this.settingsButton.reset(false);
this.button.reset(false);

NodeComponent.refreshCurrentDisplayedData();
},
err => {
// Allow to continue using the component.
this.working = false;
this.settingsButton.showError(false);
this.button.reset(false);
err = processServiceError(err);

this.snackbarService.showError(err);
},
);
}

/**
* Copies a public key.
* @param publicKey Key to copy.
Expand All @@ -487,7 +549,13 @@ export class SkysocksClientSettingsComponent implements OnInit, OnDestroy {

// Makes the call to the hypervisor API for changing the configuration.
private continueSavingChanges(publicKey: string, password: string, enteredManually: boolean, location: string, note: string) {
this.button.showLoading();
// The operation can not continue if the component is already working.
if (this.working) {
return;
}

this.button.showLoading(false);
this.settingsButton.showLoading(false);
this.working = true;

const data = { pk: publicKey };
Expand All @@ -505,12 +573,12 @@ export class SkysocksClientSettingsComponent implements OnInit, OnDestroy {
this.data.name,
data,
).subscribe(
() => this.onSuccess(publicKey, !!password, enteredManually, location, note),
err => this.onError(err),
() => this.onServerDataChangeSuccess(publicKey, !!password, enteredManually, location, note),
err => this.onServerDataChangeError(err),
);
}

private onSuccess(publicKey: string, hasPassword: boolean, enteredManually: boolean, location: string, note: string) {
private onServerDataChangeSuccess(publicKey: string, hasPassword: boolean, enteredManually: boolean, location: string, note: string) {
// Remove any repeated entry from the history.
this.history = this.history.filter(value => value.key !== publicKey);

Expand Down Expand Up @@ -547,12 +615,14 @@ export class SkysocksClientSettingsComponent implements OnInit, OnDestroy {

// Allow to continue using the component.
this.working = false;
this.button.reset();
this.button.reset(false);
this.settingsButton.reset(false);
}

private onError(err: OperationError) {
private onServerDataChangeError(err: OperationError) {
this.working = false;
this.button.showError();
this.button.showError(false);
this.settingsButton.reset(false);
err = processServiceError(err);

this.snackbarService.showError(err);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@
{{ 'apps.vpn-socks-server-settings.passwords-not-match' | translate }}
</mat-error>
</mat-form-field>
<div class="main-theme settings-option">
<mat-checkbox
color="primary"
[checked]="secureMode"
(change)="setSecureMode($event)"
>
{{ 'apps.vpn-socks-server-settings.secure-mode-check' | translate }}
<mat-icon [inline]="true" class="help-icon" [matTooltip]="'apps.vpn-socks-server-settings.secure-mode-info' | translate">help</mat-icon>
</mat-checkbox>
</div>

<app-button
#button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ export class SkysocksSettingsComponent implements OnInit, OnDestroy {
// True if configuring Vpn-Server, false if configuring Skysocks.
configuringVpn = false;

// Indicates if the secure mode option is selected in the UI or not.
secureMode = false;

private operationSubscription: Subscription;
private formSubscription: Subscription;

Expand All @@ -55,6 +58,15 @@ export class SkysocksSettingsComponent implements OnInit, OnDestroy {
if (data.name.toLocaleLowerCase().indexOf('vpn') !== -1) {
this.configuringVpn = true;
}

// Get the current values saved on the visor, if returned by the API.
if (this.data.args && this.data.args.length > 0) {
for (let i = 0; i < this.data.args.length; i++) {
if (this.data.args[i] === '-secure' && i + 1 < this.data.args.length) {
this.secureMode = (this.data.args[i + 1] as string).toLowerCase() === 'true';
}
}
}
}

ngOnInit() {
Expand All @@ -77,6 +89,13 @@ export class SkysocksSettingsComponent implements OnInit, OnDestroy {
}
}

// Used by the checkbox for the secure mode setting.
setSecureMode(event) {
if (!this.button.disabled) {
this.secureMode = event.checked ? true : false;
}
}

/**
* Saves the settings.
*/
Expand Down Expand Up @@ -104,7 +123,7 @@ export class SkysocksSettingsComponent implements OnInit, OnDestroy {
// The node pk is obtained from the currently openned node page.
NodeComponent.getCurrentNodeKey(),
this.data.name,
{ passcode: this.form.get('password').value },
{ passcode: this.form.get('password').value, secure: this.secureMode },
).subscribe({
next: this.onSuccess.bind(this),
error: this.onError.bind(this)
Expand Down
7 changes: 7 additions & 0 deletions static/skywire-manager-src/src/assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,8 @@
"new-password": "New password (Leave empty to remove the password)",
"repeat-password": "Repeat password",
"passwords-not-match": "Passwords do not match.",
"secure-mode-check": "Use secure mode",
"secure-mode-info": "When active, the server doesn't allow client/server SSH and doesn't allow any traffic from VPN clients to the server local network.",
"save": "Save",
"remove-passowrd-confirmation": "You left the password field empty. Are you sure you want to remove the password?",
"change-passowrd-confirmation": "Are you sure you want to change the password?",
Expand All @@ -343,6 +345,7 @@
"discovery-tab": "Search",
"remote-visor-tab": "Enter manually",
"history-tab": "History",
"settings-tab": "Settings",
"use": "Use this data",
"change-note": "Change note",
"remove-entry": "Remove entry",
Expand Down Expand Up @@ -373,6 +376,10 @@
"no-history": "This tab will show the last {{ number }} public keys used.",
"default-note-warning": "The default note has been used.",
"pagination-info": "{{ currentElementsRange }} of {{ totalElements }}",
"killswitch-check": "Activate killswitch",
"killswitch-info": "When active, all network connections will be disabled if the app is running but the VPN protection is interrupted (for temporary errors or any other problem).",
"settings-changed-alert": " The changes have not been saved yet.",
"save-settings": "Save settings",

"change-note-dialog": {
"title": "Change Note",
Expand Down
7 changes: 7 additions & 0 deletions static/skywire-manager-src/src/assets/i18n/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,8 @@
"new-password": "Nueva contraseña (dejar en blanco para eliminar la contraseña)",
"repeat-password": "Repita la contraseña",
"passwords-not-match": "Las contraseñas no coinciden.",
"secure-mode-check": "Usar modo seguro",
"secure-mode-info": "Cuando está activo, el servidor no permite SSH con los clientes y no permite ningún tráfico de clientes VPN a la red local del servidor.",
"save": "Guardar",
"remove-passowrd-confirmation": "Ha dejado el campo de contraseña vacío. ¿Seguro que desea eliminar la contraseña?",
"change-passowrd-confirmation": "¿Seguro que desea cambiar la contraseña?",
Expand All @@ -340,6 +342,7 @@
"vpn-title": "Configuración de VPN-Client",
"discovery-tab": "Buscar",
"remote-visor-tab": "Introducir manualmente",
"settings-tab": "Configuracion",
"history-tab": "Historial",
"use": "Usar estos datos",
"change-note": "Cambiar nota",
Expand Down Expand Up @@ -371,6 +374,10 @@
"no-history": "Esta pestaña mostrará las últimas {{ number }} llaves públicas usadas.",
"default-note-warning": "La nota por defecto ha sido utilizada.",
"pagination-info": "{{ currentElementsRange }} de {{ totalElements }}",
"killswitch-check": "Activar killswitch",
"killswitch-info": "Cuando está activo, todas las conexiones de red se desactivarán si la aplicación se está ejecutando pero la protección VPN está interrumpida (por errores temporales o cualquier otro problema).",
"settings-changed-alert": "Los cambios aún no se han guardado.",
"save-settings": "Guardar configuracion",

"change-note-dialog": {
"title": "Cambiar Nota",
Expand Down
Loading