From 391727f269d29de2fe588c990bb98c8afbd99ceb Mon Sep 17 00:00:00 2001 From: Senyoret1 <34079003+Senyoret1@users.noreply.github.com> Date: Mon, 5 Jun 2023 15:39:23 -0400 Subject: [PATCH 1/4] Limit the Skychay UI to localhost --- cmd/apps/skychat/skychat.go | 2 +- .../pages/node/apps/node-apps-list/node-apps-list.component.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/apps/skychat/skychat.go b/cmd/apps/skychat/skychat.go index b35bfb317b..876225a116 100644 --- a/cmd/apps/skychat/skychat.go +++ b/cmd/apps/skychat/skychat.go @@ -97,7 +97,7 @@ func main() { } setAppStatus(appCl, appserver.AppDetailedStatusRunning) srv := &http.Server{ //nolint gosec - Addr: *addr, + Addr: "127.0.0.1" + (*addr), ReadTimeout: 5 * time.Second, WriteTimeout: 10 * time.Second, } diff --git a/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps-list/node-apps-list.component.ts b/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps-list/node-apps-list.component.ts index d895368c7d..fc8edf4104 100644 --- a/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps-list/node-apps-list.component.ts +++ b/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps-list/node-apps-list.component.ts @@ -264,7 +264,7 @@ export class NodeAppsListComponent implements OnInit, OnDestroy { port = ':' + port; } - return 'http://' + this.nodeIp + port; + return 'http://127.0.0.1' + port; } else if (app.name.toLocaleLowerCase() === 'vpn-client' && this.nodePK) { return location.origin + '/#/vpn/' + this.nodePK + '/status'; } else if (!this.officialAppsList.has(app.name)) { From 34179fecc4662d1155b7778d5ace6fbb3b54a117 Mon Sep 17 00:00:00 2001 From: Senyoret1 <34079003+Senyoret1@users.noreply.github.com> Date: Fri, 9 Jun 2023 16:44:18 -0400 Subject: [PATCH 2/4] Settings for Skychat --- cmd/apps/skychat/skychat.go | 19 ++- pkg/visor/api.go | 42 +++++++ pkg/visor/hypervisor.go | 10 +- pkg/visor/rpc.go | 7 ++ pkg/visor/rpc_client.go | 23 ++++ .../skywire-manager-src/src/app/app.module.ts | 2 + .../node-apps-list.component.ts | 26 ++-- .../skychat-settings.component.html | 42 +++++++ .../skychat-settings.component.scss | 0 .../skychat-settings.component.ts | 119 ++++++++++++++++++ .../src/assets/i18n/en.json | 8 ++ .../src/assets/i18n/es.json | 8 ++ .../src/assets/i18n/es_base.json | 8 ++ 13 files changed, 302 insertions(+), 12 deletions(-) create mode 100644 static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skychat-settings/skychat-settings.component.html create mode 100644 static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skychat-settings/skychat-settings.component.scss create mode 100644 static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skychat-settings/skychat-settings.component.ts diff --git a/cmd/apps/skychat/skychat.go b/cmd/apps/skychat/skychat.go index 876225a116..8ed778a17e 100644 --- a/cmd/apps/skychat/skychat.go +++ b/cmd/apps/skychat/skychat.go @@ -36,7 +36,7 @@ const ( port = routing.Port(1) ) -var addr = flag.String("addr", ":8001", "address to bind") +var addr = flag.String("addr", ":8001", "address to bind, put an * before the port if you want to be able to access outside localhost") var r = netutil.NewRetrier(nil, 50*time.Millisecond, netutil.DefaultMaxBackoff, 5, 2) var ( @@ -84,7 +84,20 @@ func main() { http.HandleFunc("/message", messageHandler(ctx)) http.HandleFunc("/sse", sseHandler) - fmt.Println("Serving HTTP on", *addr) + url := "" + address := *addr + if len(address) < 5 || (address[:1] != ":" && address[:2] != "*:") { + url = "127.0.0.1:8001" + } else if address[:1] == ":" { + url = "127.0.0.1" + address + } else if address[:2] == "*:" { + url = address[1:] + } else { + url = "127.0.0.1:8001" + } + + fmt.Println("Serving HTTP on", url) + if runtime.GOOS != "windows" { termCh := make(chan os.Signal, 1) signal.Notify(termCh, os.Interrupt) @@ -97,7 +110,7 @@ func main() { } setAppStatus(appCl, appserver.AppDetailedStatusRunning) srv := &http.Server{ //nolint gosec - Addr: "127.0.0.1" + (*addr), + Addr: url, ReadTimeout: 5 * time.Second, WriteTimeout: 10 * time.Second, } diff --git a/pkg/visor/api.go b/pkg/visor/api.go index 5a1d88084b..6c483eaa85 100644 --- a/pkg/visor/api.go +++ b/pkg/visor/api.go @@ -12,6 +12,7 @@ import ( "net/http" "os" "path/filepath" + "strconv" "strings" "sync/atomic" "time" @@ -72,6 +73,7 @@ type API interface { SetAppPassword(appName, password string) error SetAppPK(appName string, pk cipher.PubKey) error SetAppSecure(appName string, isSecure bool) error + SetAppAddress(appName string, address string) error SetAppKillswitch(appName string, killswitch bool) error SetAppNetworkInterface(appName string, netifc string) error SetAppDNS(appName string, dnsaddr string) error @@ -769,6 +771,46 @@ func (v *Visor) SetAppSecure(appName string, isSecure bool) error { return nil } +// SetAppAddress implements API. +func (v *Visor) SetAppAddress(appName string, address string) error { + // check app launcher availability + if v.appL == nil { + return ErrAppLauncherNotAvailable + } + + if appName != visorconfig.SkychatName { + return fmt.Errorf("app %s is not allowed to set addr", appName) + } + + if len(address) < 5 || (address[:1] != ":" && address[:2] != "*:") { + return fmt.Errorf("invalid addr value: %s", address) + } + + forLocalhostOnly := address[:1] == ":" + prefix := 2 + if forLocalhostOnly == true { + prefix = 1 + } + + portNumber, err := strconv.Atoi(address[prefix:]) + if err != nil || portNumber < 1025 || portNumber > 65536 { + return fmt.Errorf("invalid port number: %s", strconv.Itoa(portNumber)) + } + + v.log.Infof("Setting %s addr to %v", appName, address) + + const ( + addrArg = "-addr" + ) + if err := v.conf.UpdateAppArg(v.appL, appName, addrArg, address); err != nil { + return err + } + + v.log.Infof("Updated %v addr state", appName) + + return nil +} + // SetAppPK implements API. func (v *Visor) SetAppPK(appName string, pk cipher.PubKey) error { allowedToChangePK := func(appName string) bool { diff --git a/pkg/visor/hypervisor.go b/pkg/visor/hypervisor.go index a797cb87c6..cd45bccff9 100644 --- a/pkg/visor/hypervisor.go +++ b/pkg/visor/hypervisor.go @@ -598,6 +598,7 @@ func (hv *Hypervisor) putApp() http.HandlerFunc { AutoStart *bool `json:"autostart,omitempty"` Killswitch *bool `json:"killswitch,omitempty"` Secure *bool `json:"secure,omitempty"` + Address *string `json:"Address,omitempty"` Status *int `json:"status,omitempty"` Passcode *string `json:"passcode,omitempty"` NetIfc *string `json:"netifc,omitempty"` @@ -608,7 +609,7 @@ func (hv *Hypervisor) putApp() http.HandlerFunc { shouldRestartApp := func(r req) bool { // we restart the app if one of these fields was changed - return r.Killswitch != nil || r.Secure != nil || r.Passcode != nil || + return r.Killswitch != nil || r.Secure != nil || r.Address != nil || r.Passcode != nil || r.PK != nil || r.NetIfc != nil || r.CustomSetting != nil } @@ -660,6 +661,13 @@ func (hv *Hypervisor) putApp() http.HandlerFunc { } } + if reqBody.Address != nil { + if err := ctx.API.SetAppAddress(ctx.App.Name, *reqBody.Address); err != nil { + httputil.WriteJSON(w, r, http.StatusInternalServerError, err) + return + } + } + if reqBody.NetIfc != nil { if err := ctx.API.SetAppNetworkInterface(ctx.App.Name, *reqBody.NetIfc); err != nil { httputil.WriteJSON(w, r, http.StatusInternalServerError, err) diff --git a/pkg/visor/rpc.go b/pkg/visor/rpc.go index 2c008a16ae..e6e601401c 100644 --- a/pkg/visor/rpc.go +++ b/pkg/visor/rpc.go @@ -391,6 +391,13 @@ func (r *RPC) SetAppSecure(in *SetAppBoolIn, _ *struct{}) (err error) { return r.visor.SetAppSecure(in.AppName, in.Val) } +// SetAppPort sets addr flag for the app +func (r *RPC) SetAppAddress(in *SetAppStringIn, _ *struct{}) (err error) { + defer rpcutil.LogCall(r.log, "SetAppAddress", in)(nil, &err) + + return r.visor.SetAppAddress(in.AppName, in.Val) +} + // GetAppStats gets app runtime statistics. func (r *RPC) GetAppStats(appName *string, out *appserver.AppStats) (err error) { defer rpcutil.LogCall(r.log, "GetAppStats", appName)(out, &err) diff --git a/pkg/visor/rpc_client.go b/pkg/visor/rpc_client.go index 86c246c333..af9ea3dbd4 100644 --- a/pkg/visor/rpc_client.go +++ b/pkg/visor/rpc_client.go @@ -267,6 +267,14 @@ func (rc *rpcClient) SetAppSecure(appName string, isSecure bool) error { }, &struct{}{}) } +// SetAppAddress implements API. +func (rc *rpcClient) SetAppAddress(appName string, address string) error { + return rc.Call("SetAppAddress", &SetAppStringIn{ + AppName: appName, + Val: address, + }, &struct{}{}) +} + // SetAppDNS implements API. func (rc *rpcClient) SetAppDNS(appName string, dnsAddr string) error { return rc.Call("SetAppDNS", &SetAppStringIn{ @@ -980,6 +988,21 @@ func (mc *mockRPCClient) SetAppSecure(appName string, isSecure bool) error { //n }) } +// SetAppAddress implements API. +func (mc *mockRPCClient) SetAppAddress(appName string, address string) error { //nolint:all + return mc.do(true, func() error { + const chatName = "skychat" + + for i := range mc.o.Apps { + if mc.o.Apps[i].Name == chatName { + return nil + } + } + + return fmt.Errorf("app of name '%s' does not exist", chatName) + }) +} + // SetAppDNS implements API. func (mc *mockRPCClient) SetAppDNS(string, string) error { return mc.do(true, func() error { diff --git a/static/skywire-manager-src/src/app/app.module.ts b/static/skywire-manager-src/src/app/app.module.ts index 36fc082746..36a55e4109 100644 --- a/static/skywire-manager-src/src/app/app.module.ts +++ b/static/skywire-manager-src/src/app/app.module.ts @@ -101,6 +101,7 @@ import { RewardsAddressComponent } from './components/pages/node/node-info/node- import { BulkRewardAddressChangerComponent } from './components/layout/bulk-reward-address-changer/bulk-reward-address-changer.component'; import { UserAppSettingsComponent } from './components/pages/node/apps/node-apps/user-app-settings/user-app-settings.component'; import { NodeLogsComponent } from './components/pages/node/actions/node-logs/node-logs.component'; +import { SkychatSettingsComponent } from './components/pages/node/apps/node-apps/skychat-settings/skychat-settings.component'; const globalRippleConfig: RippleGlobalOptions = { disabled: true, @@ -178,6 +179,7 @@ const globalRippleConfig: RippleGlobalOptions = { BulkRewardAddressChangerComponent, UserAppSettingsComponent, NodeLogsComponent, + SkychatSettingsComponent, ], imports: [ BrowserModule, diff --git a/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps-list/node-apps-list.component.ts b/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps-list/node-apps-list.component.ts index fc8edf4104..38ae2dbedb 100644 --- a/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps-list/node-apps-list.component.ts +++ b/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps-list/node-apps-list.component.ts @@ -23,6 +23,7 @@ import { FilterProperties, FilterFieldTypes } from 'src/app/utils/filters'; import { SortingColumn, SortingModes, DataSorter } from 'src/app/utils/lists/data-sorter'; import { DataFilterer } from 'src/app/utils/lists/data-filterer'; import { UserAppSettingsComponent } from '../node-apps/user-app-settings/user-app-settings.component'; +import { SkychatSettingsComponent } from '../node-apps/skychat-settings/skychat-settings.component'; /** * Shows the list of applications of a node. It shows official or user apps, not both at the @@ -80,7 +81,7 @@ export class NodeAppsListComponent implements OnInit, OnDestroy { } // List with the names of all the apps which can not be configured directly on the manager. - appsWithoutConfig = new Set(['skychat']); + appsWithoutConfig = new Set(); // All apps the ode has. allApps: Application[]; @@ -248,14 +249,23 @@ export class NodeAppsListComponent implements OnInit, OnDestroy { */ getLink(app: Application): string { if (app.name.toLocaleLowerCase() === 'skychat' && this.nodeIp && app.status !== 0 && app.status !== 2) { - // Default port. + // Default port and ip. let port = '8001'; + let url = '127.0.0.1'; - // Try to get the port from the config array. + // Try to get the address and port from the config array. if (app.args) { for (let i = 0; i < app.args.length; i++) { if (app.args[i] === '-addr' && i + 1 < app.args.length) { - port = (app.args[i + 1] as string).trim(); + const addr = (app.args[i + 1] as string).trim(); + + const parts = addr.split(':'); + // If the app can be accessed outside localhost, use the remote ip. + if (parts[0] === '*') { + url = this.nodeIp; + } + + port = parts[1]; } } } @@ -264,7 +274,7 @@ export class NodeAppsListComponent implements OnInit, OnDestroy { port = ':' + port; } - return 'http://127.0.0.1' + port; + return 'http://' + url + port; } else if (app.name.toLocaleLowerCase() === 'vpn-client' && this.nodePK) { return location.origin + '/#/vpn/' + this.nodePK + '/status'; } else if (!this.officialAppsList.has(app.name)) { @@ -574,12 +584,12 @@ export class NodeAppsListComponent implements OnInit, OnDestroy { * Shows the appropriate modal window for configuring the app. */ config(app: Application): void { - if (app.name === 'skysocks' || app.name === 'vpn-server') { + if (app.name === 'skychat') { + SkychatSettingsComponent.openDialog(this.dialog, app); + } else if (app.name === 'skysocks' || app.name === 'vpn-server') { SkysocksSettingsComponent.openDialog(this.dialog, app); } else if (app.name === 'skysocks-client' || app.name === 'vpn-client') { SkysocksClientSettingsComponent.openDialog(this.dialog, app); - } else if (app.name === 'skychat') { - this.snackbarService.showError('apps.error'); } else { UserAppSettingsComponent.openDialog(this.dialog, app); } diff --git a/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skychat-settings/skychat-settings.component.html b/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skychat-settings/skychat-settings.component.html new file mode 100644 index 0000000000..5d53b0fcfe --- /dev/null +++ b/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skychat-settings/skychat-settings.component.html @@ -0,0 +1,42 @@ + +
+ + +
+ + + {{ 'common.yes' | translate }} + {{ 'common.no' | translate }} + +
+
+ + +
+ + +
+ + {{ 'apps.skychat-settings.port-error' | translate }} + +
+
+ + + {{ 'apps.skychat-settings.save' | translate }} + +
diff --git a/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skychat-settings/skychat-settings.component.scss b/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skychat-settings/skychat-settings.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skychat-settings/skychat-settings.component.ts b/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skychat-settings/skychat-settings.component.ts new file mode 100644 index 0000000000..49805c7841 --- /dev/null +++ b/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skychat-settings/skychat-settings.component.ts @@ -0,0 +1,119 @@ +import { Component, OnInit, ViewChild, OnDestroy, Inject } from '@angular/core'; +import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { MatDialogRef, MatDialog, MatDialogConfig, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { Subscription } from 'rxjs'; + +import { ButtonComponent } from '../../../../../layout/button/button.component'; +import { NodeComponent } from '../../../node.component'; +import { SnackbarService } from '../../../../../../services/snackbar.service'; +import { AppConfig } from 'src/app/app.config'; +import { processServiceError } from 'src/app/utils/errors'; +import { OperationError } from 'src/app/utils/operation-error'; +import { AppsService } from 'src/app/services/apps.service'; +import { Application } from 'src/app/app.datatypes'; + +/** + * Modal window used for configuring the Skychat app. + */ +@Component({ + selector: 'app-skychat-settings', + templateUrl: './skychat-settings.component.html', + styleUrls: ['./skychat-settings.component.scss'] +}) +export class SkychatSettingsComponent implements OnInit, OnDestroy { + @ViewChild('button') button: ButtonComponent; + form: UntypedFormGroup; + + private operationSubscription: Subscription; + + /** + * Opens the modal window. Please use this function instead of opening the window "by hand". + */ + public static openDialog(dialog: MatDialog, app: Application): MatDialogRef { + const config = new MatDialogConfig(); + config.data = app; + config.autoFocus = false; + config.width = AppConfig.mediumModalWidth; + + return dialog.open(SkychatSettingsComponent, config); + } + + constructor( + @Inject(MAT_DIALOG_DATA) private data: Application, + private appsService: AppsService, + private formBuilder: UntypedFormBuilder, + public dialogRef: MatDialogRef, + private snackbarService: SnackbarService, + ) { } + + ngOnInit() { + this.form = this.formBuilder.group({ + localhostOnly: [true], + port: ['', Validators.compose([Validators.required, Validators.min(1025), Validators.max(65536)])], + }); + + // 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] === '-addr' && i + 1 < this.data.args.length) { + const parts = (this.data.args[i + 1] as string).split(':'); + if (parts[0] === '*') { + this.form.get('localhostOnly').setValue(false); + } + + this.form.get('port').setValue(parts[1]); + } + } + } + } + + ngOnDestroy() { + if (this.operationSubscription) { + this.operationSubscription.unsubscribe(); + } + } + + /** + * If true, all the ways provided by default by the UI for closing the modal window are disabled. + */ + get disableDismiss(): boolean { + return this.button ? this.button.isLoading : false; + } + + /** + * Saves the settings. + */ + saveChanges() { + if (!this.form.valid || this.button.disabled) { + return; + } + + this.button.showLoading(); + + const data = {address: this.form.get('localhostOnly').value ? ':' : '*:'}; + data['address'] += this.form.get('port').value; + + this.operationSubscription = this.appsService.changeAppSettings( + // The node pk is obtained from the currently openned node page. + NodeComponent.getCurrentNodeKey(), + this.data.name, + data, + ).subscribe({ + next: this.onSuccess.bind(this), + error: this.onError.bind(this) + }); + } + + private onSuccess() { + NodeComponent.refreshCurrentDisplayedData(); + this.snackbarService.showDone('apps.skychat-settings.changes-made'); + this.dialogRef.close(); + } + + private onError(err: OperationError) { + this.button.showError(); + err = processServiceError(err); + + this.snackbarService.showError(err); + } +} diff --git a/static/skywire-manager-src/src/assets/i18n/en.json b/static/skywire-manager-src/src/assets/i18n/en.json index 79aa6c8329..9f71be51a6 100644 --- a/static/skywire-manager-src/src/assets/i18n/en.json +++ b/static/skywire-manager-src/src/assets/i18n/en.json @@ -457,6 +457,14 @@ "empty-confirmation": "The settings list is empty. Do you really want to continue?", "changes-made": "The changes have been made." }, + "skychat-settings": { + "title": "Skychat Settings", + "localhost-only": "Allow access from the local machine only", + "port": "Port", + "save": "Save", + "changes-made": "The changes have been made.", + "port-error": "Must be a valid number between 1025 and 65536." + }, "vpn-socks-server-settings": { "socks-title": "Skysocks Settings", "vpn-title": "VPN-Server Settings", diff --git a/static/skywire-manager-src/src/assets/i18n/es.json b/static/skywire-manager-src/src/assets/i18n/es.json index 27dd44541f..ad795e30e1 100644 --- a/static/skywire-manager-src/src/assets/i18n/es.json +++ b/static/skywire-manager-src/src/assets/i18n/es.json @@ -461,6 +461,14 @@ "empty-confirmation": "La lista de configuración está vacía. ¿Realmente desea continuar?", "changes-made": "Los cambios han sido realizados." }, + "skychat-settings": { + "title": "Configuración de Skychat", + "localhost-only": "Permitir acceso sólo desde la máquina local", + "port": "Puerto", + "save": "Guardar", + "changes-made": "Los cambios han sido realizados.", + "port-error": "Debe ser un número válido entre 1025 y 65536." + }, "vpn-socks-server-settings": { "socks-title": "Configuración de Skysocks", "vpn-title": "Configuración de VPN-Server", 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 8c853eda94..505872da82 100644 --- a/static/skywire-manager-src/src/assets/i18n/es_base.json +++ b/static/skywire-manager-src/src/assets/i18n/es_base.json @@ -461,6 +461,14 @@ "empty-confirmation": "The settings list is empty. Do you really want to continue?", "changes-made": "The changes have been made." }, + "skychat-settings": { + "title": "Skychat Settings", + "localhost-only": "Allow access from the local machine only", + "port": "Port", + "save": "Save", + "changes-made": "The changes have been made.", + "port-error": "Must be a valid number between 1025 and 65536." + }, "vpn-socks-server-settings": { "socks-title": "Skysocks Settings", "vpn-title": "VPN-Server Settings", From 37e20d9236386b031c6e1a245cc894388a2affea Mon Sep 17 00:00:00 2001 From: Senyoret1 <34079003+Senyoret1@users.noreply.github.com> Date: Fri, 9 Jun 2023 16:50:24 -0400 Subject: [PATCH 3/4] Small lint fixes --- pkg/visor/api.go | 2 +- pkg/visor/rpc.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/visor/api.go b/pkg/visor/api.go index 6c483eaa85..88d0cceef1 100644 --- a/pkg/visor/api.go +++ b/pkg/visor/api.go @@ -788,7 +788,7 @@ func (v *Visor) SetAppAddress(appName string, address string) error { forLocalhostOnly := address[:1] == ":" prefix := 2 - if forLocalhostOnly == true { + if forLocalhostOnly { prefix = 1 } diff --git a/pkg/visor/rpc.go b/pkg/visor/rpc.go index e6e601401c..699a44cfec 100644 --- a/pkg/visor/rpc.go +++ b/pkg/visor/rpc.go @@ -391,7 +391,7 @@ func (r *RPC) SetAppSecure(in *SetAppBoolIn, _ *struct{}) (err error) { return r.visor.SetAppSecure(in.AppName, in.Val) } -// SetAppPort sets addr flag for the app +// SetAppAddress sets addr flag for the app func (r *RPC) SetAppAddress(in *SetAppStringIn, _ *struct{}) (err error) { defer rpcutil.LogCall(r.log, "SetAppAddress", in)(nil, &err) From 458c156d729adbd89333d36cdc8c58d6b070b9e2 Mon Sep 17 00:00:00 2001 From: Senyoret1 <34079003+Senyoret1@users.noreply.github.com> Date: Mon, 12 Jun 2023 13:06:57 -0400 Subject: [PATCH 4/4] As confirmation for Skychat access --- .../skychat-settings.component.ts | 21 +++++++++++++++++++ .../src/assets/i18n/en.json | 3 ++- .../src/assets/i18n/es.json | 3 ++- .../src/assets/i18n/es_base.json | 3 ++- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skychat-settings/skychat-settings.component.ts b/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skychat-settings/skychat-settings.component.ts index 49805c7841..a2bb039249 100644 --- a/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skychat-settings/skychat-settings.component.ts +++ b/static/skywire-manager-src/src/app/components/pages/node/apps/node-apps/skychat-settings/skychat-settings.component.ts @@ -11,6 +11,7 @@ import { processServiceError } from 'src/app/utils/errors'; import { OperationError } from 'src/app/utils/operation-error'; import { AppsService } from 'src/app/services/apps.service'; import { Application } from 'src/app/app.datatypes'; +import GeneralUtils from 'src/app/utils/generalUtils'; /** * Modal window used for configuring the Skychat app. @@ -24,6 +25,7 @@ export class SkychatSettingsComponent implements OnInit, OnDestroy { @ViewChild('button') button: ButtonComponent; form: UntypedFormGroup; + private formSubscription: Subscription; private operationSubscription: Subscription; /** @@ -44,6 +46,7 @@ export class SkychatSettingsComponent implements OnInit, OnDestroy { private formBuilder: UntypedFormBuilder, public dialogRef: MatDialogRef, private snackbarService: SnackbarService, + private dialog: MatDialog, ) { } ngOnInit() { @@ -52,6 +55,20 @@ export class SkychatSettingsComponent implements OnInit, OnDestroy { port: ['', Validators.compose([Validators.required, Validators.min(1025), Validators.max(65536)])], }); + this.formSubscription = this.form.get('localhostOnly').valueChanges.subscribe(value => { + // If "no" is selected ask for confirmation. + if (!value) { + this.form.get('localhostOnly').setValue(true); + const confirmationDialog = GeneralUtils.createConfirmationDialog(this.dialog, 'apps.skychat-settings.non-localhost-confirmation'); + + confirmationDialog.componentInstance.operationAccepted.subscribe(() => { + confirmationDialog.componentInstance.closeModal(); + + this.form.get('localhostOnly').setValue(false, { emitEvent: false }); + }); + } + }); + // 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++) { @@ -68,6 +85,10 @@ export class SkychatSettingsComponent implements OnInit, OnDestroy { } ngOnDestroy() { + if (this.formSubscription) { + this.formSubscription.unsubscribe(); + } + if (this.operationSubscription) { this.operationSubscription.unsubscribe(); } diff --git a/static/skywire-manager-src/src/assets/i18n/en.json b/static/skywire-manager-src/src/assets/i18n/en.json index 9f71be51a6..b01a27b8e3 100644 --- a/static/skywire-manager-src/src/assets/i18n/en.json +++ b/static/skywire-manager-src/src/assets/i18n/en.json @@ -463,7 +463,8 @@ "port": "Port", "save": "Save", "changes-made": "The changes have been made.", - "port-error": "Must be a valid number between 1025 and 65536." + "port-error": "Must be a valid number between 1025 and 65536.", + "non-localhost-confirmation": "This will allow to use the app from anywhere on the internet. Are you sure you vant to continue?" }, "vpn-socks-server-settings": { "socks-title": "Skysocks Settings", diff --git a/static/skywire-manager-src/src/assets/i18n/es.json b/static/skywire-manager-src/src/assets/i18n/es.json index ad795e30e1..f369ed1fee 100644 --- a/static/skywire-manager-src/src/assets/i18n/es.json +++ b/static/skywire-manager-src/src/assets/i18n/es.json @@ -467,7 +467,8 @@ "port": "Puerto", "save": "Guardar", "changes-made": "Los cambios han sido realizados.", - "port-error": "Debe ser un número válido entre 1025 y 65536." + "port-error": "Debe ser un número válido entre 1025 y 65536.", + "non-localhost-confirmation": "Esto permitirá usar la aplicación desde cualquier lugar en Internet. ¿Seguro que desea continuar?" }, "vpn-socks-server-settings": { "socks-title": "Configuración de Skysocks", 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 505872da82..7965323a28 100644 --- a/static/skywire-manager-src/src/assets/i18n/es_base.json +++ b/static/skywire-manager-src/src/assets/i18n/es_base.json @@ -467,7 +467,8 @@ "port": "Port", "save": "Save", "changes-made": "The changes have been made.", - "port-error": "Must be a valid number between 1025 and 65536." + "port-error": "Must be a valid number between 1025 and 65536.", + "non-localhost-confirmation": "This will allow to use the app from anywhere on the internet. Are you sure you vant to continue?" }, "vpn-socks-server-settings": { "socks-title": "Skysocks Settings",