endpoint for getting config

This commit is contained in:
Matt Hill
2025-10-30 14:33:21 -06:00
parent 6ff329c897
commit 3dcdca18a3
4 changed files with 79 additions and 46 deletions

View File

@@ -90,7 +90,7 @@ import { TunnelData, WgServer } from 'src/app/services/patch-db/data-model'
tuiOption
iconStart="@tui.settings"
new
(click)="config.set(true)"
(click)="onConfig(device)"
>
View Config
</button>
@@ -163,7 +163,7 @@ import { TunnelData, WgServer } from 'src/app/services/patch-db/data-model'
</footer>
</form>
</ng-template>
<ng-template [(tuiDialog)]="config">
<ng-template [(tuiDialog)]="showConfig">
<header tuiHeader>
<h2 tuiTitle>Device Config</h2>
<aside tuiAccessories>
@@ -180,7 +180,7 @@ import { TunnelData, WgServer } from 'src/app/services/patch-db/data-model'
</aside>
</header>
@if (segmented?.activeItemIndex) {
<qr-code [value]="mock" size="352" />
<qr-code [value]="config()" size="352" />
} @else {
<tui-textfield>
<textarea
@@ -188,7 +188,7 @@ import { TunnelData, WgServer } from 'src/app/services/patch-db/data-model'
[min]="16"
[max]="16"
[readOnly]="true"
[value]="mock"
[value]="config()"
></textarea>
<tui-icon tuiCopy />
<a
@@ -196,7 +196,7 @@ import { TunnelData, WgServer } from 'src/app/services/patch-db/data-model'
iconStart="@tui.download"
download="start-tunnel.conf"
size="s"
[href]="href"
[href]="href()"
>
Download
</a>
@@ -234,10 +234,14 @@ export default class Devices {
private readonly loading = inject(LoadingService)
private readonly patch = inject<PatchDB<TunnelData>>(PatchDB)
protected readonly mock = MOCK
protected readonly href = `data:text/plain;charset=utf-8,${encodeURIComponent(MOCK)}`
protected readonly dialog = signal(false)
protected readonly config = signal(false)
protected readonly showConfig = signal(false)
protected readonly config = signal('')
protected readonly href = computed(
() => `data:text/plain;charset=utf-8,${encodeURIComponent(this.config())}`,
)
protected readonly editing = signal(false)
protected readonly subnets = toSignal<MappedSubnet[], []>(
@@ -279,18 +283,36 @@ export default class Devices {
ip: ['', Validators.required],
})
protected onAdd(): void {
protected onAdd() {
this.editing.set(false)
this.form.reset()
this.dialog.set(true)
}
protected onEdit(device: MappedDevice): void {
protected onEdit(device: MappedDevice) {
this.editing.set(true)
this.form.reset(device)
this.dialog.set(true)
}
async onConfig(device: MappedDevice) {
const loader = this.loading.open().subscribe()
try {
const config = await this.api.showDeviceConfig({
subnet: device.subnet.range,
ip: device.ip,
})
this.config.set(config)
this.showConfig.set(true)
} catch (e) {
console.log(e)
} finally {
loader.unsubscribe()
this.dialog.set(false)
}
}
protected async onSave() {
if (this.form.invalid) {
tuiMarkControlAsTouchedAndValidate(this.form)
@@ -353,21 +375,3 @@ type MappedDevice = {
ip: string
name: string
}
const MOCK = `[Interface]
# Server's private IP address for the WireGuard VPN subnet
Address = 10.20.10.1/24
# UDP port WireGuard listens on
ListenPort = 33333
# Server private key (generated)
PrivateKey = 4K68mdpQWdEz/FpdVuRoZYgWpQgpW63J9GFzn+iOulQ=
# Commands to run after starting/stopping WireGuard tunnel to enable forwarding and NAT (example)
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
# Add client peers below with their public keys and allowed IPs
[Peer]
# Client public key
PublicKey = MQBiYHxAj7u8paj3L4w4uav3P/9YBPbaN4gkWn90SSs=
# Allowed client IP address within VPN subnet`

View File

@@ -8,22 +8,23 @@ import { Observable } from 'rxjs'
})
export abstract class ApiService {
abstract openWebsocket$<T>(guid: string): Observable<T>
abstract subscribe(): Promise<SubscribeRes>
abstract subscribe(): Promise<SubscribeRes> // db.subscribe
// auth
abstract login(params: LoginReq): Promise<null>
abstract logout(): Promise<null>
abstract setPassword(params: LoginReq): Promise<null>
abstract login(params: LoginReq): Promise<null> // auth.login
abstract logout(): Promise<null> // auth.logout
abstract setPassword(params: LoginReq): Promise<null> // auth.set-password
// subnets
abstract addSubnet(params: UpsertSubnetReq): Promise<null>
abstract editSubnet(params: UpsertSubnetReq): Promise<null>
abstract deleteSubnet(params: DeleteSubnetReq): Promise<null>
abstract addSubnet(params: UpsertSubnetReq): Promise<null> // subnet.add
abstract editSubnet(params: UpsertSubnetReq): Promise<null> // subnet.add
abstract deleteSubnet(params: DeleteSubnetReq): Promise<null> // subnet.remove
// devices
abstract addDevice(params: UpsertDeviceReq): Promise<null>
abstract editDevice(params: UpsertDeviceReq): Promise<null>
abstract deleteDevice(params: DeleteDeviceReq): Promise<null>
abstract addDevice(params: UpsertDeviceReq): Promise<null> // device.add
abstract editDevice(params: UpsertDeviceReq): Promise<null> // device.add
abstract deleteDevice(params: DeleteDeviceReq): Promise<null> // device.remove
abstract showDeviceConfig(params: DeleteDeviceReq): Promise<string> // device.show-config
// forwards
abstract addForward(params: AddForwardReq): Promise<null>
abstract deleteForward(params: DeleteForwardReq): Promise<null>
abstract addForward(params: AddForwardReq): Promise<null> // forward.add
abstract deleteForward(params: DeleteForwardReq): Promise<null> // forward.remove
}
export type SubscribeRes = {

View File

@@ -70,7 +70,7 @@ export class LiveApiService extends ApiService {
}
async deleteSubnet(params: DeleteSubnetReq): Promise<null> {
return this.rpcRequest({ method: 'subnet.delete', params })
return this.rpcRequest({ method: 'subnet.remove', params })
}
// devices
@@ -84,27 +84,31 @@ export class LiveApiService extends ApiService {
}
async deleteDevice(params: DeleteDeviceReq): Promise<null> {
return this.rpcRequest({ method: 'device.delete', params })
return this.rpcRequest({ method: 'device.remove', params })
}
async showDeviceConfig(params: DeleteDeviceReq): Promise<string> {
return this.rpcRequest({ method: 'device.show-config', params })
}
// forwards
async addForward(params: AddForwardReq): Promise<null> {
return this.rpcRequest({ method: 'forward.create', params })
return this.rpcRequest({ method: 'forward.add', params })
}
async deleteForward(params: DeleteForwardReq): Promise<null> {
return this.rpcRequest({ method: 'forward.delete', params })
return this.rpcRequest({ method: 'forward.remove', params })
}
// private
private async upsertSubnet(params: UpsertSubnetReq): Promise<null> {
return this.rpcRequest({ method: 'subnet.upsert', params })
return this.rpcRequest({ method: 'subnet.add', params })
}
private async upsertDevice(params: UpsertDeviceReq): Promise<null> {
return this.rpcRequest({ method: 'device.upsert', params })
return this.rpcRequest({ method: 'device.add', params })
}
private async rpcRequest<T>(

View File

@@ -161,6 +161,12 @@ export class MockApiService extends ApiService {
return null
}
async showDeviceConfig(params: DeleteDeviceReq): Promise<string> {
await pauseFor(1000)
return MOCK_CONFIG
}
async addForward(params: AddForwardReq): Promise<null> {
await pauseFor(1000)
@@ -202,3 +208,21 @@ export class MockApiService extends ApiService {
function replaceSlashes(val: string) {
return val.replace(new RegExp('/', 'g'), '~1')
}
const MOCK_CONFIG = `[Interface]
# Server's private IP address for the WireGuard VPN subnet
Address = 10.20.10.1/24
# UDP port WireGuard listens on
ListenPort = 33333
# Server private key (generated)
PrivateKey = 4K68mdpQWdEz/FpdVuRoZYgWpQgpW63J9GFzn+iOulQ=
# Commands to run after starting/stopping WireGuard tunnel to enable forwarding and NAT (example)
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
# Add client peers below with their public keys and allowed IPs
[Peer]
# Client public key
PublicKey = MQBiYHxAj7u8paj3L4w4uav3P/9YBPbaN4gkWn90SSs=
# Allowed client IP address within VPN subnet`