support for raw-wireguard and wg-quick style peer configurations (#441) (#473)

This commit is contained in:
h44z 2025-06-29 19:47:53 +02:00 committed by GitHub
parent dd28a8dddf
commit f08740991b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 149 additions and 51 deletions

View File

@ -50,7 +50,7 @@ const selectedStats = computed(() => {
if (!s) { if (!s) {
if (!!props.peerId || props.peerId.length) { if (!!props.peerId || props.peerId.length) {
p = profile.Statistics(props.peerId) s = profile.Statistics(props.peerId)
} else { } else {
s = freshStats() // dummy stats to avoid 'undefined' exceptions s = freshStats() // dummy stats to avoid 'undefined' exceptions
} }
@ -79,13 +79,19 @@ const title = computed(() => {
} }
}) })
const configStyle = ref("wgquick")
watch(() => props.visible, async (newValue, oldValue) => { watch(() => props.visible, async (newValue, oldValue) => {
if (oldValue === false && newValue === true) { // if modal is shown if (oldValue === false && newValue === true) { // if modal is shown
await peers.LoadPeerConfig(selectedPeer.value.Identifier) await peers.LoadPeerConfig(selectedPeer.value.Identifier, configStyle.value)
configString.value = peers.configuration configString.value = peers.configuration
} }
} })
)
watch(() => configStyle.value, async () => {
await peers.LoadPeerConfig(selectedPeer.value.Identifier, configStyle.value)
configString.value = peers.configuration
})
function download() { function download() {
// credit: https://www.bitdegree.org/learn/javascript-download // credit: https://www.bitdegree.org/learn/javascript-download
@ -103,7 +109,7 @@ function download() {
} }
function email() { function email() {
peers.MailPeerConfig(settings.Setting("MailLinkOnly"), [selectedPeer.value.Identifier]).catch(e => { peers.MailPeerConfig(settings.Setting("MailLinkOnly"), configStyle.value, [selectedPeer.value.Identifier]).catch(e => {
notify({ notify({
title: "Failed to send mail with peer configuration!", title: "Failed to send mail with peer configuration!",
text: e.toString(), text: e.toString(),
@ -114,7 +120,7 @@ function email() {
function ConfigQrUrl() { function ConfigQrUrl() {
if (props.peerId.length) { if (props.peerId.length) {
return apiWrapper.url(`/peer/config-qr/${base64_url_encode(props.peerId)}`) return apiWrapper.url(`/peer/config-qr/${base64_url_encode(props.peerId)}?style=${configStyle.value}`)
} }
return '' return ''
} }
@ -124,6 +130,15 @@ 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">
<span class="me-2">{{ $t('modals.peer-view.style-label') }}: </span>
<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">
<label class="btn btn-outline-primary btn-sm" for="raw">Raw</label>
<input type="radio" class="btn-check" name="configstyle" id="wgquick" value="wgquick" autocomplete="off" checked="" v-model="configStyle">
<label class="btn btn-outline-primary btn-sm" for="wgquick">WG-Quick</label>
</div>
</div>
<div class="accordion" id="peerInformation"> <div class="accordion" id="peerInformation">
<div class="accordion-item"> <div class="accordion-item">
<h2 class="accordion-header"> <h2 class="accordion-header">
@ -213,6 +228,14 @@ function ConfigQrUrl() {
</template> </template>
</Modal></template> </Modal></template>
<style>.config-qr-img { <style>
.config-qr-img {
max-width: 100%; max-width: 100%;
}</style> }
.btn-switch-group .btn {
border-width: 1px;
padding: 5px;
line-height: 1;
}
</style>

View File

@ -467,7 +467,8 @@
"connected-since": "Verbunden seit", "connected-since": "Verbunden seit",
"endpoint": "Endpunkt", "endpoint": "Endpunkt",
"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"
}, },
"peer-edit": { "peer-edit": {
"headline-edit-peer": "Peer bearbeiten:", "headline-edit-peer": "Peer bearbeiten:",

View File

@ -468,7 +468,8 @@
"connected-since": "Connected since", "connected-since": "Connected since",
"endpoint": "Endpoint", "endpoint": "Endpoint",
"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"
}, },
"peer-edit": { "peer-edit": {
"headline-edit-peer": "Edit peer:", "headline-edit-peer": "Edit peer:",

View File

@ -142,8 +142,8 @@ export const peerStore = defineStore('peers', {
}) })
}) })
}, },
async MailPeerConfig(linkOnly, ids) { async MailPeerConfig(linkOnly, style, ids) {
return apiWrapper.post(`${baseUrl}/config-mail`, { return apiWrapper.post(`${baseUrl}/config-mail?style=${style}`, {
Identifiers: ids, Identifiers: ids,
LinkOnly: linkOnly LinkOnly: linkOnly
}) })
@ -158,8 +158,8 @@ export const peerStore = defineStore('peers', {
throw new Error(error) throw new Error(error)
}) })
}, },
async LoadPeerConfig(id) { async LoadPeerConfig(id, style) {
return apiWrapper.get(`${baseUrl}/config/${base64_url_encode(id)}`) return apiWrapper.get(`${baseUrl}/config/${base64_url_encode(id)}?style=${style}`)
.then(this.setPeerConfig) .then(this.setPeerConfig)
.catch(error => { .catch(error => {
this.configuration = "" this.configuration = ""

View File

@ -819,6 +819,12 @@
"schema": { "schema": {
"$ref": "#/definitions/model.PeerMailRequest" "$ref": "#/definitions/model.PeerMailRequest"
} }
},
{
"type": "string",
"description": "The configuration style",
"name": "style",
"in": "query"
} }
], ],
"responses": { "responses": {
@ -858,6 +864,12 @@
"name": "id", "name": "id",
"in": "path", "in": "path",
"required": true "required": true
},
{
"type": "string",
"description": "The configuration style",
"name": "style",
"in": "query"
} }
], ],
"responses": { "responses": {
@ -899,6 +911,12 @@
"name": "id", "name": "id",
"in": "path", "in": "path",
"required": true "required": true
},
{
"type": "string",
"description": "The configuration style",
"name": "style",
"in": "query"
} }
], ],
"responses": { "responses": {

View File

@ -1072,6 +1072,10 @@ paths:
required: true required: true
schema: schema:
$ref: '#/definitions/model.PeerMailRequest' $ref: '#/definitions/model.PeerMailRequest'
- description: The configuration style
in: query
name: style
type: string
produces: produces:
- application/json - application/json
responses: responses:
@ -1097,6 +1101,10 @@ paths:
name: id name: id
required: true required: true
type: string type: string
- description: The configuration style
in: query
name: style
type: string
produces: produces:
- image/png - image/png
- application/json - application/json
@ -1125,6 +1133,10 @@ paths:
name: id name: id
required: true required: true
type: string type: string
- description: The configuration style
in: query
name: style
type: string
produces: produces:
- application/json - application/json
responses: responses:

View File

@ -27,12 +27,12 @@ type PeerServicePeerManager interface {
} }
type PeerServiceConfigFileManager interface { type PeerServiceConfigFileManager interface {
GetPeerConfig(ctx context.Context, id domain.PeerIdentifier) (io.Reader, error) GetPeerConfig(ctx context.Context, id domain.PeerIdentifier, style string) (io.Reader, error)
GetPeerConfigQrCode(ctx context.Context, id domain.PeerIdentifier) (io.Reader, error) GetPeerConfigQrCode(ctx context.Context, id domain.PeerIdentifier, style string) (io.Reader, error)
} }
type PeerServiceMailManager interface { type PeerServiceMailManager interface {
SendPeerEmail(ctx context.Context, linkOnly bool, peers ...domain.PeerIdentifier) error SendPeerEmail(ctx context.Context, linkOnly bool, style string, peers ...domain.PeerIdentifier) error
} }
// endregion dependencies // endregion dependencies
@ -95,16 +95,24 @@ func (p PeerService) DeletePeer(ctx context.Context, id domain.PeerIdentifier) e
return p.peers.DeletePeer(ctx, id) return p.peers.DeletePeer(ctx, id)
} }
func (p PeerService) GetPeerConfig(ctx context.Context, id domain.PeerIdentifier) (io.Reader, error) { func (p PeerService) GetPeerConfig(ctx context.Context, id domain.PeerIdentifier, style string) (io.Reader, error) {
return p.configFile.GetPeerConfig(ctx, id) return p.configFile.GetPeerConfig(ctx, id, style)
} }
func (p PeerService) GetPeerConfigQrCode(ctx context.Context, id domain.PeerIdentifier) (io.Reader, error) { func (p PeerService) GetPeerConfigQrCode(ctx context.Context, id domain.PeerIdentifier, style string) (
return p.configFile.GetPeerConfigQrCode(ctx, id) io.Reader,
error,
) {
return p.configFile.GetPeerConfigQrCode(ctx, id, style)
} }
func (p PeerService) SendPeerEmail(ctx context.Context, linkOnly bool, peers ...domain.PeerIdentifier) error { func (p PeerService) SendPeerEmail(
return p.mailer.SendPeerEmail(ctx, linkOnly, peers...) ctx context.Context,
linkOnly bool,
style string,
peers ...domain.PeerIdentifier,
) error {
return p.mailer.SendPeerEmail(ctx, linkOnly, style, peers...)
} }
func (p PeerService) GetPeerStats(ctx context.Context, id domain.InterfaceIdentifier) ([]domain.PeerStatus, error) { func (p PeerService) GetPeerStats(ctx context.Context, id domain.InterfaceIdentifier) ([]domain.PeerStatus, error) {

View File

@ -34,11 +34,11 @@ type PeerService interface {
// DeletePeer deletes the peer with the given id. // DeletePeer deletes the peer with the given id.
DeletePeer(ctx context.Context, id domain.PeerIdentifier) error DeletePeer(ctx context.Context, id domain.PeerIdentifier) error
// GetPeerConfig returns the peer configuration for the given id. // GetPeerConfig returns the peer configuration for the given id.
GetPeerConfig(ctx context.Context, id domain.PeerIdentifier) (io.Reader, error) GetPeerConfig(ctx context.Context, id domain.PeerIdentifier, style string) (io.Reader, error)
// GetPeerConfigQrCode returns the peer configuration as qr code for the given id. // GetPeerConfigQrCode returns the peer configuration as qr code for the given id.
GetPeerConfigQrCode(ctx context.Context, id domain.PeerIdentifier) (io.Reader, error) GetPeerConfigQrCode(ctx context.Context, id domain.PeerIdentifier, style string) (io.Reader, error)
// SendPeerEmail sends the peer configuration via email. // SendPeerEmail sends the peer configuration via email.
SendPeerEmail(ctx context.Context, linkOnly bool, peers ...domain.PeerIdentifier) error SendPeerEmail(ctx context.Context, linkOnly bool, style string, peers ...domain.PeerIdentifier) error
// GetPeerStats returns the peer stats for the given interface. // GetPeerStats returns the peer stats for the given interface.
GetPeerStats(ctx context.Context, id domain.InterfaceIdentifier) ([]domain.PeerStatus, error) GetPeerStats(ctx context.Context, id domain.InterfaceIdentifier) ([]domain.PeerStatus, error)
} }
@ -355,6 +355,7 @@ func (e PeerEndpoint) handleDelete() http.HandlerFunc {
// @Summary Get peer configuration as string. // @Summary Get peer configuration as string.
// @Produce json // @Produce json
// @Param id path string true "The peer identifier" // @Param id path string true "The peer identifier"
// @Param style query string false "The configuration style"
// @Success 200 {object} string // @Success 200 {object} string
// @Failure 400 {object} model.Error // @Failure 400 {object} model.Error
// @Failure 500 {object} model.Error // @Failure 500 {object} model.Error
@ -369,7 +370,9 @@ func (e PeerEndpoint) handleConfigGet() http.HandlerFunc {
return return
} }
configTxt, err := e.peerService.GetPeerConfig(r.Context(), domain.PeerIdentifier(id)) configStyle := e.getConfigStyle(r)
configTxt, err := e.peerService.GetPeerConfig(r.Context(), domain.PeerIdentifier(id), configStyle)
if err != nil { if err != nil {
respond.JSON(w, http.StatusInternalServerError, model.Error{ respond.JSON(w, http.StatusInternalServerError, model.Error{
Code: http.StatusInternalServerError, Message: err.Error(), Code: http.StatusInternalServerError, Message: err.Error(),
@ -397,6 +400,7 @@ func (e PeerEndpoint) handleConfigGet() http.HandlerFunc {
// @Produce png // @Produce png
// @Produce json // @Produce json
// @Param id path string true "The peer identifier" // @Param id path string true "The peer identifier"
// @Param style query string false "The configuration style"
// @Success 200 {file} binary // @Success 200 {file} binary
// @Failure 400 {object} model.Error // @Failure 400 {object} model.Error
// @Failure 500 {object} model.Error // @Failure 500 {object} model.Error
@ -411,7 +415,9 @@ func (e PeerEndpoint) handleQrCodeGet() http.HandlerFunc {
return return
} }
configQr, err := e.peerService.GetPeerConfigQrCode(r.Context(), domain.PeerIdentifier(id)) configStyle := e.getConfigStyle(r)
configQr, err := e.peerService.GetPeerConfigQrCode(r.Context(), domain.PeerIdentifier(id), configStyle)
if err != nil { if err != nil {
respond.JSON(w, http.StatusInternalServerError, model.Error{ respond.JSON(w, http.StatusInternalServerError, model.Error{
Code: http.StatusInternalServerError, Message: err.Error(), Code: http.StatusInternalServerError, Message: err.Error(),
@ -438,6 +444,7 @@ func (e PeerEndpoint) handleQrCodeGet() http.HandlerFunc {
// @Summary Send peer configuration via email. // @Summary Send peer configuration via email.
// @Produce json // @Produce json
// @Param request body model.PeerMailRequest true "The peer mail request data" // @Param request body model.PeerMailRequest true "The peer mail request data"
// @Param style query string false "The configuration style"
// @Success 204 "No content if mail sending was successful" // @Success 204 "No content if mail sending was successful"
// @Failure 400 {object} model.Error // @Failure 400 {object} model.Error
// @Failure 500 {object} model.Error // @Failure 500 {object} model.Error
@ -460,11 +467,13 @@ func (e PeerEndpoint) handleEmailPost() http.HandlerFunc {
return return
} }
configStyle := e.getConfigStyle(r)
peerIds := make([]domain.PeerIdentifier, len(req.Identifiers)) peerIds := make([]domain.PeerIdentifier, len(req.Identifiers))
for i := range req.Identifiers { for i := range req.Identifiers {
peerIds[i] = domain.PeerIdentifier(req.Identifiers[i]) peerIds[i] = domain.PeerIdentifier(req.Identifiers[i])
} }
if err := e.peerService.SendPeerEmail(r.Context(), req.LinkOnly, peerIds...); err != nil { if err := e.peerService.SendPeerEmail(r.Context(), req.LinkOnly, configStyle, peerIds...); err != nil {
respond.JSON(w, http.StatusInternalServerError, respond.JSON(w, http.StatusInternalServerError,
model.Error{Code: http.StatusInternalServerError, Message: err.Error()}) model.Error{Code: http.StatusInternalServerError, Message: err.Error()})
return return
@ -504,3 +513,11 @@ func (e PeerEndpoint) handleStatsGet() http.HandlerFunc {
respond.JSON(w, http.StatusOK, model.NewPeerStats(e.cfg.Statistics.CollectPeerData, stats)) respond.JSON(w, http.StatusOK, model.NewPeerStats(e.cfg.Statistics.CollectPeerData, stats))
} }
} }
func (e PeerEndpoint) getConfigStyle(r *http.Request) string {
configStyle := request.QueryDefault(r, "style", domain.ConfigStyleWgQuick)
if configStyle != domain.ConfigStyleWgQuick && configStyle != domain.ConfigStyleRaw {
configStyle = domain.ConfigStyleWgQuick // default to wg-quick style
}
return configStyle
}

View File

@ -23,8 +23,8 @@ type ProvisioningServicePeerManagerRepo interface {
} }
type ProvisioningServiceConfigFileManagerRepo interface { type ProvisioningServiceConfigFileManagerRepo interface {
GetPeerConfig(ctx context.Context, id domain.PeerIdentifier) (io.Reader, error) GetPeerConfig(ctx context.Context, id domain.PeerIdentifier, style string) (io.Reader, error)
GetPeerConfigQrCode(ctx context.Context, id domain.PeerIdentifier) (io.Reader, error) GetPeerConfigQrCode(ctx context.Context, id domain.PeerIdentifier, style string) (io.Reader, error)
} }
type ProvisioningService struct { type ProvisioningService struct {
@ -96,7 +96,7 @@ func (p ProvisioningService) GetPeerConfig(ctx context.Context, peerId domain.Pe
return nil, err return nil, err
} }
peerCfgReader, err := p.configFiles.GetPeerConfig(ctx, peer.Identifier) peerCfgReader, err := p.configFiles.GetPeerConfig(ctx, peer.Identifier, domain.ConfigStyleWgQuick)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -119,7 +119,7 @@ func (p ProvisioningService) GetPeerQrPng(ctx context.Context, peerId domain.Pee
return nil, err return nil, err
} }
peerCfgQrReader, err := p.configFiles.GetPeerConfigQrCode(ctx, peer.Identifier) peerCfgQrReader, err := p.configFiles.GetPeerConfigQrCode(ctx, peer.Identifier, domain.ConfigStyleWgQuick)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -46,7 +46,7 @@ type TemplateRenderer interface {
// GetInterfaceConfig returns the configuration file for the given interface. // GetInterfaceConfig returns the configuration file for the given interface.
GetInterfaceConfig(iface *domain.Interface, peers []domain.Peer) (io.Reader, error) GetInterfaceConfig(iface *domain.Interface, peers []domain.Peer) (io.Reader, error)
// GetPeerConfig returns the configuration file for the given peer. // GetPeerConfig returns the configuration file for the given peer.
GetPeerConfig(peer *domain.Peer) (io.Reader, error) GetPeerConfig(peer *domain.Peer, style string) (io.Reader, error)
} }
type EventBus interface { type EventBus interface {
@ -186,7 +186,7 @@ func (m Manager) GetInterfaceConfig(ctx context.Context, id domain.InterfaceIden
// GetPeerConfig returns the configuration file for the given peer. // GetPeerConfig returns the configuration file for the given peer.
// The file is structured in wg-quick format. // The file is structured in wg-quick format.
func (m Manager) GetPeerConfig(ctx context.Context, id domain.PeerIdentifier) (io.Reader, error) { func (m Manager) GetPeerConfig(ctx context.Context, id domain.PeerIdentifier, style string) (io.Reader, error) {
peer, err := m.wg.GetPeer(ctx, id) peer, err := m.wg.GetPeer(ctx, id)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to fetch peer %s: %w", id, err) return nil, fmt.Errorf("failed to fetch peer %s: %w", id, err)
@ -196,11 +196,11 @@ func (m Manager) GetPeerConfig(ctx context.Context, id domain.PeerIdentifier) (i
return nil, err return nil, err
} }
return m.tplHandler.GetPeerConfig(peer) return m.tplHandler.GetPeerConfig(peer, style)
} }
// GetPeerConfigQrCode returns a QR code image containing the configuration for the given peer. // GetPeerConfigQrCode returns a QR code image containing the configuration for the given peer.
func (m Manager) GetPeerConfigQrCode(ctx context.Context, id domain.PeerIdentifier) (io.Reader, error) { func (m Manager) GetPeerConfigQrCode(ctx context.Context, id domain.PeerIdentifier, style string) (io.Reader, error) {
peer, err := m.wg.GetPeer(ctx, id) peer, err := m.wg.GetPeer(ctx, id)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to fetch peer %s: %w", id, err) return nil, fmt.Errorf("failed to fetch peer %s: %w", id, err)
@ -210,7 +210,7 @@ func (m Manager) GetPeerConfigQrCode(ctx context.Context, id domain.PeerIdentifi
return nil, err return nil, err
} }
cfgData, err := m.tplHandler.GetPeerConfig(peer) cfgData, err := m.tplHandler.GetPeerConfig(peer, style)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to get peer config for %s: %w", id, err) return nil, fmt.Errorf("failed to get peer config for %s: %w", id, err)
} }

View File

@ -55,11 +55,12 @@ func (c TemplateHandler) GetInterfaceConfig(cfg *domain.Interface, peers []domai
} }
// GetPeerConfig returns the rendered configuration file for a WireGuard peer. // GetPeerConfig returns the rendered configuration file for a WireGuard peer.
func (c TemplateHandler) GetPeerConfig(peer *domain.Peer) (io.Reader, error) { func (c TemplateHandler) GetPeerConfig(peer *domain.Peer, style string) (io.Reader, error) {
var tplBuff bytes.Buffer var tplBuff bytes.Buffer
err := c.templates.ExecuteTemplate(&tplBuff, "wg_peer.tpl", map[string]any{ err := c.templates.ExecuteTemplate(&tplBuff, "wg_peer.tpl", map[string]any{
"Peer": peer, "Style": style,
"Peer": peer,
"Portal": map[string]any{ "Portal": map[string]any{
"Version": "unknown", "Version": "unknown",
}, },

View File

@ -1,6 +1,8 @@
# AUTOGENERATED FILE - DO NOT EDIT # AUTOGENERATED FILE - DO NOT EDIT
# This file uses wg-quick format. # This file uses {{ .Style }} format.
{{- if eq .Style "wgquick"}}
# See https://man7.org/linux/man-pages/man8/wg-quick.8.html#CONFIGURATION # See https://man7.org/linux/man-pages/man8/wg-quick.8.html#CONFIGURATION
{{- end}}
# Lines starting with the -WGP- tag are used by # Lines starting with the -WGP- tag are used by
# the WireGuard Portal configuration parser. # the WireGuard Portal configuration parser.
@ -21,22 +23,27 @@
# Core settings # Core settings
PrivateKey = {{ .Peer.Interface.KeyPair.PrivateKey }} PrivateKey = {{ .Peer.Interface.KeyPair.PrivateKey }}
{{- if eq .Style "wgquick"}}
Address = {{ CidrsToString .Peer.Interface.Addresses }} Address = {{ CidrsToString .Peer.Interface.Addresses }}
{{- end}}
# Misc. settings (optional) # Misc. settings (optional)
{{- if eq .Style "wgquick"}}
{{- if .Peer.Interface.DnsStr.GetValue}} {{- if .Peer.Interface.DnsStr.GetValue}}
DNS = {{ .Peer.Interface.DnsStr.GetValue }} {{- if .Peer.Interface.DnsSearchStr.GetValue}}, {{ .Peer.Interface.DnsSearchStr.GetValue }} {{- end}} DNS = {{ .Peer.Interface.DnsStr.GetValue }} {{- if .Peer.Interface.DnsSearchStr.GetValue}}, {{ .Peer.Interface.DnsSearchStr.GetValue }} {{- end}}
{{- end}} {{- end}}
{{- if ne .Peer.Interface.Mtu.GetValue 0}} {{- if ne .Peer.Interface.Mtu.GetValue 0}}
MTU = {{ .Peer.Interface.Mtu.GetValue }} MTU = {{ .Peer.Interface.Mtu.GetValue }}
{{- end}} {{- end}}
{{- if ne .Peer.Interface.FirewallMark.GetValue 0}}
FwMark = {{ .Peer.Interface.FirewallMark.GetValue }}
{{- end}}
{{- if ne .Peer.Interface.RoutingTable.GetValue ""}} {{- if ne .Peer.Interface.RoutingTable.GetValue ""}}
Table = {{ .Peer.Interface.RoutingTable.GetValue }} Table = {{ .Peer.Interface.RoutingTable.GetValue }}
{{- end}} {{- end}}
{{- end}}
{{- if ne .Peer.Interface.FirewallMark.GetValue 0}}
FwMark = {{ .Peer.Interface.FirewallMark.GetValue }}
{{- end}}
{{- if eq .Style "wgquick"}}
# Interface hooks (optional) # Interface hooks (optional)
{{- if .Peer.Interface.PreUp.GetValue}} {{- if .Peer.Interface.PreUp.GetValue}}
PreUp = {{ .Peer.Interface.PreUp.GetValue }} PreUp = {{ .Peer.Interface.PreUp.GetValue }}
@ -50,6 +57,7 @@ PreDown = {{ .Peer.Interface.PreDown.GetValue }}
{{- if .Peer.Interface.PostDown.GetValue}} {{- if .Peer.Interface.PostDown.GetValue}}
PostDown = {{ .Peer.Interface.PostDown.GetValue }} PostDown = {{ .Peer.Interface.PostDown.GetValue }}
{{- end}} {{- end}}
{{- end}}
[Peer] [Peer]
PublicKey = {{ .Peer.EndpointPublicKey.GetValue }} PublicKey = {{ .Peer.EndpointPublicKey.GetValue }}

View File

@ -21,9 +21,9 @@ type ConfigFileManager interface {
// GetInterfaceConfig returns the configuration for the given interface. // GetInterfaceConfig returns the configuration for the given interface.
GetInterfaceConfig(ctx context.Context, id domain.InterfaceIdentifier) (io.Reader, error) GetInterfaceConfig(ctx context.Context, id domain.InterfaceIdentifier) (io.Reader, error)
// GetPeerConfig returns the configuration for the given peer. // GetPeerConfig returns the configuration for the given peer.
GetPeerConfig(ctx context.Context, id domain.PeerIdentifier) (io.Reader, error) GetPeerConfig(ctx context.Context, id domain.PeerIdentifier, style string) (io.Reader, error)
// GetPeerConfigQrCode returns the QR code for the given peer. // GetPeerConfigQrCode returns the QR code for the given peer.
GetPeerConfigQrCode(ctx context.Context, id domain.PeerIdentifier) (io.Reader, error) GetPeerConfigQrCode(ctx context.Context, id domain.PeerIdentifier, style string) (io.Reader, error)
} }
type UserDatabaseRepo interface { type UserDatabaseRepo interface {
@ -89,7 +89,7 @@ func NewMailManager(
} }
// SendPeerEmail sends an email to the user linked to the given peers. // SendPeerEmail sends an email to the user linked to the given peers.
func (m Manager) SendPeerEmail(ctx context.Context, linkOnly bool, peers ...domain.PeerIdentifier) error { func (m Manager) SendPeerEmail(ctx context.Context, linkOnly bool, style string, peers ...domain.PeerIdentifier) error {
for _, peerId := range peers { for _, peerId := range peers {
peer, err := m.wg.GetPeer(ctx, peerId) peer, err := m.wg.GetPeer(ctx, peerId)
if err != nil { if err != nil {
@ -123,7 +123,7 @@ func (m Manager) SendPeerEmail(ctx context.Context, linkOnly bool, peers ...doma
continue continue
} }
err = m.sendPeerEmail(ctx, linkOnly, user, peer) err = m.sendPeerEmail(ctx, linkOnly, style, user, peer)
if err != nil { if err != nil {
return fmt.Errorf("failed to send peer email for %s: %w", peerId, err) return fmt.Errorf("failed to send peer email for %s: %w", peerId, err)
} }
@ -132,7 +132,13 @@ func (m Manager) SendPeerEmail(ctx context.Context, linkOnly bool, peers ...doma
return nil return nil
} }
func (m Manager) sendPeerEmail(ctx context.Context, linkOnly bool, user *domain.User, peer *domain.Peer) error { func (m Manager) sendPeerEmail(
ctx context.Context,
linkOnly bool,
style string,
user *domain.User,
peer *domain.Peer,
) error {
qrName := "WireGuardQRCode.png" qrName := "WireGuardQRCode.png"
configName := peer.GetConfigFileName() configName := peer.GetConfigFileName()
@ -148,12 +154,12 @@ func (m Manager) sendPeerEmail(ctx context.Context, linkOnly bool, user *domain.
} }
} else { } else {
peerConfig, err := m.configFiles.GetPeerConfig(ctx, peer.Identifier) peerConfig, err := m.configFiles.GetPeerConfig(ctx, peer.Identifier, style)
if err != nil { if err != nil {
return fmt.Errorf("failed to fetch peer config for %s: %w", peer.Identifier, err) return fmt.Errorf("failed to fetch peer config for %s: %w", peer.Identifier, err)
} }
peerConfigQr, err := m.configFiles.GetPeerConfigQrCode(ctx, peer.Identifier) peerConfigQr, err := m.configFiles.GetPeerConfigQrCode(ctx, peer.Identifier, style)
if err != nil { if err != nil {
return fmt.Errorf("failed to fetch peer config QR code for %s: %w", peer.Identifier, err) return fmt.Errorf("failed to fetch peer config QR code for %s: %w", peer.Identifier, err)
} }

View File

@ -62,4 +62,7 @@ const (
LockedReasonAdmin = "locked by admin" LockedReasonAdmin = "locked by admin"
LockedReasonApi = "locked by admin" LockedReasonApi = "locked by admin"
ConfigStyleRaw = "raw"
ConfigStyleWgQuick = "wgquick"
) )