round out adding new domains

This commit is contained in:
Matt Hill
2023-07-14 12:53:26 -06:00
parent 19f5e92a74
commit bd0ddafcd0
6 changed files with 162 additions and 57 deletions

View File

@@ -2,7 +2,7 @@ import { Config } from '@start9labs/start-sdk/lib/config/builder/config'
import { Value } from '@start9labs/start-sdk/lib/config/builder/value'
import { Variants } from '@start9labs/start-sdk/lib/config/builder/variants'
const ddnsOptions = Config.of({
const auth = Config.of({
username: Value.text({
name: 'Username',
required: { default: null },
@@ -14,7 +14,46 @@ const ddnsOptions = Config.of({
}),
})
export const domainSpec = Config.of({
const strategyUnion = Value.union(
{
name: 'Networking Strategy',
required: { default: 'router' },
},
Variants.of({
router: {
name: 'Router',
spec: Config.of({
ip: Value.select({
name: 'IP Strategy',
description: `
<h5>IPv6 Only</h5><b>Pros</b>: Ready for IPv6 Internet. Enhanced privacy, as IPv6 addresses are less correlated with geographic area
<b>Cons</b>: Your website is only accessible to people who's ISP supports IPv6
<h5>IPv6 and IPv4</h5><b>Pros</b>: Ready for IPv6 Internet. Anyone can access your website
<b>Cons</b>: IPv4 addresses are closely correlated with geographic areas
<h5>IPv4 Only</h5><b>Pros</b>: Anyone can access your website
<b>Cons</b>: IPv4 addresses are closely correlated with geographic areas
`,
required: { default: 'ipv6' },
values: {
ipv6: 'IPv6 Only',
both: 'IPv6 and IPv4',
ipv4: 'IPv4 Only',
},
}),
}),
},
reverseProxy: {
name: 'Reverse Proxy',
spec: Config.of({}),
},
}),
)
export const start9MeSpec = Config.of({
strategy: strategyUnion,
})
export const customSpec = Config.of({
hostname: Value.text({
name: 'Hostname',
required: { default: null },
@@ -32,30 +71,32 @@ export const domainSpec = Config.of({
},
duckdns: {
name: 'Duck DNS',
spec: ddnsOptions,
spec: auth,
},
dyn: {
name: 'DynDNS',
spec: ddnsOptions,
spec: auth,
},
easydns: {
name: 'easyDNS',
spec: ddnsOptions,
spec: auth,
},
googledomains: {
name: 'Google Domains',
spec: ddnsOptions,
spec: auth,
},
namecheap: {
name: 'Namecheap (IPv4 only)',
spec: ddnsOptions,
spec: auth,
},
zoneedit: {
name: 'Zoneedit',
spec: ddnsOptions,
spec: auth,
},
}),
),
strategy: strategyUnion,
})
export type DomainSpec = typeof domainSpec.validator._TYPE
export type Start9MeSpec = typeof start9MeSpec.validator._TYPE
export type CustomSpec = typeof customSpec.validator._TYPE

View File

@@ -24,7 +24,7 @@
class="ion-padding-start"
strong
size="small"
(click)="presentAlertClaimStart9MeDomain()"
(click)="presentModalClaimStart9Me()"
>
<ion-icon slot="start" name="add-outline"></ion-icon>
Claim
@@ -34,20 +34,24 @@
<div class="grid-fixed">
<ion-grid class="ion-padding">
<ion-row class="grid-headings">
<ion-col size="3">Domain</ion-col>
<ion-col size="2.5">Added</ion-col>
<ion-col size="2.5">DDNS Provider</ion-col>
<ion-col size="2">In Use</ion-col>
<ion-col size="2"></ion-col>
<ion-col size="2">Domain</ion-col>
<ion-col size="2">Added</ion-col>
<ion-col size="2">DDNS Provider</ion-col>
<ion-col size="1.5">Network Strategy</ion-col>
<ion-col size="2">IP Strategy</ion-col>
<ion-col size="1.5">In Use</ion-col>
<ion-col size="1"></ion-col>
</ion-row>
<ion-row
*ngIf="domains.start9Me as start9Me"
class="ion-align-items-center grid-row-border"
>
<ion-col size="3">{{ start9Me.value }}</ion-col>
<ion-col size="2.5">{{ start9Me.createdAt| date: 'medium' }}</ion-col>
<ion-col size="2.5">Start9</ion-col>
<ion-col size="2" *ngIf="start9Me.usedBy as usedBy">
<ion-col size="2">{{ start9Me.value }}</ion-col>
<ion-col size="2">{{ start9Me.createdAt| date: 'short' }}</ion-col>
<ion-col size="2">Start9</ion-col>
<ion-col size="1.5">{{ start9Me.networkStrategy }}</ion-col>
<ion-col size="2">{{ start9Me.ipStrategy || 'N/A' }}</ion-col>
<ion-col size="1.5" *ngIf="start9Me.usedBy as usedBy">
<a
*ngIf="usedBy.length as qty; else unused"
(click)="presentAlertUsedBy(start9Me.value, usedBy)"
@@ -58,7 +62,7 @@
<span>N/A</span>
</ng-template>
</ion-col>
<ion-col size="2">
<ion-col size="1">
<ion-buttons style="float: right">
<ion-button size="small" (click)="presentAlertDeleteStart9Me()">
<ion-icon name="trash"></ion-icon>
@@ -85,20 +89,24 @@
<div class="grid-fixed">
<ion-grid class="ion-padding">
<ion-row class="grid-headings">
<ion-col size="3">Domain</ion-col>
<ion-col size="2.5">Added</ion-col>
<ion-col size="2.5">DDNS Provider</ion-col>
<ion-col size="2">In Use</ion-col>
<ion-col size="2"></ion-col>
<ion-col size="2">Domain</ion-col>
<ion-col size="2">Added</ion-col>
<ion-col size="2">DDNS Provider</ion-col>
<ion-col size="1.5">Network Strategy</ion-col>
<ion-col size="2">IP Strategy</ion-col>
<ion-col size="1.5">In Use</ion-col>
<ion-col size="1"></ion-col>
</ion-row>
<ion-row
*ngFor="let domain of domains.custom"
class="ion-align-items-center grid-row-border"
>
<ion-col size="3">{{ domain.value }}</ion-col>
<ion-col size="2.5">{{ domain.createdAt| date: 'medium' }}</ion-col>
<ion-col size="2.5">{{ domain.provider.unionSelectKey }}</ion-col>
<ion-col size="2" *ngIf="domain.usedBy as usedBy">
<ion-col size="2">{{ domain.value }}</ion-col>
<ion-col size="2">{{ domain.createdAt| date: 'short' }}</ion-col>
<ion-col size="2">{{ domain.provider }}</ion-col>
<ion-col size="1.5">{{ domain.networkStrategy }}</ion-col>
<ion-col size="2">{{ domain.ipStrategy || 'N/A' }}</ion-col>
<ion-col size="1.5" *ngIf="domain.usedBy as usedBy">
<a
*ngIf="usedBy.length as qty; else unused"
(click)="presentAlertUsedBy(domain.value, usedBy)"
@@ -109,7 +117,7 @@
<span>N/A</span>
</ng-template>
</ion-col>
<ion-col size="2">
<ion-col size="1">
<ion-buttons style="float: right">
<ion-button
size="small"

View File

@@ -7,7 +7,12 @@ import { PatchDB } from 'patch-db-client'
import { ApiService } from 'src/app/services/api/embassy-api.service'
import { DataModel } from 'src/app/services/patch-db/data-model'
import { FormDialogService } from 'src/app/services/form-dialog.service'
import { DomainSpec, domainSpec } from './domain.const'
import {
start9MeSpec,
Start9MeSpec,
customSpec,
CustomSpec,
} from './domain.const'
import { ConnectionService } from 'src/app/services/connection.service'
import { FormContext, FormPage } from '../../../modals/form/form.page'
import { getClearnetAddress } from 'src/app/util/clearnetAddress'
@@ -23,7 +28,7 @@ export class DomainsPage {
readonly server$ = this.patch.watch$('server-info')
readonly pkgs$ = this.patch.watch$('package-data').pipe(first())
readonly domains$ = this.connectionService.connected$.pipe(
readonly domains$ = this.connectionService.websocketConnected$.pipe(
filter(Boolean),
switchMap(() =>
combineLatest([this.server$, this.pkgs$]).pipe(
@@ -35,6 +40,8 @@ export class DomainsPage {
value: `${start9MeSubdomain.value}.start9.me`,
createdAt: start9MeSubdomain.createdAt,
provider: 'Start9',
networkStrategy: start9MeSubdomain.networkStrategy,
ipStrategy: start9MeSubdomain.ipStrategy,
usedBy: usedBy(
start9MeSubdomain.value,
getClearnetAddress('https', ui.domainInfo),
@@ -45,6 +52,8 @@ export class DomainsPage {
value: domain.value,
createdAt: domain.createdAt,
provider: domain.provider,
networkStrategy: domain.networkStrategy,
ipStrategy: domain.ipStrategy,
usedBy: usedBy(
domain.value,
getClearnetAddress('https', ui.domainInfo),
@@ -69,10 +78,10 @@ export class DomainsPage {
) {}
async presentModalAdd() {
const options: Partial<TuiDialogOptions<FormContext<DomainSpec>>> = {
const options: Partial<TuiDialogOptions<FormContext<CustomSpec>>> = {
label: 'Custom Domain',
data: {
spec: await domainSpec.build({} as any),
spec: await customSpec.build({} as any),
buttons: [
{
text: 'Save',
@@ -84,19 +93,20 @@ export class DomainsPage {
this.formDialog.open(FormPage, options)
}
presentAlertClaimStart9MeDomain() {
this.dialogs
.open(TUI_PROMPT, {
label: 'Confirm',
size: 's',
data: {
content: 'Claim your start9.me domain?',
yes: 'Claim',
no: 'Cancel',
},
})
.pipe(filter(Boolean))
.subscribe(() => this.claimStart9MeDomain())
async presentModalClaimStart9Me() {
const options: Partial<TuiDialogOptions<FormContext<Start9MeSpec>>> = {
label: 'start9.me',
data: {
spec: await start9MeSpec.build({} as any),
buttons: [
{
text: 'Save',
handler: async value => this.claimStart9MeDomain(value),
},
],
},
}
this.formDialog.open(FormPage, options)
}
presentAlertDelete(hostname: string) {
@@ -143,11 +153,17 @@ export class DomainsPage {
.subscribe()
}
private async claimStart9MeDomain(): Promise<boolean> {
private async claimStart9MeDomain(value: Start9MeSpec): Promise<boolean> {
const loader = this.loader.open('Saving...').subscribe()
const networkStrategy = value.strategy.unionSelectKey
try {
await this.api.claimStart9MeDomain({})
await this.api.claimStart9MeDomain({
networkStrategy,
ipStrategy:
networkStrategy === 'router' ? value.strategy.unionValueKey.ip : null,
})
return true
} catch (e: any) {
this.errorService.handleError(e)
@@ -157,11 +173,30 @@ export class DomainsPage {
}
}
private async save(value: DomainSpec): Promise<boolean> {
private async save(value: CustomSpec): Promise<boolean> {
const loader = this.loader.open('Saving...').subscribe()
const networkStrategy = value.strategy.unionSelectKey
const providerName = value.provider.unionSelectKey
try {
await this.api.addDomain(value)
await this.api.addDomain({
hostname: value.hostname,
provider: {
name: providerName,
username:
providerName === 'start9'
? null
: value.provider.unionValueKey.username,
password:
providerName === 'start9'
? null
: value.provider.unionValueKey.password,
},
networkStrategy,
ipStrategy:
networkStrategy === 'router' ? value.strategy.unionValueKey.ip : null,
})
return true
} catch (e: any) {
this.errorService.handleError(e)

View File

@@ -8,7 +8,10 @@ import {
} from 'src/app/services/patch-db/data-model'
import { StartOSDiskInfo, LogsRes, ServerLogsReq } from '@start9labs/shared'
import { customSmtp } from '@start9labs/start-sdk/lib/config/configConstants'
import { DomainSpec } from 'src/app/apps/ui/pages/system/domains/domain.const'
import {
CustomSpec,
Start9MeSpec,
} from 'src/app/apps/ui/pages/system/domains/domain.const'
export module RR {
// DB
@@ -112,13 +115,25 @@ export module RR {
// domains
export type ClaimStart9MeReq = {} // net.domain.me.claim
export type ClaimStart9MeReq = {
networkStrategy: string
ipStrategy: string | null
} // net.domain.me.claim
export type ClaimStart9MeRes = null
export type DeleteStart9MeReq = {} // net.domain.me.delete
export type DeleteStart9MeRes = null
export type AddDomainReq = DomainSpec // net.domain.add
export type AddDomainReq = {
hostname: string
provider: {
name: string
username: string | null
password: string | null
}
networkStrategy: string
ipStrategy: string | null
} // net.domain.add
export type AddDomainRes = null
export type DeleteDomainReq = { hostname: string } // net.domain.delete

View File

@@ -452,6 +452,8 @@ export class MockApiService extends ApiService {
value: {
value: 'xyz',
createdAt: new Date(),
networkStrategy: params.networkStrategy,
ipStrategy: params.ipStrategy,
},
},
]
@@ -482,7 +484,9 @@ export class MockApiService extends ApiService {
value: [
{
value: params.hostname,
provider: params.provider,
provider: params.provider.name,
networkStrategy: params.networkStrategy,
ipStrategy: params.ipStrategy,
createdAt: new Date(),
},
],

View File

@@ -3,7 +3,7 @@ import { Url } from '@start9labs/shared'
import { Manifest } from '@start9labs/marketplace'
import { BackupJob } from '../api/api.types'
import { customSmtp } from '@start9labs/start-sdk/lib/config/configConstants'
import { DomainSpec } from 'src/app/apps/ui/pages/system/domains/domain.const'
import { CustomSpec } from 'src/app/apps/ui/pages/system/domains/domain.const'
export interface DataModel {
'server-info': ServerInfo
@@ -104,7 +104,9 @@ export type WiFiInfo = {
export type Domain = {
value: string
provider: DomainSpec['provider']
provider: string
networkStrategy: string
ipStrategy: string
createdAt: string
}