mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 10:21:52 +00:00
round out adding new domains
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(),
|
||||
},
|
||||
],
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user