fix incorrect handling of client mode (#537)
Some checks are pending
Docker / Build and Push (push) Waiting to run
Docker / release (push) Blocked by required conditions
github-pages / deploy (push) Waiting to run

This commit is contained in:
Christoph Haas
2025-10-03 17:30:14 +02:00
parent cc2d1f53c4
commit 97b6c398e8
5 changed files with 50 additions and 23 deletions

View File

@@ -358,7 +358,7 @@ async function del() {
<input type="text" class="form-control" :placeholder="$t('modals.peer-edit.endpoint.placeholder')" <input type="text" class="form-control" :placeholder="$t('modals.peer-edit.endpoint.placeholder')"
v-model="formData.Endpoint.Value"> v-model="formData.Endpoint.Value">
</div> </div>
<div class="form-group"> <div class="form-group" v-if="selectedInterface.Mode !== 'client'">
<label class="form-label mt-4">{{ $t('modals.peer-edit.ip.label') }}</label> <label class="form-label mt-4">{{ $t('modals.peer-edit.ip.label') }}</label>
<vue-tags-input class="form-control" v-model="currentTags.Addresses" <vue-tags-input class="form-control" v-model="currentTags.Addresses"
:tags="formData.Addresses.map(str => ({ text: str }))" :tags="formData.Addresses.map(str => ({ text: str }))"

View File

@@ -130,7 +130,7 @@ function ConfigQrUrl() {
<template> <template>
<Modal :title="title" :visible="visible" @close="close"> <Modal :title="title" :visible="visible" @close="close">
<template #default> <template #default>
<div class="d-flex justify-content-end align-items-center mb-1"> <div class="d-flex justify-content-end align-items-center mb-1" v-if="selectedInterface.Mode !== 'client'">
<span class="me-2">{{ $t('modals.peer-view.style-label') }}: </span> <span class="me-2">{{ $t('modals.peer-view.style-label') }}: </span>
<div class="btn-group btn-switch-group" role="group" aria-label="Configuration Style"> <div class="btn-group btn-switch-group" role="group" aria-label="Configuration Style">
<input type="radio" class="btn-check" name="configstyle" id="raw" value="raw" autocomplete="off" checked="" v-model="configStyle"> <input type="radio" class="btn-check" name="configstyle" id="raw" value="raw" autocomplete="off" checked="" v-model="configStyle">
@@ -151,20 +151,28 @@ function ConfigQrUrl() {
data-bs-parent="#peerInformation" style=""> data-bs-parent="#peerInformation" style="">
<div class="accordion-body"> <div class="accordion-body">
<div class="row"> <div class="row">
<div class="col-md-8"> <div :class="{ 'col-md-8': selectedInterface.Mode !== 'client', 'col-md-12': selectedInterface.Mode !== 'server' }" class="col-md-8">
<ul> <ul>
<li>{{ $t('modals.peer-view.identifier') }}: {{ selectedPeer.PublicKey }}</li> <li v-if="selectedInterface.Mode !== 'client'"><strong>{{ $t('modals.peer-view.identifier') }}</strong>: {{ selectedPeer.PublicKey }}</li>
<li>{{ $t('modals.peer-view.ip') }}: <span v-for="ip in selectedPeer.Addresses" :key="ip" <li v-if="selectedInterface.Mode !== 'server'"><strong>{{ $t('modals.peer-view.endpoint-key') }}</strong>: {{ selectedPeer.PublicKey }}</li>
<li v-if="selectedInterface.Mode !== 'server'"><strong>{{ $t('modals.peer-view.endpoint') }}</strong>: {{ selectedPeer.Endpoint.Value }}</li>
<li v-if="selectedInterface.Mode !== 'client'"><strong>{{ $t('modals.peer-view.ip') }}</strong>: <span v-for="ip in selectedPeer.Addresses" :key="ip"
class="badge rounded-pill bg-light">{{ ip }}</span></li> class="badge rounded-pill bg-light">{{ ip }}</span></li>
<li>{{ $t('modals.peer-view.user') }}: {{ selectedPeer.UserIdentifier }}</li> <li v-if="selectedInterface.Mode === 'server'"><strong>{{ $t('modals.peer-view.extra-allowed-ip') }}</strong>: <span v-for="ip in selectedPeer.ExtraAllowedIPs" :key="ip"
<li v-if="selectedPeer.Notes">{{ $t('modals.peer-view.notes') }}: {{ selectedPeer.Notes }}</li> class="badge rounded-pill bg-light">{{ ip }}</span></li>
<li v-if="selectedPeer.ExpiresAt">{{ $t('modals.peer-view.expiry-status') }}: {{ <li v-if="selectedInterface.Mode !== 'server' && selectedPeer.AllowedIPs.Value"><strong>{{ $t('modals.peer-view.allowed-ip') }}</strong>: <span v-for="ip in selectedPeer.AllowedIPs.Value" :key="ip"
class="badge rounded-pill bg-light">{{ ip }}</span></li>
<li v-if="selectedInterface.Mode !== 'server'"><strong>{{ $t('modals.peer-view.keepalive') }}</strong>: {{ selectedPeer.PersistentKeepalive.Value }}</li>
<li v-if="selectedPeer.UserDisplayName"><strong>{{ $t('modals.peer-view.user') }}</strong>: {{ selectedPeer.UserDisplayName }} ({{ selectedPeer.UserIdentifier }})</li>
<li v-else><strong>{{ $t('modals.peer-view.user') }}</strong>: {{ selectedPeer.UserIdentifier }}</li>
<li v-if="selectedPeer.Notes"><strong>{{ $t('modals.peer-view.notes') }}</strong>: {{ selectedPeer.Notes }}</li>
<li v-if="selectedPeer.ExpiresAt"><strong>{{ $t('modals.peer-view.expiry-status') }}</strong>: {{
selectedPeer.ExpiresAt }}</li> selectedPeer.ExpiresAt }}</li>
<li v-if="selectedPeer.Disabled">{{ $t('modals.peer-view.disabled-status') }}: {{ <li v-if="selectedPeer.Disabled"><strong>{{ $t('modals.peer-view.disabled-status') }}</strong>: {{
selectedPeer.DisabledReason }}</li> selectedPeer.DisabledReason }}</li>
</ul> </ul>
</div> </div>
<div class="col-md-4"> <div class="col-md-4" v-if="selectedInterface.Mode !== 'client'">
<img class="config-qr-img" :src="ConfigQrUrl()" loading="lazy" alt="Configuration QR Code"> <img class="config-qr-img" :src="ConfigQrUrl()" loading="lazy" alt="Configuration QR Code">
</div> </div>
</div> </div>
@@ -199,7 +207,7 @@ function ConfigQrUrl() {
</div> </div>
</div> </div>
</div> </div>
<div v-if="selectedInterface.Mode === 'server'" class="accordion-item"> <div v-if="selectedInterface.Mode !== 'client'" class="accordion-item">
<h2 class="accordion-header" id="headingConfig"> <h2 class="accordion-header" id="headingConfig">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
data-bs-target="#collapseConfig" aria-expanded="false" aria-controls="collapseConfig"> data-bs-target="#collapseConfig" aria-expanded="false" aria-controls="collapseConfig">
@@ -217,9 +225,9 @@ function ConfigQrUrl() {
</template> </template>
<template #footer> <template #footer>
<div class="flex-fill text-start"> <div class="flex-fill text-start">
<button @click.prevent="download" type="button" class="btn btn-primary me-1">{{ <button v-if="selectedInterface.Mode !== 'client'" @click.prevent="download" type="button" class="btn btn-primary me-1">{{
$t('modals.peer-view.button-download') }}</button> $t('modals.peer-view.button-download') }}</button>
<button @click.prevent="email" type="button" class="btn btn-primary me-1">{{ <button v-if="selectedInterface.Mode !== 'client'" @click.prevent="email" type="button" class="btn btn-primary me-1">{{
$t('modals.peer-view.button-email') }}</button> $t('modals.peer-view.button-email') }}</button>
</div> </div>
<button @click.prevent="close" type="button" class="btn btn-secondary">{{ $t('general.close') }}</button> <button @click.prevent="close" type="button" class="btn btn-secondary">{{ $t('general.close') }}</button>

View File

@@ -461,6 +461,8 @@
"section-config": "Konfiguration", "section-config": "Konfiguration",
"identifier": "Kennung", "identifier": "Kennung",
"ip": "IP-Adressen", "ip": "IP-Adressen",
"allowed-ip": "Erlaubte IP-Adressen",
"extra-allowed-ip": "Serverseitig erlaubte IP-Adressen",
"user": "Zugeordneter Benutzer", "user": "Zugeordneter Benutzer",
"notes": "Notizen", "notes": "Notizen",
"expiry-status": "Läuft ab am", "expiry-status": "Läuft ab am",
@@ -473,6 +475,8 @@
"handshake": "Letzter Handshake", "handshake": "Letzter Handshake",
"connected-since": "Verbunden seit", "connected-since": "Verbunden seit",
"endpoint": "Endpunkt", "endpoint": "Endpunkt",
"endpoint-key": "Öffentlicher Endpunkt-Schlüssel",
"keepalive": "Persistentes Keepalive",
"button-download": "Konfiguration herunterladen", "button-download": "Konfiguration herunterladen",
"button-email": "Konfiguration per E-Mail senden", "button-email": "Konfiguration per E-Mail senden",
"style-label": "Konfigurationsformat" "style-label": "Konfigurationsformat"

View File

@@ -462,6 +462,8 @@
"section-config": "Configuration", "section-config": "Configuration",
"identifier": "Identifier", "identifier": "Identifier",
"ip": "IP Addresses", "ip": "IP Addresses",
"allowed-ip": "Allowed IP Addresses",
"extra-allowed-ip": "Server Side Allowed IP Addresses",
"user": "Associated User", "user": "Associated User",
"notes": "Notes", "notes": "Notes",
"expiry-status": "Expires At", "expiry-status": "Expires At",
@@ -474,6 +476,8 @@
"handshake": "Last Handshake", "handshake": "Last Handshake",
"connected-since": "Connected since", "connected-since": "Connected since",
"endpoint": "Endpoint", "endpoint": "Endpoint",
"endpoint-key": "Endpoint Public Key",
"keepalive": "Persistent Keepalive",
"button-download": "Download configuration", "button-download": "Download configuration",
"button-email": "Send configuration via E-Mail", "button-email": "Send configuration via E-Mail",
"style-label": "Configuration Style" "style-label": "Configuration Style"

View File

@@ -308,22 +308,33 @@ func ConvertPhysicalPeer(pp *PhysicalPeer) *Peer {
func MergeToPhysicalPeer(pp *PhysicalPeer, p *Peer) { func MergeToPhysicalPeer(pp *PhysicalPeer, p *Peer) {
pp.Identifier = p.Identifier pp.Identifier = p.Identifier
pp.Endpoint = p.Endpoint.GetValue() pp.PresharedKey = p.PresharedKey
if p.Interface.Type == InterfaceTypeServer { pp.PublicKey = p.Interface.PublicKey
allowedIPs, _ := CidrsFromString(p.AllowedIPsStr.GetValue())
extraAllowedIPs, _ := CidrsFromString(p.ExtraAllowedIPsStr) switch p.Interface.Type {
pp.AllowedIPs = append(allowedIPs, extraAllowedIPs...) case InterfaceTypeClient: // this means that the corresponding interface in wgportal is a server interface
} else {
allowedIPs := make([]Cidr, len(p.Interface.Addresses)) allowedIPs := make([]Cidr, len(p.Interface.Addresses))
for i, ip := range p.Interface.Addresses { for i, ip := range p.Interface.Addresses {
allowedIPs[i] = ip.HostAddr() allowedIPs[i] = ip.HostAddr() // add the peer's host address to the allowed IPs
} }
extraAllowedIPs, _ := CidrsFromString(p.ExtraAllowedIPsStr) extraAllowedIPs, _ := CidrsFromString(p.ExtraAllowedIPsStr)
pp.AllowedIPs = append(allowedIPs, extraAllowedIPs...) pp.AllowedIPs = append(allowedIPs, extraAllowedIPs...)
case InterfaceTypeServer: // this means that the corresponding interface in wgportal is a client interface
allowedIPs, _ := CidrsFromString(p.AllowedIPsStr.GetValue())
extraAllowedIPs, _ := CidrsFromString(p.ExtraAllowedIPsStr)
pp.AllowedIPs = append(allowedIPs, extraAllowedIPs...)
pp.Endpoint = p.Endpoint.GetValue()
pp.PersistentKeepalive = p.PersistentKeepalive.GetValue()
case InterfaceTypeAny: // this means that the corresponding interface in wgportal has no specific type
allowedIPs := make([]Cidr, len(p.Interface.Addresses))
for i, ip := range p.Interface.Addresses {
allowedIPs[i] = ip.HostAddr() // add the peer's host address to the allowed IPs
}
extraAllowedIPs, _ := CidrsFromString(p.ExtraAllowedIPsStr)
pp.AllowedIPs = append(allowedIPs, extraAllowedIPs...)
pp.Endpoint = p.Endpoint.GetValue()
pp.PersistentKeepalive = p.PersistentKeepalive.GetValue()
} }
pp.PresharedKey = p.PresharedKey
pp.PublicKey = p.Interface.PublicKey
pp.PersistentKeepalive = p.PersistentKeepalive.GetValue()
switch pp.ImportSource { switch pp.ImportSource {
case ControllerTypeMikrotik: case ControllerTypeMikrotik: