From a97764941ae5b725f1e89dc0b7421420218bb149 Mon Sep 17 00:00:00 2001 From: Senyoret1 <34079003+Senyoret1@users.noreply.github.com> Date: Tue, 24 Nov 2020 07:57:25 -0400 Subject: [PATCH 1/2] Add the killswitch and secure options to the manager --- .../layout/button/button.component.ts | 33 ++++++-- .../skysocks-client-settings.component.html | 33 +++++++- .../skysocks-client-settings.component.scss | 12 +++ .../skysocks-client-settings.component.ts | 81 +++++++++++++++++-- .../skysocks-settings.component.html | 10 +++ .../skysocks-settings.component.ts | 22 +++++ .../src/assets/i18n/en.json | 7 ++ .../src/assets/i18n/es.json | 7 ++ .../src/assets/i18n/es_base.json | 7 ++ static/skywire-manager-src/src/styles.scss | 8 ++ static/skywire-manager-src/src/theme.scss | 4 + 11 files changed, 209 insertions(+), 15 deletions(-) diff --git a/static/skywire-manager-src/src/app/components/layout/button/button.component.ts b/static/skywire-manager-src/src/app/components/layout/button/button.component.ts index 155421cf16..e2016e91cf 100644 --- a/static/skywire-manager-src/src/app/components/layout/button/button.component.ts +++ b/static/skywire-manager-src/src/app/components/layout/button/button.component.ts @@ -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() { @@ -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; + } } } diff --git a/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skysocks-client-settings/skysocks-client-settings.component.html b/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skysocks-client-settings/skysocks-client-settings.component.html index 43fe6be6b1..5c6676eae1 100644 --- a/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skysocks-client-settings/skysocks-client-settings.component.html +++ b/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skysocks-client-settings/skysocks-client-settings.component.html @@ -41,7 +41,7 @@ @@ -226,5 +226,36 @@ + + + +
+ + {{ 'apps.vpn-socks-client-settings.killswitch-check' | translate }} + help + +
+ + +
+ warning + {{ 'apps.vpn-socks-client-settings.settings-changed-alert' | translate }} +
+ + + + {{ 'apps.vpn-socks-client-settings.save-settings' | translate }} + +
diff --git a/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skysocks-client-settings/skysocks-client-settings.component.scss b/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skysocks-client-settings/skysocks-client-settings.component.scss index 1016e5b5fb..f53cf05c7e 100644 --- a/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skysocks-client-settings/skysocks-client-settings.component.scss +++ b/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skysocks-client-settings/skysocks-client-settings.component.scss @@ -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; +} diff --git a/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skysocks-client-settings/skysocks-client-settings.component.ts b/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skysocks-client-settings/skysocks-client-settings.component.ts index 80cb489526..968145feaf 100644 --- a/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skysocks-client-settings/skysocks-client-settings.component.ts +++ b/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skysocks-client-settings/skysocks-client-settings.component.ts @@ -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. @@ -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; @@ -188,6 +195,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[] = []; @@ -472,6 +486,49 @@ 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; + } + + // Temporal data + const data = { passcode: '' }; + + 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); + }, + 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. @@ -487,7 +544,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 }; @@ -505,12 +568,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); @@ -547,12 +610,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); diff --git a/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skysocks-settings/skysocks-settings.component.html b/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skysocks-settings/skysocks-settings.component.html index 86cabc28b8..32464ba893 100644 --- a/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skysocks-settings/skysocks-settings.component.html +++ b/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skysocks-settings/skysocks-settings.component.html @@ -27,6 +27,16 @@ {{ 'apps.vpn-socks-server-settings.passwords-not-match' | translate }} +
+ + {{ 'apps.vpn-socks-server-settings.secure-mode-check' | translate }} + help + +
0) { + for (let i = 0; i < this.data.args.length; i++) { + // TODO: check the value and use it. + /* + if (this.data.args[i] === '-secure' && i + 1 < this.data.args.length) { + this.secureMode = (this.data.args[i + 1] as string).toLowerCase() === 'true'; + } + */ + } + } } ngOnInit() { @@ -77,6 +92,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. */ diff --git a/static/skywire-manager-src/src/assets/i18n/en.json b/static/skywire-manager-src/src/assets/i18n/en.json index 4d66220300..266c49f892 100644 --- a/static/skywire-manager-src/src/assets/i18n/en.json +++ b/static/skywire-manager-src/src/assets/i18n/en.json @@ -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?", @@ -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", @@ -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", diff --git a/static/skywire-manager-src/src/assets/i18n/es.json b/static/skywire-manager-src/src/assets/i18n/es.json index 4978bf6f3c..968899380e 100644 --- a/static/skywire-manager-src/src/assets/i18n/es.json +++ b/static/skywire-manager-src/src/assets/i18n/es.json @@ -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?", @@ -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", @@ -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", diff --git a/static/skywire-manager-src/src/assets/i18n/es_base.json b/static/skywire-manager-src/src/assets/i18n/es_base.json index c244732a91..8dcfa84eaa 100644 --- a/static/skywire-manager-src/src/assets/i18n/es_base.json +++ b/static/skywire-manager-src/src/assets/i18n/es_base.json @@ -330,6 +330,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?", @@ -341,6 +343,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", @@ -371,6 +374,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", diff --git a/static/skywire-manager-src/src/styles.scss b/static/skywire-manager-src/src/styles.scss index dfeeb76a55..9883bfeefe 100644 --- a/static/skywire-manager-src/src/styles.scss +++ b/static/skywire-manager-src/src/styles.scss @@ -93,3 +93,11 @@ button:focus { height: 11px; } } + +.help-icon { + opacity: 0.4; + font-size: 14px; + cursor: default; + position: relative; + top: 1px; +} diff --git a/static/skywire-manager-src/src/theme.scss b/static/skywire-manager-src/src/theme.scss index ec9733f191..19a1233bb6 100644 --- a/static/skywire-manager-src/src/theme.scss +++ b/static/skywire-manager-src/src/theme.scss @@ -30,6 +30,10 @@ $skywire-theme: mat-light-theme($skywire-primary, $skywire-accent); @include angular-material-theme($skywire-theme); +.main-theme { + @include angular-material-theme($skywire-theme); +} + $mat-white-primary: ( 100: white, 500: white, From 96611fa9296ccbbc0d72355a55b010dd4faac158 Mon Sep 17 00:00:00 2001 From: Senyoret1 <34079003+Senyoret1@users.noreply.github.com> Date: Sun, 29 Nov 2020 16:54:08 -0400 Subject: [PATCH 2/2] Finish adding the killswitch and secure options to the manager --- .../skysocks-client-settings.component.ts | 9 +++++++-- .../skysocks-settings/skysocks-settings.component.ts | 5 +---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skysocks-client-settings/skysocks-client-settings.component.ts b/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skysocks-client-settings/skysocks-client-settings.component.ts index 968145feaf..e13a84c9a9 100644 --- a/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skysocks-client-settings/skysocks-client-settings.component.ts +++ b/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skysocks-client-settings/skysocks-client-settings.component.ts @@ -172,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; + } } } @@ -495,8 +499,7 @@ export class SkysocksClientSettingsComponent implements OnInit, OnDestroy { return; } - // Temporal data - const data = { passcode: '' }; + const data = { killswitch: this.killswitch }; this.settingsButton.showLoading(false); this.button.showLoading(false); @@ -516,6 +519,8 @@ export class SkysocksClientSettingsComponent implements OnInit, OnDestroy { this.working = false; this.settingsButton.reset(false); this.button.reset(false); + + NodeComponent.refreshCurrentDisplayedData(); }, err => { // Allow to continue using the component. diff --git a/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skysocks-settings/skysocks-settings.component.ts b/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skysocks-settings/skysocks-settings.component.ts index bfd127fc1a..8d9257de46 100644 --- a/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skysocks-settings/skysocks-settings.component.ts +++ b/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skysocks-settings/skysocks-settings.component.ts @@ -62,12 +62,9 @@ export class SkysocksSettingsComponent implements OnInit, OnDestroy { // 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++) { - // TODO: check the value and use it. - /* if (this.data.args[i] === '-secure' && i + 1 < this.data.args.length) { this.secureMode = (this.data.args[i + 1] as string).toLowerCase() === 'true'; } - */ } } } @@ -126,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)