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

[WIP] VPN desktop client #603

Merged
merged 31 commits into from
Apr 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
5752ea4
Initial VPN client commit
Senyoret1 Nov 12, 2020
27f71d1
Improvements for the VPN server list
Senyoret1 Nov 13, 2020
55d6590
Design for the main VPN client page
Senyoret1 Nov 15, 2020
5720145
Initial code for connecting the VPN client UI with the backend
Senyoret1 Nov 19, 2020
1af9766
Improvements for the VPN client
Senyoret1 Nov 24, 2020
fe840f8
Add server selection to the VPN client
Senyoret1 Nov 26, 2020
b8a3c13
Centralize the VPN client state management in a service
Senyoret1 Nov 26, 2020
1f29fdd
Improvements for the VPN client service and server selection
Senyoret1 Nov 28, 2020
8cbf30e
More improvements for the VPN client
Senyoret1 Nov 29, 2020
6300f98
Initial code for saving lists in the VPN desktop client
Senyoret1 Dec 1, 2020
b9b2eb2
Improvements for server list management code of the VPN client
Senyoret1 Dec 6, 2020
29028e1
Make the VPN client show all the server lists
Senyoret1 Dec 7, 2020
cbc0b64
Improvements for the server list
Senyoret1 Dec 14, 2020
0b9f7d3
Add the settings page to the desktop VPN client
Senyoret1 Dec 16, 2020
4ff9c32
More status info for the desktop VPN client
Senyoret1 Dec 16, 2020
d73221d
Merge remote-tracking branch 'upstream/develop' into vpn-client
Senyoret1 Dec 16, 2020
bde4849
Improvements for the VPN desktop client
Senyoret1 Dec 21, 2020
a6bdf3d
Improvements for the IP management of the VPN desktop client
Senyoret1 Dec 23, 2020
3fbf7dd
Show data stats in the VPN desktop client
Senyoret1 Dec 24, 2020
0c23ecb
Improvements for the Skywire VPN desktop client
Senyoret1 Dec 25, 2020
7d4c77d
Improve the server options in the VPN desktop client
Senyoret1 Dec 26, 2020
db75831
Improvements for the VPN desktop client
Senyoret1 Dec 27, 2020
8897217
Improvements for the VPN client UI
Senyoret1 Dec 30, 2020
2b6c667
Improvements for the code of the VPN desktop client
Senyoret1 Jan 4, 2021
b5f5d71
General improvements for the VPN desktop client
Senyoret1 Jan 7, 2021
1cff7db
More improvements for the VPN desktop client
Senyoret1 Jan 8, 2021
ed63f60
Improvements for the VPN client
Senyoret1 Jan 15, 2021
3dc4658
Improvements for the VPN client
Senyoret1 Feb 26, 2021
7fb2713
Show correct units in the VPN client
Senyoret1 Mar 21, 2021
2de08af
Merge remote-tracking branch 'upstream/develop' into vpn-client
Senyoret1 Mar 21, 2021
773c98e
Changes requested by the linter
Senyoret1 Mar 24, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
13 changes: 9 additions & 4 deletions static/skywire-manager-src/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Skywire Manager
# Skywire Manager and VPN client

Frontend application that allows to manage a group of Skywire visors through a Hypervisor instance.
It also includes the front-end of the Skywire VPN desktop client.

## Prerequisites

Expand All @@ -26,12 +27,12 @@ The Hypervisor instance must be running in `http://127.0.0.1:8000`. If it is run

If the hypervisor instance is running with TLS active (check the hypervisor configuration file) Run `npm run start` to start a
dev server. If you followed the steps indicated in the [ssl folder](./ssl/README.md), the server will use your custom SSL
certificate. If not, the server will use an automatically created one. Alternatively, If the hypervisor instance is running
certificate. If not, the server will use an automatically created one. Alternatively, if the hypervisor instance is running
without TLS, you can start the dev server by running `npm run start-no-ssl`.

After starting the server with `npm run start`, you can access the app by navigating to `https://localhost:4200` with a web
browser (note that you could get a security warning if the SSL certificate is not in the trusted certificates list). Yo can use
`https://localhost:4200` if you started the dev server with `npm run start-no-ssl`. The app will be automatically reloaded if you
browser (note that you could get a security warning if the SSL certificate is not in the trusted certificates list). You can use
`http://localhost:4200` if you started the dev server with `npm run start-no-ssl`. The app will be automatically reloaded if you
change any of the source files.

## Build
Expand All @@ -41,3 +42,7 @@ Run `make build-ui` in the top directory of this repo to rebuild the UI. The bui
## Translations

You can find information about how to work with translation files in the [Translations README](/static/skywire-manager-src/src/assets/i18n/README.md).

## VPN client

