diff --git a/web/projects/ui/src/app/routes/portal/components/interfaces/interface.service.ts b/web/projects/ui/src/app/routes/portal/components/interfaces/interface.service.ts index 48e93a951..5960e2a1c 100644 --- a/web/projects/ui/src/app/routes/portal/components/interfaces/interface.service.ts +++ b/web/projects/ui/src/app/routes/portal/components/interfaces/interface.service.ts @@ -42,7 +42,7 @@ function cmpLan(host: T.Host, a: LanAddress, b: LanAddress): -1 | 0 | 1 { return cmpWithRankedPredicates(a, b, [ x => x.info.hostname.kind === 'domain' && - !!host.privateDomains[x.info.hostname.value], // private domain + !!host.privateDomains.find(d => d === x.info.hostname.value), // private domain x => x.info.hostname.kind === 'local', // .local x => x.info.hostname.kind === 'ipv4', // ipv4 x => x.info.hostname.kind === 'ipv6', // ipv6 @@ -66,7 +66,7 @@ function cmpVpn(host: T.Host, a: VpnAddress, b: VpnAddress): -1 | 0 | 1 { return cmpWithRankedPredicates(a, b, [ x => x.info.hostname.kind === 'domain' && - !!host.privateDomains[x.info.hostname.value], // private domain + !!host.privateDomains.find(d => d === x.info.hostname.value), // private domain x => x.info.hostname.kind === 'ipv4', // ipv4 x => x.info.hostname.kind === 'ipv6', // ipv6 // remainder: public domains accessible privately @@ -102,7 +102,7 @@ function cmpClearnet( function toDisplayAddress( { info, url }: AddressWithInfo, gateways: GatewayPlus[], - publicDomains: Record, + publicDomains: Record, ): DisplayAddress { let access: DisplayAddress['access'] let gatewayName: DisplayAddress['gatewayName'] @@ -248,11 +248,13 @@ function toDisplayAddress( } export function getPublicDomains( - publicDomains: Record, + publicDomains: Record, + gateways: GatewayPlus[], ): PublicDomain[] { return Object.entries(publicDomains).map(([fqdn, info]) => ({ fqdn, - ...info, + acme: info.acme, + gateway: gateways.find(g => g.id === info.gateway) || null, })) } @@ -302,18 +304,11 @@ export class InterfaceService { return { common: bestAddrs.map(a => - toDisplayAddress(a, gateways, host.publicDomains, host.privateDomains), + toDisplayAddress(a, gateways, host.publicDomains), ), uncommon: allAddressesWithInfo .filter(a => !bestAddrs.includes(a)) - .map(a => - toDisplayAddress( - a, - gateways, - host.publicDomains, - host.privateDomains, - ), - ), + .map(a => toDisplayAddress(a, gateways, host.publicDomains)), } } diff --git a/web/projects/ui/src/app/routes/portal/components/interfaces/public-domains/dns.component.ts b/web/projects/ui/src/app/routes/portal/components/interfaces/public-domains/dns.component.ts index c5046f680..74dbf85ff 100644 --- a/web/projects/ui/src/app/routes/portal/components/interfaces/public-domains/dns.component.ts +++ b/web/projects/ui/src/app/routes/portal/components/interfaces/public-domains/dns.component.ts @@ -150,9 +150,8 @@ export class DnsComponent { this.loading.set(true) try { - const ip = await this.api.testDns({ + const ip = await this.api.queryDns({ fqdn: this.context.data.fqdn, - gateway: this.context.data.gateway.id, }) this.pass.set(ip === this.context.data.gateway.ipInfo.wanIp) diff --git a/web/projects/ui/src/app/routes/portal/components/interfaces/public-domains/pd.component.ts b/web/projects/ui/src/app/routes/portal/components/interfaces/public-domains/pd.component.ts index 33699bc27..a02eda247 100644 --- a/web/projects/ui/src/app/routes/portal/components/interfaces/public-domains/pd.component.ts +++ b/web/projects/ui/src/app/routes/portal/components/interfaces/public-domains/pd.component.ts @@ -39,7 +39,7 @@ import { PublicDomain, PublicDomainService } from './pd.service' @for (domain of publicDomains(); track $index) { - + } @empty { @if (publicDomains()) { diff --git a/web/projects/ui/src/app/routes/portal/components/interfaces/public-domains/pd.item.component.ts b/web/projects/ui/src/app/routes/portal/components/interfaces/public-domains/pd.item.component.ts index 22c808f23..b4958c511 100644 --- a/web/projects/ui/src/app/routes/portal/components/interfaces/public-domains/pd.item.component.ts +++ b/web/projects/ui/src/app/routes/portal/components/interfaces/public-domains/pd.item.component.ts @@ -16,10 +16,10 @@ import { PublicDomain, PublicDomainService } from './pd.service' import { toAuthorityName } from 'src/app/utils/acme' @Component({ - selector: 'tr[domain]', + selector: 'tr[publicDomain]', template: ` - - + +
{{ domain().fqdn }}{{ domain().gateway }}{{ publicDomain().fqdn }}{{ publicDomain().gateway?.ipInfo?.name }} {{ authority() }} @@ -59,7 +63,7 @@ import { toAuthorityName } from 'src/app/utils/acme' new iconStart="@tui.trash" class="g-negative" - (click)="service.remove(domain().fqdn)" + (click)="service.remove(publicDomain().fqdn)" > {{ 'Delete' | i18n }} @@ -99,11 +103,11 @@ export class PublicDomainsItemComponent { open = false - readonly domain = input.required() + readonly publicDomain = input.required() - readonly authority = computed(() => toAuthorityName(this.domain().acme)) + readonly authority = computed(() => toAuthorityName(this.publicDomain().acme)) readonly dnsMessage = computed( () => - `Create one of the DNS records below to cause ${this.domain().fqdn} to resolve to ${this.domain().gateway.ipInfo.wanIp}` as i18nKey, + `Create one of the DNS records below to cause ${this.publicDomain().fqdn} to resolve to ${this.publicDomain().gateway?.ipInfo.wanIp}` as i18nKey, ) } diff --git a/web/projects/ui/src/app/routes/portal/components/interfaces/public-domains/pd.service.ts b/web/projects/ui/src/app/routes/portal/components/interfaces/public-domains/pd.service.ts index 29f364dce..b14d45c07 100644 --- a/web/projects/ui/src/app/routes/portal/components/interfaces/public-domains/pd.service.ts +++ b/web/projects/ui/src/app/routes/portal/components/interfaces/public-domains/pd.service.ts @@ -15,7 +15,6 @@ import { configBuilderToSpec } from 'src/app/utils/configBuilderToSpec' import { PatchDB } from 'patch-db-client' import { DataModel } from 'src/app/services/patch-db/data-model' import { toAuthorityName } from 'src/app/utils/acme' -import { GatewayPlus } from 'src/app/services/gateway.service' import { InterfaceComponent } from '../interface.component' import { DNS } from './dns.component' @@ -23,7 +22,7 @@ import { DNS } from './dns.component' export type PublicDomain = { fqdn: string - gateway: GatewayPlus + gateway: GatewayWithId | null acme: string | null } @@ -104,7 +103,7 @@ export class PublicDomainService { }, ], value: { - gateway: domain.gateway.id, + gateway: domain.gateway!.id, authority: domain.acme, }, }, diff --git a/web/projects/ui/src/app/routes/portal/routes/services/components/interfaces.component.ts b/web/projects/ui/src/app/routes/portal/routes/services/components/interfaces.component.ts index 59772ef01..74723546e 100644 --- a/web/projects/ui/src/app/routes/portal/routes/services/components/interfaces.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/services/components/interfaces.component.ts @@ -48,7 +48,7 @@ export class ServiceInterfacesComponent { readonly pkg = input.required() readonly disabled = input(false) - readonly interfaces = computed(({ serviceInterfaces, hosts } = this.pkg()) => + readonly interfaces = computed(({ serviceInterfaces } = this.pkg()) => Object.entries(serviceInterfaces) .sort((a, b) => tuiDefaultSort(a[1], b[1])) .map(([id, value]) => { diff --git a/web/projects/ui/src/app/routes/portal/routes/services/routes/interface.component.ts b/web/projects/ui/src/app/routes/portal/routes/services/routes/interface.component.ts index 39ec3fdad..d61885e73 100644 --- a/web/projects/ui/src/app/routes/portal/routes/services/routes/interface.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/services/routes/interface.component.ts @@ -100,10 +100,6 @@ export default class ServiceInterfaceRoute { readonly pkg = toSignal(this.patch.watch$('packageData', this.pkgId)) - readonly domains = toSignal( - this.patch.watch$('serverInfo', 'network', 'domains'), - ) - readonly isRunning = computed(() => { return this.pkg()?.status.main === 'running' }) @@ -111,9 +107,8 @@ export default class ServiceInterfaceRoute { readonly serviceInterface = computed(() => { const pkg = this.pkg() const id = this.interfaceId() - const domains = this.domains() - if (!pkg || !id || !domains) { + if (!pkg || !id) { return } @@ -131,20 +126,15 @@ export default class ServiceInterfaceRoute { return { ...iFace, - addresses: this.interfaceService.getAddresses( - iFace, - host, - domains, - gateways, - ), + addresses: this.interfaceService.getAddresses(iFace, host, gateways), gateways: gateways.map(g => ({ enabled: true, ...g, })) || [], torDomains: host.onions.map(o => `${o}.onion`), - publicDomains: getPublicDomains(host.domains.public), - privateDomains: host.domains.private, + publicDomains: getPublicDomains(host.publicDomains, gateways), + privateDomains: host.privateDomains, isOs: false, } }) diff --git a/web/projects/ui/src/app/routes/portal/routes/system/routes/dns/dns.component.ts b/web/projects/ui/src/app/routes/portal/routes/system/routes/dns/dns.component.ts index 59086b878..0e2fd55eb 100644 --- a/web/projects/ui/src/app/routes/portal/routes/system/routes/dns/dns.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/system/routes/dns/dns.component.ts @@ -158,19 +158,27 @@ export default class SystemDnsComponent { switchMap(async ([pkgs, { gateways, dns }]) => { const spec = await configBuilderToSpec(this.dnsSpec) - const selection = dns.static ? 'custom' : 'defaults' + const current = dns.staticServers + ? { + selection: 'custom', + value: dns.staticServers, + } + : { selection: 'defaults', value: dns.dhcpServers } - const form = this.formService.createForm(spec, { - strategy: { selection, value: dns.servers }, - }) + const form = this.formService.createForm(spec, current) return { spec, form, warn: - (Object.values(pkgs).some(p => p) || []) && + (Object.values(pkgs).some(p => + Object.values(p.hosts).some(h => h?.privateDomains.length), + ) || + []) && Object.values(gateways) - .filter(g => dns.servers.includes(g.ipInfo?.lanIp)) + .filter(g => + dns.dhcpServers.some(d => g.ipInfo?.lanIp.includes(d)), + ) .map(g => g.ipInfo?.name), } }), diff --git a/web/projects/ui/src/app/routes/portal/routes/system/routes/startos-ui/startos-ui.component.ts b/web/projects/ui/src/app/routes/portal/routes/system/routes/startos-ui/startos-ui.component.ts index 4c44fd222..cc7a6ac4e 100644 --- a/web/projects/ui/src/app/routes/portal/routes/system/routes/startos-ui/startos-ui.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/system/routes/startos-ui/startos-ui.component.ts @@ -89,7 +89,6 @@ export default class StartOsUiComponent { addresses: this.interfaceService.getAddresses( this.iface, network.host, - network.domains, gateways, ), gateways: gateways.map(g => ({ @@ -97,8 +96,8 @@ export default class StartOsUiComponent { ...g, })), torDomains: network.host.onions.map(o => `${o}.onion`), - publicDomains: getPublicDomains(network.host.domains.public), - privateDomains: network.host.domains.private, + publicDomains: getPublicDomains(network.host.publicDomains, gateways), + privateDomains: network.host.privateDomains, isOs: true, } }) diff --git a/web/projects/ui/src/app/services/api/api.fixures.ts b/web/projects/ui/src/app/services/api/api.fixures.ts index 5f01fa370..20fd6ef96 100644 --- a/web/projects/ui/src/app/services/api/api.fixures.ts +++ b/web/projects/ui/src/app/services/api/api.fixures.ts @@ -2069,11 +2069,9 @@ export namespace Mock { }, }, }, + publicDomains: {}, + privateDomains: [], onions: [], - domains: { - public: {}, - private: {}, - }, hostnameInfo: { 80: [ { @@ -2172,11 +2170,9 @@ export namespace Mock { }, }, }, + publicDomains: {}, + privateDomains: [], onions: [], - domains: { - public: {}, - private: {}, - }, hostnameInfo: { 8332: [], }, @@ -2198,11 +2194,9 @@ export namespace Mock { }, }, }, + publicDomains: {}, + privateDomains: [], onions: [], - domains: { - public: {}, - private: {}, - }, hostnameInfo: { 8333: [], }, diff --git a/web/projects/ui/src/app/services/api/embassy-mock-api.service.ts b/web/projects/ui/src/app/services/api/embassy-mock-api.service.ts index f5cf9b560..39ea7c3ca 100644 --- a/web/projects/ui/src/app/services/api/embassy-mock-api.service.ts +++ b/web/projects/ui/src/app/services/api/embassy-mock-api.service.ts @@ -582,9 +582,11 @@ export class MockApiService extends ApiService { name: params.name, scopeId: 3, deviceType: 'wireguard', - subnets: [], - wanIp: '1.1.1.1', + subnets: ['192.168.1.10/24'], + wanIp: '203.0.113.45', ntpServers: [], + lanIp: ['192.168.1.10'], + dnsServers: [], }, }, }, @@ -1417,7 +1419,7 @@ export class MockApiService extends ApiService { const patch: Operation[] = [ { op: PatchOp.ADD, - path: `/serverInfo/host/domains/public`, + path: `/serverInfo/host/publicDomains`, value: { [params.fqdn]: { gateway: params.gateway, acme: params.acme }, }, @@ -1452,7 +1454,7 @@ export class MockApiService extends ApiService { const patch: RemoveOperation[] = [ { op: PatchOp.REMOVE, - path: `/serverInfo/host/domains/public/${params.fqdn}`, + path: `/serverInfo/host/publicDomains/${params.fqdn}`, }, { op: PatchOp.REMOVE, @@ -1472,7 +1474,7 @@ export class MockApiService extends ApiService { const patch: Operation[] = [ { op: PatchOp.REPLACE, - path: `/serverInfo/host/domains/private`, + path: `/serverInfo/host/privateDomains`, value: [params.fqdn], }, { @@ -1505,7 +1507,7 @@ export class MockApiService extends ApiService { const patch: Operation[] = [ { op: PatchOp.REPLACE, - path: `/serverInfo/host/domains/private`, + path: `/serverInfo/host/privateDomains`, value: [], }, { @@ -1590,7 +1592,7 @@ export class MockApiService extends ApiService { const patch: Operation[] = [ { op: PatchOp.ADD, - path: `/packageData/${params.package}/hosts/${params.host}/domains/public`, + path: `/packageData/${params.package}/hosts/${params.host}/publicDomains`, value: { [params.fqdn]: { gateway: params.gateway, acme: params.acme }, }, @@ -1625,7 +1627,7 @@ export class MockApiService extends ApiService { const patch: RemoveOperation[] = [ { op: PatchOp.REMOVE, - path: `/packageData/${params.package}/hosts/${params.host}/domains/public/${params.fqdn}`, + path: `/packageData/${params.package}/hosts/${params.host}/publicDomains/${params.fqdn}`, }, { op: PatchOp.REMOVE, @@ -1645,7 +1647,7 @@ export class MockApiService extends ApiService { const patch: Operation[] = [ { op: PatchOp.REPLACE, - path: `/packageData/${params.package}/hosts/${params.host}/domains/private`, + path: `/packageData/${params.package}/hosts/${params.host}/privateDomains`, value: [params.fqdn], }, { @@ -1678,7 +1680,7 @@ export class MockApiService extends ApiService { const patch: Operation[] = [ { op: PatchOp.REPLACE, - path: `/packageData/${params.package}/hosts/${params.host}/domains/private`, + path: `/packageData/${params.package}/hosts/${params.host}/privateDomains`, value: [], }, { diff --git a/web/projects/ui/src/app/services/api/mock-patch.ts b/web/projects/ui/src/app/services/api/mock-patch.ts index 19fa5fe91..1a0ed8a3f 100644 --- a/web/projects/ui/src/app/services/api/mock-patch.ts +++ b/web/projects/ui/src/app/services/api/mock-patch.ts @@ -52,10 +52,8 @@ export const mockPatchData: DataModel = { }, }, }, - domains: { - public: {}, - private: {}, - }, + publicDomains: {}, + privateDomains: [], onions: ['myveryownspecialtoraddress'], hostnameInfo: { 80: [ @@ -149,6 +147,8 @@ export const mockPatchData: DataModel = { subnets: ['10.0.0.2/24'], wanIp: '203.0.113.45', ntpServers: [], + lanIp: ['10.0.2.12'], + dnsServers: [], }, }, wlan0: { @@ -164,6 +164,8 @@ export const mockPatchData: DataModel = { ], wanIp: '203.0.113.45', ntpServers: [], + lanIp: ['10.0.90.12'], + dnsServers: ['8.8.8.8'], }, }, wireguard1: { @@ -179,9 +181,15 @@ export const mockPatchData: DataModel = { ], wanIp: '203.0.113.45', ntpServers: [], + lanIp: ['10.0.90.12'], + dnsServers: ['1.1.1.1'], }, }, }, + dns: { + dhcpServers: ['1.1.1.1', '8.8.8.8'], + staticServers: null, + }, }, unreadNotificationCount: 4, // password is asdfasdf @@ -338,11 +346,9 @@ export const mockPatchData: DataModel = { }, }, }, + publicDomains: {}, + privateDomains: [], onions: [], - domains: { - public: {}, - private: {}, - }, hostnameInfo: { 80: [ { @@ -441,11 +447,9 @@ export const mockPatchData: DataModel = { }, }, }, + publicDomains: {}, + privateDomains: [], onions: [], - domains: { - public: {}, - private: {}, - }, hostnameInfo: { 8332: [], }, @@ -467,11 +471,9 @@ export const mockPatchData: DataModel = { }, }, }, + publicDomains: {}, + privateDomains: [], onions: [], - domains: { - public: {}, - private: {}, - }, hostnameInfo: { 8333: [], },