Skip to content

Commit

Permalink
rework ca-wiz and add icons to menu for warnings
Browse files Browse the repository at this point in the history
  • Loading branch information
MattDHill committed Oct 31, 2023
1 parent 9e554bd commit 36f4fb6
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 156 deletions.
8 changes: 7 additions & 1 deletion frontend/projects/ui/src/app/app/menu/menu.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,17 @@
<ion-label class="label montserrat" routerLinkActive="label_selected">
{{ page.title }}
</ion-label>
<ion-icon
*ngIf="page.url === '/system' && (warning$ | async)"
color="warning"
size="small"
name="warning"
></ion-icon>
<ion-icon
*ngIf="page.url === '/system' && (showEOSUpdate$ | async)"
color="success"
size="small"
name="rocket-outline"
name="rocket"
></ion-icon>
<ion-badge
*ngIf="page.url === '/updates' && (updateCount$ | async) as updateCount"
Expand Down
9 changes: 9 additions & 0 deletions frontend/projects/ui/src/app/app/menu/menu.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ import {
filter,
first,
map,
merge,
Observable,
of,
pairwise,
startWith,
switchMap,
Expand All @@ -22,6 +24,7 @@ import { DataModel } from 'src/app/services/patch-db/data-model'
import { SplitPaneTracker } from 'src/app/services/split-pane.service'
import { Emver, THEME } from '@start9labs/shared'
import { ConnectionService } from 'src/app/services/connection.service'
import { ConfigService } from 'src/app/services/config.service'

@Component({
selector: 'app-menu',
Expand Down Expand Up @@ -111,6 +114,11 @@ export class MenuComponent {

readonly theme$ = inject(THEME)

readonly warning$ = merge(
of(this.config.isTorHttp()),
this.patch.watch$('server-info', 'ntp-synced').pipe(map(synced => !synced)),
)

constructor(
private readonly patch: PatchDB<DataModel>,
private readonly eosService: EOSService,
Expand All @@ -119,5 +127,6 @@ export class MenuComponent {
private readonly splitPane: SplitPaneTracker,
private readonly emver: Emver,
private readonly connectionService: ConnectionService,
private readonly config: ConfigService,
) {}
}
Original file line number Diff line number Diff line change
@@ -1,106 +1,78 @@
<ion-grid class="grid-wiz">
<img width="60px" height="60px" src="/assets/img/icon.png" alt="StartOS" />
<ion-row>
<ion-col class="ion-text-center">
<ion-icon name="lock-closed-outline" class="wiz-icon"></ion-icon>
</ion-col>
</ion-row>
<ion-row>
<ion-col class="ion-text-center">
<h2><b>Trust your Root Certificate Authority (CA)</b></h2>
<p>
Download and trust your server's Root CA to establish secure, encrypted
(
<b>HTTPS</b>
) connections with your server
</p>
</ion-col>
</ion-row>
<ion-row>
<ion-col sizeXs="12" sizeLg="4">
<div class="wiz-card">
<ion-row class="ion-justify-content-between">
<b class="wiz-step">1</b>
<tui-tooltip
content="Your server uses its Root CA to generate SSL/TLS certificates for itself and its installed services. These certificates are used to encrypt network traffic with your client devices."
direction="right"
></tui-tooltip>
</ion-row>
<div class="ion-text-center">
<h2>Download Root CA</h2>
<p>Download your server's Root CA</p>
</div>
<ion-button class="wiz-card-button" shape="round" (click)="download()">
<ion-icon slot="start" name="download-outline"></ion-icon>
<ion-content>
<ng-container *ngIf="!caTrusted; else trusted">
<ion-icon name="lock-closed-outline" class="wiz-icon"></ion-icon>
<h1 class="title">Trust Your Root CA</h1>
<p class="subtitle">
Download and trust your server's Root Certificate Authority to establish a
secure (
<b>HTTPS</b>
) connection. You will need to repeat this on every device you use to
connect to your server.
</p>
<ol>
<li>
<b>Download your server's Root CA</b>
. Your server uses its Root CA to generate SSL/TLS certificates for
itself and installed services. These certificates are then used to
encrypt network traffic with your client devices.
<br />
<ion-button strong size="small" (click)="download()">
Download
<ion-icon slot="end" name="download-outline"></ion-icon>
</ion-button>
</div>
</ion-col>
<ion-col sizeXs="12" sizeLg="4">
<div class="wiz-card" [class.disabled]="!downloadClicked">
<ion-row class="ion-justify-content-between">
<b class="wiz-step">2</b>
<tui-tooltip
content="By trusting your server's Root CA, your device can verify the authenticity of its encrypted communications with your server and installed services. You will need to trust the Root CA on every device used to connect to your server."
direction="right"
></tui-tooltip>
</ion-row>
<div class="ion-text-center">
<h2>Trust Root CA</h2>
<p>Follow instructions for your OS</p>
</div>
<ion-button
class="wiz-card-button"
shape="round"
(click)="instructions()"
[disabled]="!downloadClicked"
>
View Docs
</li>
<li>
<b>Trust your server's Root CA</b>
. Follow instructions for your OS. By trusting your server's Root CA,
your device can verify the authenticity of encrypted communications with
your server.
<br />
<ion-button strong size="small" (click)="instructions()">
View Instructions
<ion-icon slot="end" name="open-outline"></ion-icon>
</ion-button>
</div>
</ion-col>
<ion-col sizeXs="12" sizeLg="4">
<div class="wiz-card" [class.disabled]="!polling && !caTrusted">
<b class="wiz-step">3</b>
<div class="ion-text-center">
<h2>Go To Login</h2>
<p *ngIf="instructionsClicked; else space" class="inline-center">
<ion-spinner
class="wiz-spinner"
*ngIf="!caTrusted; else trusted"
></ion-spinner>
<ng-template #trusted>
<ion-icon name="ribbon-outline" color="success"></ion-icon>
</ng-template>
&nbsp;{{ caTrusted ? 'Root CA trusted!' : 'Waiting for trust...' }}
</p>
<ng-template #space>
<!-- to keep alignment -->
<p><br /></p>
</ng-template>
</div>
<ion-button
class="wiz-card-button"
shape="round"
(click)="launchHttps()"
[disabled]="!caTrusted"
>
Open
<ion-icon slot="end" name="open-outline"></ion-icon>
</li>
<li>
<b>Test</b>
. If refreshing the page does not work, you may need to quit the browser
and re-open.
<i>Tip: before quitting, bookmark this page or copy the URL.</i>
<br />
<ion-button strong size="small" (click)="refresh()">
Refresh
<ion-icon slot="end" name="refresh"></ion-icon>
</ion-button>
</div>
</ion-col>
</ion-row>
<ion-row>
<ion-col class="ion-text-center">
<ion-button fill="clear" (click)="launchHttps()" [disabled]="caTrusted">
Skip
<ion-icon slot="end" name="open-outline"></ion-icon>
</ion-button>
</ion-col>
</ion-row>
</ion-grid>
</li>
</ol>
<ion-button
style="--padding-start: 0"
fill="clear"
(click)="launchHttps()"
[disabled]="caTrusted"
>
Skip
<ion-icon slot="end" name="open-outline"></ion-icon>
</ion-button>
</ng-container>

<ng-template #trusted>
<ion-icon
name="shield-checkmark-outline"
class="wiz-icon"
color="success"
></ion-icon>
<h1 class="title">Root CA Trusted!</h1>
<p class="subtitle">
You have successfully trusted your server's Root CA and may now log in
securely.
</p>
<ion-button strong (click)="launchHttps()">
Go to login
<ion-icon slot="end" name="open-outline"></ion-icon>
</ion-button>
</ng-template>
</ion-content>

<a
id="install-cert"
href="/eos/local.crt"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,44 +1,41 @@
.grid-wiz {
--ion-grid-padding: 36px;
height: 100%
ion-content {
--padding-top: 2.2rem;
--padding-bottom: 2.2rem;
--padding-start: 2.2rem;
--padding-end: 2.2rem;
}

.wiz-icon {
font-size: 84px;
.title {
font-size: 28px;
font-weight: 600;
}

.wiz-card {
background: #414141;
margin: 24px;
padding: 16px;
height: 280px;
border-radius: 16px;
display: grid;

& h2 {
font-weight: 600;
}
.subtitle {
font-size: 21px;
line-height: 26px;
margin-bottom: 30px;
margin-top: 0;
}

.wiz-card-button {
justify-self: center;
white-space: normal;
}
ol {
font-size: 17px;
line-height: 25px;

.wiz-spinner {
width: 14px;
height: 14px;
}
li {
padding-bottom: 24px;
}

.disabled {
filter: saturate(0.2) contrast(0.5)
ion-button {
margin-top: 8px;
}
}

.wiz-step {
margin-top: 4px;
a {
cursor: pointer;
color: aquamarine;
text-decoration: underline;
}

.inline-center {
display: inline-flex;
align-items: center;
}
.wiz-icon {
font-size: 64px;
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Component, Inject } from '@angular/core'
import { ApiService } from 'src/app/services/api/embassy-api.service'
import { ConfigService } from 'src/app/services/config.service'
import { pauseFor, RELATIVE_URL } from '@start9labs/shared'
import { RELATIVE_URL } from '@start9labs/shared'
import { DOCUMENT } from '@angular/common'
import { WINDOW } from '@ng-web-apis/common'

Expand All @@ -11,9 +11,6 @@ import { WINDOW } from '@ng-web-apis/common'
styleUrls: ['./ca-wizard.component.scss'],
})
export class CAWizardComponent {
downloadClicked = false
instructionsClicked = false
polling = false
caTrusted = false

constructor(
Expand All @@ -25,15 +22,12 @@ export class CAWizardComponent {
) {}

async ngOnInit() {
if (!this.config.isSecure()) {
await this.testHttps().catch(e =>
console.warn('Failed Https connection attempt'),
)
}
await this.testHttps().catch(e =>
console.warn('Failed Https connection attempt'),
)
}

download() {
this.downloadClicked = true
this.document.getElementById('install-cert')?.click()
}

Expand All @@ -43,21 +37,10 @@ export class CAWizardComponent {
'_blank',
'noreferrer',
)
this.instructionsClicked = true
this.startDaemon()
}

private async startDaemon(): Promise<void> {
this.polling = true
while (this.polling) {
try {
await this.testHttps()
this.polling = false
} catch (e) {
console.warn('Failed Https connection attempt')
await pauseFor(2000)
}
}
refresh() {
this.document.location.reload()
}

launchHttps() {
Expand All @@ -68,8 +51,6 @@ export class CAWizardComponent {
private async testHttps() {
const url = `https://${this.document.location.host}${this.relativeUrl}`
await this.api.echo({ message: 'ping' }, url).then(() => {
this.downloadClicked = true
this.instructionsClicked = true
this.caTrusted = true
})
}
Expand Down

0 comments on commit 36f4fb6

Please sign in to comment.