The VPN client forms part of the app. For opening it, just use the `{SkywireManagerUrl}/#/vpn/{VisorPublicKey}` URL.
46 changes: 46 additions & 0 deletions static/skywire-manager-src/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ import { AllRoutesComponent } from './components/pages/node/routing/all-routes/a
import { AllAppsComponent } from './components/pages/node/apps/all-apps/all-apps.component';
import { NodeInfoComponent } from './components/pages/node/node-info/node-info.component';
import { AllLabelsComponent } from './components/pages/settings/all-labels/all-labels.component';
import { VpnServerListComponent } from './components/vpn/pages/vpn-server-list/vpn-server-list.component';
import { VpnStatusComponent } from './components/vpn/pages/vpn-status/vpn-status.component';
import { VpnErrorComponent } from './components/vpn/pages/vpn-error/vpn-error.component';
import { VpnSettingsComponent } from './components/vpn/pages/vpn-settings/vpn-settings.component';
import { VpnAuthGuardService } from './services/vpn-auth-guard.service';

const routes: Routes = [
{
Expand Down Expand Up @@ -124,6 +129,47 @@ const routes: Routes = [
},
],
},
{
path: 'vpn',
canActivate: [VpnAuthGuardService],
canActivateChild: [VpnAuthGuardService],
children: [
{
path: 'unavailable',
component: VpnErrorComponent
},
{
path: ':key',
children: [
{
path: 'status',
component: VpnStatusComponent
},
{
path: 'servers',
redirectTo: 'servers/public/1',
pathMatch: 'full'
},
{
path: 'servers/:type/:page',
component: VpnServerListComponent
},
{
path: 'settings',
component: VpnSettingsComponent
},
{
path: '**',
redirectTo: 'status'
}
]
},
{
path: '**',
redirectTo: '/vpn/unavailable?problem=pk'
}
],
},
{
path: '**',
redirectTo: ''
Expand Down
8 changes: 8 additions & 0 deletions static/skywire-manager-src/src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
<!-- Window size alert for the VPN client. -->
<div class="size-alert d-md-none" *ngIf="inVpnClient">
<div>
<img src="assets/img/size-alert.png">
<div>{{ 'common.window-size-error' | translate }}</div>
</div>
</div>
<div class="flex-1 content container-fluid">
<div [ngClass]="{'background': inVpnClient}"></div>
<router-outlet></router-outlet>
</div>
32 changes: 32 additions & 0 deletions static/skywire-manager-src/src/app/app.component.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
.size-alert {
background-color: rgba(0, 0, 0, 0.85);
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 10000;
display: inline-flex;
align-items: center;
justify-content: center;
text-align: center;
color: white;

> div {
margin: 0px 40px;
max-width: 400px;
}
}

:host {
display: flex;
flex-direction: column;
Expand All @@ -9,3 +29,15 @@
.content {
padding: 20px !important;
}

.background {
background-image: url('/assets/img/map.png');
background-size: cover;
background-position: center;
opacity: 0.1;
width: 100%;
height: 100%;
top: 0;
left: 0;
position: fixed;
}
17 changes: 17 additions & 0 deletions static/skywire-manager-src/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import { LanguageService } from './services/language.service';
styleUrls: ['./app.component.scss']
})
export class AppComponent {
// If the app is showing the VPN client.
inVpnClient = false;

constructor(
// Imported to call its constructor right after opening the app.
storage: StorageService,
Expand Down Expand Up @@ -44,5 +47,19 @@ export class AppComponent {

// Initialize the language configuration.
languageService.loadLanguageSettings();

// Check if the app is showing the VPN client.
router.events.subscribe(() => {
this.inVpnClient = router.url.includes('/vpn/');

// Show the correct document title.
if (router.url.length > 2) {
if (this.inVpnClient) {
document.title = 'Skywire VPN';
} else {
document.title = 'Skywire Manager';
}
}
});
}
}
10 changes: 10 additions & 0 deletions static/skywire-manager-src/src/app/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,14 @@ export const AppConfig = {
smallModalWidth: '480px',
mediumModalWidth: '640px',
largeModalWidth: '900px',

/**
* Vpn desktop client configuration.
*/
vpn: {
/**
* If true, a hardcoded ip will be shown in the UI while in development mode.
*/
hardcodedIpWhileDeveloping: true,
},
};
16 changes: 16 additions & 0 deletions static/skywire-manager-src/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,14 @@ import { AllLabelsComponent } from './components/pages/settings/all-labels/all-l
import { LabelListComponent } from './components/pages/settings/all-labels/label-list/label-list.component';
import { UpdateComponent } from './components/layout/update/update.component';
import { UpdaterConfigComponent } from './components/pages/settings/updater-config/updater-config.component';
import { VpnServerListComponent } from './components/vpn/pages/vpn-server-list/vpn-server-list.component';
import { AddVpnServerComponent } from './components/vpn/pages/vpn-server-list/add-vpn-server/add-vpn-server.component';
import { EditVpnServerValueComponent } from './components/vpn/pages/vpn-server-list/edit-vpn-server-value/edit-vpn-server-value.component';
import { VpnStatusComponent } from './components/vpn/pages/vpn-status/vpn-status.component';
import { VpnSettingsComponent } from './components/vpn/pages/vpn-settings/vpn-settings.component';
import { VpnErrorComponent } from './components/vpn/pages/vpn-error/vpn-error.component';
import { VpnServerNameComponent } from './components/vpn/layout/vpn-server-name/vpn-server-name.component';
import { EnterVpnServerPasswordComponent } from './components/vpn/pages/vpn-server-list/enter-vpn-server-password/enter-vpn-server-password.component';

const globalRippleConfig: RippleGlobalOptions = {
disabled: true,
Expand Down Expand Up @@ -148,6 +156,14 @@ const globalRippleConfig: RippleGlobalOptions = {
EditSkysocksClientNoteComponent,
SkysocksClientFilterComponent,
SkysocksClientPasswordComponent,
VpnServerListComponent,
VpnStatusComponent,
VpnErrorComponent,
AddVpnServerComponent,
VpnSettingsComponent,
EditVpnServerValueComponent,
VpnServerNameComponent,
EnterVpnServerPasswordComponent,
],
imports: [
BrowserModule,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
<div class="wrapper highlight-internal-icon"
[clipboard]="text"
(copyEvent)="onCopyToClipboardClicked()"
[matTooltip]="(!short ? 'copy.tooltip' : 'copy.tooltip-with-text') | translate:{ text: text }"
[matTooltip]="(!short && !shortSimple ? 'copy.tooltip' : 'copy.tooltip-with-text') | translate:{ text: text }"
[matTooltipClass]="{ 'tooltip-word-break': true }"
>
<app-truncated-text [short]="short" [showTooltip]="false" [shortTextLength]="shortTextLength" [text]="text"></app-truncated-text>
&nbsp;<mat-icon [inline]="true">filter_none</mat-icon>
<ng-container *ngIf="!shortSimple">
<app-truncated-text [short]="short" [showTooltip]="false" [shortTextLength]="shortTextLength" [text]="text"></app-truncated-text>
&nbsp;<mat-icon [inline]="true">filter_none</mat-icon>
</ng-container>
<div *ngIf="shortSimple" class="d-flex">
<div class="single-line">{{text}}</div>
&nbsp;<mat-icon [inline]="true">filter_none</mat-icon>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,16 @@ import { SnackbarService } from '../../../services/snackbar.service';
styleUrls: ['./copy-to-clipboard-text.component.scss']
})
export class CopyToClipboardTextComponent {
@Input() text: string;
/**
* Indicates if the text must be truncated if it is too long.
* Indicates if the text must be truncated to show an specific amount of characters only,
* if it is too long.
*/
@Input() public short = false;
@Input() text: string;
/**
* Indicates if the text must be truncated at the end, if it is too long.
*/
@Input() public shortSimple = false;
/**
* Number of characters at the left and right of the text that will be shown if "short" is
* "true". Example: if the text is "Hello word" and this var is set to 2, the component will
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,24 @@
[formControlName]="fieldParams.keyNameInFiltersObject"
[placeholder]="fieldParams.filterName | translate"
>
<mat-option *ngFor="let option of fieldParams.printableLabelsForValues" [value]="option.value">{{ option.label | translate }}</mat-option>
<mat-option *ngFor="let option of fieldParams.printableLabelsForValues" [value]="option.value">
<!-- Option image. -->
<div
*ngIf="fieldParams.printableLabelGeneralSettings && option.image"
class="image-container"
[style]="
'background-image: url(\'' + fieldParams.printableLabelGeneralSettings.defaultImage + '\'); ' +
'width: ' + fieldParams.printableLabelGeneralSettings.imageWidth + 'px; ' +
'height: ' + fieldParams.printableLabelGeneralSettings.imageHeight + 'px;'"
>
<div
class="image"
[style]="'background-image: url(\'' + option.image + '\');'">
</div>
</div>
<!-- Option text. -->
{{ option.label | translate }}
</mat-option>
</mat-select>
</mat-form-field>
</ng-container>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.image-container {
display: inline-block;
background-size: contain;
margin-right: 5px;

.image {
background-size: contain;
width: 100%;
height: 100%;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="chart-container">
<div class="chart-container" [style]="'height: ' + height + 'px;'">
<!-- If the height is changed, also change the height of the container in the scss file. -->
<canvas height="100" #chart></canvas>
<canvas #chart></canvas>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

.chart-container {
position: relative;
height: 100px;
width: 100%;
overflow: hidden;
border-radius: $mat-dialog-radius;
Expand Down
Loading