mirror of
https://github.com/h44z/wg-portal.git
synced 2025-08-09 15:02:24 +00:00
creation of multiple peers
This commit is contained in:
parent
4b05f1840c
commit
85438d1dce
97
frontend/src/components/PeerMultiCreateModal.vue
Normal file
97
frontend/src/components/PeerMultiCreateModal.vue
Normal file
@ -0,0 +1,97 @@
|
||||
<script setup>
|
||||
import Modal from "./Modal.vue";
|
||||
import {peerStore} from "@/stores/peers";
|
||||
import {interfaceStore} from "@/stores/interfaces";
|
||||
import {computed, ref, watch} from "vue";
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { notify } from "@kyvg/vue3-notification";
|
||||
import Vue3TagsInput from "vue3-tags-input";
|
||||
import { freshInterface } from '@/helpers/models';
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const peers = peerStore()
|
||||
const interfaces = interfaceStore()
|
||||
|
||||
const props = defineProps({
|
||||
visible: Boolean,
|
||||
})
|
||||
|
||||
const emit = defineEmits(['close'])
|
||||
|
||||
const selectedInterface = computed(() => {
|
||||
let i = interfaces.GetSelected;
|
||||
|
||||
if (!i) {
|
||||
i = freshInterface() // dummy interface to avoid 'undefined' exceptions
|
||||
}
|
||||
|
||||
return i
|
||||
})
|
||||
|
||||
function freshForm() {
|
||||
return {
|
||||
Identifiers: [],
|
||||
Suffix: "",
|
||||
}
|
||||
}
|
||||
|
||||
const formData = ref(freshForm())
|
||||
|
||||
function close() {
|
||||
formData.value = freshForm()
|
||||
emit('close')
|
||||
}
|
||||
|
||||
function handleChangeUserIdentifiers(tags) {
|
||||
formData.value.Identifiers = tags
|
||||
}
|
||||
|
||||
async function save() {
|
||||
if (formData.value.Identifiers.length === 0) {
|
||||
notify({
|
||||
title: "Missing Identifiers",
|
||||
text: "At least one identifier is required to create a new peer.",
|
||||
type: 'error',
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await peers.CreateMultiplePeers(selectedInterface.value.Identifier, formData.value)
|
||||
close()
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
notify({
|
||||
title: "Backend Connection Failure",
|
||||
text: "Failed to create peers!",
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Modal :title="t('modals.peerscreate.title')" :visible="visible" @close="close">
|
||||
<template #default>
|
||||
<fieldset>
|
||||
<div class="form-group">
|
||||
<label class="form-label mt-4">{{ $t('modals.peerscreate.identifiers') }}</label>
|
||||
<vue3-tags-input class="form-control" :tags="formData.Identifiers"
|
||||
:placeholder="t('modals.peerscreate.identifiers.placeholder')"
|
||||
:add-tag-on-keys="[13, 188, 32, 9]"
|
||||
@on-tags-changed="handleChangeUserIdentifiers"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label mt-4">{{ $t('modals.peerscreate.peernamesuffix') }}</label>
|
||||
<input type="text" class="form-control" :placeholder="t('modals.peerscreate.peernamesuffix.placeholder')" v-model="formData.Suffix">
|
||||
</div>
|
||||
</fieldset>
|
||||
</template>
|
||||
<template #footer>
|
||||
<button class="btn btn-primary me-1" type="button" @click.prevent="save">Create</button>
|
||||
<button class="btn btn-secondary" type="button" @click.prevent="close">Cancel</button>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
@ -167,6 +167,19 @@ export const peerStore = defineStore({
|
||||
throw new Error(error)
|
||||
})
|
||||
},
|
||||
async CreateMultiplePeers(interfaceId, formData) {
|
||||
this.fetching = true
|
||||
return apiWrapper.post(`${baseUrl}/iface/${base64_url_encode(interfaceId)}/multiplenew`, formData)
|
||||
.then(peers => {
|
||||
this.peers.push(...peers)
|
||||
this.fetching = false
|
||||
})
|
||||
.catch(error => {
|
||||
this.fetching = false
|
||||
console.log(error)
|
||||
throw new Error(error)
|
||||
})
|
||||
},
|
||||
async LoadPeers(interfaceId) {
|
||||
// if no interfaceId is given, use the currently selected interface
|
||||
if (!interfaceId) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
<script setup>
|
||||
import PeerViewModal from "../components/PeerViewModal.vue";
|
||||
import PeerEditModal from "../components/PeerEditModal.vue";
|
||||
import PeerMultiCreateModal from "../components/PeerMultiCreateModal.vue";
|
||||
import InterfaceEditModal from "../components/InterfaceEditModal.vue";
|
||||
import InterfaceViewModal from "../components/InterfaceViewModal.vue";
|
||||
|
||||
@ -13,6 +14,7 @@ const peers = peerStore()
|
||||
|
||||
const viewedPeerId = ref("")
|
||||
const editPeerId = ref("")
|
||||
const multiCreatePeerId = ref("")
|
||||
const editInterfaceId = ref("")
|
||||
const viewedInterfaceId = ref("")
|
||||
|
||||
@ -51,6 +53,7 @@ onMounted(async () => {
|
||||
<template>
|
||||
<PeerViewModal :peerId="viewedPeerId" :visible="viewedPeerId!==''" @close="viewedPeerId=''"></PeerViewModal>
|
||||
<PeerEditModal :peerId="editPeerId" :visible="editPeerId!==''" @close="editPeerId=''"></PeerEditModal>
|
||||
<PeerMultiCreateModal :visible="multiCreatePeerId!==''" @close="multiCreatePeerId=''"></PeerMultiCreateModal>
|
||||
<InterfaceEditModal :interfaceId="editInterfaceId" :visible="editInterfaceId!==''" @close="editInterfaceId=''"></InterfaceEditModal>
|
||||
<InterfaceViewModal :interfaceId="viewedInterfaceId" :visible="viewedInterfaceId!==''" @close="viewedInterfaceId=''"></InterfaceViewModal>
|
||||
|
||||
@ -272,7 +275,7 @@ onMounted(async () => {
|
||||
</div>
|
||||
<div class="col-12 col-lg-3 text-lg-end">
|
||||
<a v-if="interfaces.GetSelected.Mode==='server' && peers.Count!==0" class="btn btn-primary" href="#" title="Send mail to all peers"><i class="fa fa-paper-plane"></i></a>
|
||||
<a class="btn btn-primary ms-2" href="#" title="Add multiple peers"><i class="fa fa-plus me-1"></i><i class="fa fa-users"></i></a>
|
||||
<a class="btn btn-primary ms-2" href="#" title="Add multiple peers" @click.prevent="multiCreatePeerId='#NEW#'"><i class="fa fa-plus me-1"></i><i class="fa fa-users"></i></a>
|
||||
<a class="btn btn-primary ms-2" href="#" title="Add a peer" @click.prevent="editPeerId='#NEW#'"><i class="fa fa-plus me-1"></i><i class="fa fa-user"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -136,6 +136,8 @@ func NewDatabase(cfg config.DatabaseConfig) (*gorm.DB, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open sqlite database: %w", err)
|
||||
}
|
||||
sqlDB, _ := gormDb.DB()
|
||||
sqlDB.SetMaxOpenConns(1)
|
||||
}
|
||||
|
||||
return gormDb, nil
|
||||
|
@ -251,6 +251,38 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/interface/config/{id}": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Interface"
|
||||
],
|
||||
"summary": "Get interface configuration as string.",
|
||||
"operationId": "interfaces_handleConfigGet",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Error"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/interface/get/{id}": {
|
||||
"get": {
|
||||
"produces": [
|
||||
@ -429,6 +461,42 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Interface"
|
||||
],
|
||||
"summary": "Delete the interface record.",
|
||||
"operationId": "interfaces_handleDelete",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "The interface identifier",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "No content if deletion was successful"
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Error"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/now": {
|
||||
@ -458,7 +526,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/peer/all/{id}": {
|
||||
"/peer/config-qr/{id}": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
@ -466,16 +534,19 @@
|
||||
"tags": [
|
||||
"Peer"
|
||||
],
|
||||
"summary": "Get peers for the given interface.",
|
||||
"operationId": "peers_handlePeersGet",
|
||||
"summary": "Get peer configuration as qr code.",
|
||||
"operationId": "peers_handleQrCodeGet",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/model.Peer"
|
||||
}
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Error"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
@ -487,7 +558,299 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/users": {
|
||||
"/peer/config/{id}": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Peer"
|
||||
],
|
||||
"summary": "Get peer configuration as string.",
|
||||
"operationId": "peers_handleConfigGet",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Error"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/peer/iface/{iface}/all": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Peer"
|
||||
],
|
||||
"summary": "Get peers for the given interface.",
|
||||
"operationId": "peers_handleAllGet",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "The interface identifier",
|
||||
"name": "iface",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/model.Peer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Error"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/peer/iface/{iface}/new": {
|
||||
"post": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Peer"
|
||||
],
|
||||
"summary": "Prepare a new peer for the given interface.",
|
||||
"operationId": "peers_handleCreatePost",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "The interface identifier",
|
||||
"name": "iface",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "The peer data",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Peer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Peer"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Error"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/peer/iface/{iface}/prepare": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Peer"
|
||||
],
|
||||
"summary": "Prepare a new peer for the given interface.",
|
||||
"operationId": "peers_handlePrepareGet",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "The interface identifier",
|
||||
"name": "iface",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Peer"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Error"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/peer/{id}": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Peer"
|
||||
],
|
||||
"summary": "Get peer for the given identifier.",
|
||||
"operationId": "peers_handleSingleGet",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "The peer identifier",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Peer"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Error"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"put": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Peer"
|
||||
],
|
||||
"summary": "Update the given peer record.",
|
||||
"operationId": "peers_handleUpdatePut",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "The peer identifier",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "The peer data",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Peer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Peer"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Error"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Peer"
|
||||
],
|
||||
"summary": "Delete the peer record.",
|
||||
"operationId": "peers_handleDelete",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "The peer identifier",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "No content if deletion was successful"
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Error"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user/all": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
@ -516,7 +879,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/users/new": {
|
||||
"/user/new": {
|
||||
"post": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
@ -559,7 +922,40 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/users/{id}": {
|
||||
"/user/{id}": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Users"
|
||||
],
|
||||
"summary": "Get a single user record.",
|
||||
"operationId": "users_handleSingleGet",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "The user identifier",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.User"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"put": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
@ -607,9 +1003,45 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Users"
|
||||
],
|
||||
"summary": "Delete the user record.",
|
||||
"operationId": "users_handleDelete",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "The user identifier",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "No content if deletion was successful"
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Error"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/model.Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/users/{id}/peers": {
|
||||
"/user/{id}/peers": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
@ -643,14 +1075,36 @@
|
||||
"model.Error": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": {
|
||||
"Code": {
|
||||
"type": "integer"
|
||||
},
|
||||
"message": {
|
||||
"Message": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"model.Int32ConfigOption": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Overridable": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"Value": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"model.IntConfigOption": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Overridable": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"Value": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"model.Interface": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@ -848,6 +1302,14 @@
|
||||
},
|
||||
"AllowedIPs": {
|
||||
"description": "all allowed ip subnets, comma seperated",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/model.StringSliceConfigOption"
|
||||
}
|
||||
]
|
||||
},
|
||||
"CheckAliveAddress": {
|
||||
"description": "optional ip address or DNS name that is used for ping checks",
|
||||
"type": "string"
|
||||
},
|
||||
"Disabled": {
|
||||
@ -864,27 +1326,54 @@
|
||||
},
|
||||
"Dns": {
|
||||
"description": "the dns server that should be set if the interface is up, comma separated",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/model.StringSliceConfigOption"
|
||||
}
|
||||
]
|
||||
},
|
||||
"DnsSearch": {
|
||||
"description": "the dns search option string that should be set if the interface is up, will be appended to DnsStr",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/model.StringSliceConfigOption"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Endpoint": {
|
||||
"description": "the endpoint address",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/model.StringConfigOption"
|
||||
}
|
||||
]
|
||||
},
|
||||
"EndpointPublicKey": {
|
||||
"description": "the endpoint public key",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/model.StringConfigOption"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ExpiresAt": {
|
||||
"description": "expiry dates for peers",
|
||||
"type": "string"
|
||||
},
|
||||
"ExtraAllowedIPs": {
|
||||
"description": "all allowed ip subnets on the server side, comma seperated",
|
||||
"type": "string"
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"FirewallMark": {
|
||||
"description": "a firewall mark",
|
||||
"type": "integer"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/model.Int32ConfigOption"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Identifier": {
|
||||
"description": "peer unique identifier",
|
||||
@ -901,27 +1390,55 @@
|
||||
},
|
||||
"Mtu": {
|
||||
"description": "the device MTU",
|
||||
"type": "integer"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/model.IntConfigOption"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Notes": {
|
||||
"description": "a note field for peers",
|
||||
"type": "string"
|
||||
},
|
||||
"PersistentKeepalive": {
|
||||
"description": "the persistent keep-alive interval",
|
||||
"type": "integer"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/model.IntConfigOption"
|
||||
}
|
||||
]
|
||||
},
|
||||
"PostDown": {
|
||||
"description": "action that is executed after the device is down",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/model.StringConfigOption"
|
||||
}
|
||||
]
|
||||
},
|
||||
"PostUp": {
|
||||
"description": "action that is executed after the device is up",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/model.StringConfigOption"
|
||||
}
|
||||
]
|
||||
},
|
||||
"PreDown": {
|
||||
"description": "action that is executed before the device is down",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/model.StringConfigOption"
|
||||
}
|
||||
]
|
||||
},
|
||||
"PreUp": {
|
||||
"description": "action that is executed before the device is up",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/model.StringConfigOption"
|
||||
}
|
||||
]
|
||||
},
|
||||
"PresharedKey": {
|
||||
"description": "the pre-shared Key of the peer",
|
||||
@ -939,7 +1456,11 @@
|
||||
},
|
||||
"RoutingTable": {
|
||||
"description": "the routing table",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/model.StringConfigOption"
|
||||
}
|
||||
]
|
||||
},
|
||||
"UserIdentifier": {
|
||||
"description": "the owner",
|
||||
@ -970,6 +1491,31 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"model.StringConfigOption": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Overridable": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"Value": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"model.StringSliceConfigOption": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Overridable": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"Value": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"model.User": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -2,11 +2,25 @@ basePath: /api/v0
|
||||
definitions:
|
||||
model.Error:
|
||||
properties:
|
||||
code:
|
||||
Code:
|
||||
type: integer
|
||||
message:
|
||||
Message:
|
||||
type: string
|
||||
type: object
|
||||
model.Int32ConfigOption:
|
||||
properties:
|
||||
Overridable:
|
||||
type: boolean
|
||||
Value:
|
||||
type: integer
|
||||
type: object
|
||||
model.IntConfigOption:
|
||||
properties:
|
||||
Overridable:
|
||||
type: boolean
|
||||
Value:
|
||||
type: integer
|
||||
type: object
|
||||
model.Interface:
|
||||
properties:
|
||||
Addresses:
|
||||
@ -154,7 +168,11 @@ definitions:
|
||||
type: string
|
||||
type: array
|
||||
AllowedIPs:
|
||||
allOf:
|
||||
- $ref: '#/definitions/model.StringSliceConfigOption'
|
||||
description: all allowed ip subnets, comma seperated
|
||||
CheckAliveAddress:
|
||||
description: optional ip address or DNS name that is used for ping checks
|
||||
type: string
|
||||
Disabled:
|
||||
description: flag that specifies if the peer is enabled (up) or not (down)
|
||||
@ -166,25 +184,35 @@ definitions:
|
||||
description: a nice display name/ description for the peer
|
||||
type: string
|
||||
Dns:
|
||||
allOf:
|
||||
- $ref: '#/definitions/model.StringSliceConfigOption'
|
||||
description: the dns server that should be set if the interface is up, comma
|
||||
separated
|
||||
type: string
|
||||
DnsSearch:
|
||||
allOf:
|
||||
- $ref: '#/definitions/model.StringSliceConfigOption'
|
||||
description: the dns search option string that should be set if the interface
|
||||
is up, will be appended to DnsStr
|
||||
type: string
|
||||
Endpoint:
|
||||
allOf:
|
||||
- $ref: '#/definitions/model.StringConfigOption'
|
||||
description: the endpoint address
|
||||
type: string
|
||||
EndpointPublicKey:
|
||||
allOf:
|
||||
- $ref: '#/definitions/model.StringConfigOption'
|
||||
description: the endpoint public key
|
||||
ExpiresAt:
|
||||
description: expiry dates for peers
|
||||
type: string
|
||||
ExtraAllowedIPs:
|
||||
description: all allowed ip subnets on the server side, comma seperated
|
||||
type: string
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
FirewallMark:
|
||||
allOf:
|
||||
- $ref: '#/definitions/model.Int32ConfigOption'
|
||||
description: a firewall mark
|
||||
type: integer
|
||||
Identifier:
|
||||
description: peer unique identifier
|
||||
example: super_nice_peer
|
||||
@ -196,23 +224,32 @@ definitions:
|
||||
description: the peer interface type (server, client, any)
|
||||
type: string
|
||||
Mtu:
|
||||
allOf:
|
||||
- $ref: '#/definitions/model.IntConfigOption'
|
||||
description: the device MTU
|
||||
type: integer
|
||||
Notes:
|
||||
description: a note field for peers
|
||||
type: string
|
||||
PersistentKeepalive:
|
||||
allOf:
|
||||
- $ref: '#/definitions/model.IntConfigOption'
|
||||
description: the persistent keep-alive interval
|
||||
type: integer
|
||||
PostDown:
|
||||
allOf:
|
||||
- $ref: '#/definitions/model.StringConfigOption'
|
||||
description: action that is executed after the device is down
|
||||
type: string
|
||||
PostUp:
|
||||
allOf:
|
||||
- $ref: '#/definitions/model.StringConfigOption'
|
||||
description: action that is executed after the device is up
|
||||
type: string
|
||||
PreDown:
|
||||
allOf:
|
||||
- $ref: '#/definitions/model.StringConfigOption'
|
||||
description: action that is executed before the device is down
|
||||
type: string
|
||||
PreUp:
|
||||
allOf:
|
||||
- $ref: '#/definitions/model.StringConfigOption'
|
||||
description: action that is executed before the device is up
|
||||
type: string
|
||||
PresharedKey:
|
||||
description: the pre-shared Key of the peer
|
||||
type: string
|
||||
@ -225,8 +262,9 @@ definitions:
|
||||
example: abcdef==
|
||||
type: string
|
||||
RoutingTable:
|
||||
allOf:
|
||||
- $ref: '#/definitions/model.StringConfigOption'
|
||||
description: the routing table
|
||||
type: string
|
||||
UserIdentifier:
|
||||
description: the owner
|
||||
type: string
|
||||
@ -246,6 +284,22 @@ definitions:
|
||||
UserLastname:
|
||||
type: string
|
||||
type: object
|
||||
model.StringConfigOption:
|
||||
properties:
|
||||
Overridable:
|
||||
type: boolean
|
||||
Value:
|
||||
type: string
|
||||
type: object
|
||||
model.StringSliceConfigOption:
|
||||
properties:
|
||||
Overridable:
|
||||
type: boolean
|
||||
Value:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
type: object
|
||||
model.User:
|
||||
properties:
|
||||
Department:
|
||||
@ -426,6 +480,30 @@ paths:
|
||||
tags:
|
||||
- Testing
|
||||
/interface/{id}:
|
||||
delete:
|
||||
operationId: interfaces_handleDelete
|
||||
parameters:
|
||||
- description: The interface identifier
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"204":
|
||||
description: No content if deletion was successful
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/model.Error'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/model.Error'
|
||||
summary: Delete the interface record.
|
||||
tags:
|
||||
- Interface
|
||||
put:
|
||||
operationId: interfaces_handleUpdatePut
|
||||
parameters:
|
||||
@ -477,6 +555,27 @@ paths:
|
||||
summary: Get all available interfaces.
|
||||
tags:
|
||||
- Interface
|
||||
/interface/config/{id}:
|
||||
get:
|
||||
operationId: interfaces_handleConfigGet
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
type: string
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/model.Error'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/model.Error'
|
||||
summary: Get interface configuration as string.
|
||||
tags:
|
||||
- Interface
|
||||
/interface/get/{id}:
|
||||
get:
|
||||
operationId: interfaces_handleSingleGet
|
||||
@ -580,9 +679,140 @@ paths:
|
||||
summary: Get the current local time.
|
||||
tags:
|
||||
- Testing
|
||||
/peer/all/{id}:
|
||||
/peer/{id}:
|
||||
delete:
|
||||
operationId: peers_handleDelete
|
||||
parameters:
|
||||
- description: The peer identifier
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"204":
|
||||
description: No content if deletion was successful
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/model.Error'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/model.Error'
|
||||
summary: Delete the peer record.
|
||||
tags:
|
||||
- Peer
|
||||
get:
|
||||
operationId: peers_handlePeersGet
|
||||
operationId: peers_handleSingleGet
|
||||
parameters:
|
||||
- description: The peer identifier
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/model.Peer'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/model.Error'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/model.Error'
|
||||
summary: Get peer for the given identifier.
|
||||
tags:
|
||||
- Peer
|
||||
put:
|
||||
operationId: peers_handleUpdatePut
|
||||
parameters:
|
||||
- description: The peer identifier
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
- description: The peer data
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/model.Peer'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/model.Peer'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/model.Error'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/model.Error'
|
||||
summary: Update the given peer record.
|
||||
tags:
|
||||
- Peer
|
||||
/peer/config-qr/{id}:
|
||||
get:
|
||||
operationId: peers_handleQrCodeGet
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
type: string
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/model.Error'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/model.Error'
|
||||
summary: Get peer configuration as qr code.
|
||||
tags:
|
||||
- Peer
|
||||
/peer/config/{id}:
|
||||
get:
|
||||
operationId: peers_handleConfigGet
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
type: string
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/model.Error'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/model.Error'
|
||||
summary: Get peer configuration as string.
|
||||
tags:
|
||||
- Peer
|
||||
/peer/iface/{iface}/all:
|
||||
get:
|
||||
operationId: peers_handleAllGet
|
||||
parameters:
|
||||
- description: The interface identifier
|
||||
in: path
|
||||
name: iface
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
@ -592,6 +822,10 @@ paths:
|
||||
items:
|
||||
$ref: '#/definitions/model.Peer'
|
||||
type: array
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/model.Error'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
@ -599,26 +833,113 @@ paths:
|
||||
summary: Get peers for the given interface.
|
||||
tags:
|
||||
- Peer
|
||||
/users:
|
||||
get:
|
||||
operationId: users_handleAllGet
|
||||
/peer/iface/{iface}/new:
|
||||
post:
|
||||
operationId: peers_handleCreatePost
|
||||
parameters:
|
||||
- description: The interface identifier
|
||||
in: path
|
||||
name: iface
|
||||
required: true
|
||||
type: string
|
||||
- description: The peer data
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/model.Peer'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/model.User'
|
||||
type: array
|
||||
$ref: '#/definitions/model.Peer'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/model.Error'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/model.Error'
|
||||
summary: Get all user records.
|
||||
summary: Prepare a new peer for the given interface.
|
||||
tags:
|
||||
- Peer
|
||||
/peer/iface/{iface}/prepare:
|
||||
get:
|
||||
operationId: peers_handlePrepareGet
|
||||
parameters:
|
||||
- description: The interface identifier
|
||||
in: path
|
||||
name: iface
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/model.Peer'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/model.Error'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/model.Error'
|
||||
summary: Prepare a new peer for the given interface.
|
||||
tags:
|
||||
- Peer
|
||||
/user/{id}:
|
||||
delete:
|
||||
operationId: users_handleDelete
|
||||
parameters:
|
||||
- description: The user identifier
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"204":
|
||||
description: No content if deletion was successful
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/model.Error'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/model.Error'
|
||||
summary: Delete the user record.
|
||||
tags:
|
||||
- Users
|
||||
get:
|
||||
operationId: users_handleSingleGet
|
||||
parameters:
|
||||
- description: The user identifier
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/model.User'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/model.Error'
|
||||
summary: Get a single user record.
|
||||
tags:
|
||||
- Users
|
||||
/users/{id}:
|
||||
put:
|
||||
operationId: users_handleUpdatePut
|
||||
parameters:
|
||||
@ -651,7 +972,7 @@ paths:
|
||||
summary: Update the user record.
|
||||
tags:
|
||||
- Users
|
||||
/users/{id}/peers:
|
||||
/user/{id}/peers:
|
||||
get:
|
||||
operationId: users_handlePeersGet
|
||||
produces:
|
||||
@ -670,7 +991,26 @@ paths:
|
||||
summary: Get peers for the given user.
|
||||
tags:
|
||||
- Users
|
||||
/users/new:
|
||||
/user/all:
|
||||
get:
|
||||
operationId: users_handleAllGet
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/model.User'
|
||||
type: array
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/model.Error'
|
||||
summary: Get all user records.
|
||||
tags:
|
||||
- Users
|
||||
/user/new:
|
||||
post:
|
||||
operationId: users_handleCreatePost
|
||||
parameters:
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -11,7 +11,7 @@
|
||||
let WGPORTAL_BACKEND_BASE_URL="http://localhost:5000/api/v0";
|
||||
</script>
|
||||
<script src="/api/v0/config/frontend.js"></script>
|
||||
<script type="module" crossorigin src="/app/assets/index-8f53e6dd.js"></script>
|
||||
<script type="module" crossorigin src="/app/assets/index-b5bbe402.js"></script>
|
||||
<link rel="stylesheet" href="/app/assets/index-a233ff7e.css">
|
||||
</head>
|
||||
<body class="d-flex flex-column min-vh-100">
|
||||
|
@ -7,7 +7,9 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/h44z/wg-portal/internal/app"
|
||||
"html/template"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
//go:embed frontend_config.js.gotpl
|
||||
@ -52,7 +54,14 @@ func (e configEndpoint) handleConfigJsGet() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
backendUrl := fmt.Sprintf("%s/api/v0", e.app.Config.Web.ExternalUrl)
|
||||
if c.GetHeader("x-wg-dev") != "" {
|
||||
backendUrl = "http://localhost:5000/api/v0" // override if reqest comes from frontend started with npm run dev
|
||||
referer := c.Request.Header.Get("Referer")
|
||||
host := "localhost"
|
||||
port := "5000"
|
||||
parsedReferer, err := url.Parse(referer)
|
||||
if err == nil {
|
||||
host, port, _ = net.SplitHostPort(parsedReferer.Host)
|
||||
}
|
||||
backendUrl = fmt.Sprintf("http://%s:%s/api/v0", host, port) // override if request comes from frontend started with npm run dev
|
||||
}
|
||||
buf := &bytes.Buffer{}
|
||||
err := e.tpl.ExecuteTemplate(buf, "frontend_config.js.gotpl", gin.H{
|
||||
|
@ -24,6 +24,7 @@ func (e peerEndpoint) RegisterRoutes(g *gin.RouterGroup, authenticator *authenti
|
||||
apiGroup.GET("/iface/:iface/all", e.handleAllGet())
|
||||
apiGroup.GET("/iface/:iface/prepare", e.handlePrepareGet())
|
||||
apiGroup.POST("/iface/:iface/new", e.handleCreatePost())
|
||||
apiGroup.POST("/iface/:iface/multiplenew", e.handleCreateMultiplePost())
|
||||
apiGroup.GET("/config-qr/:id", e.handleQrCodeGet())
|
||||
apiGroup.GET("/config/:id", e.handleConfigGet())
|
||||
apiGroup.GET("/:id", e.handleSingleGet())
|
||||
@ -168,6 +169,45 @@ func (e peerEndpoint) handleCreatePost() gin.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// handleCreateMultiplePost returns a gorm handler function.
|
||||
//
|
||||
// @ID peers_handleCreateMultiplePost
|
||||
// @Tags Peer
|
||||
// @Summary Create multiple new peers for the given interface.
|
||||
// @Produce json
|
||||
// @Param iface path string true "The interface identifier"
|
||||
// @Param request body model.MultiPeerRequest true "The peer creation request data"
|
||||
// @Success 200 {object} []model.Peer
|
||||
// @Failure 400 {object} model.Error
|
||||
// @Failure 500 {object} model.Error
|
||||
// @Router /peer/iface/{iface}/multiplenew [post]
|
||||
func (e peerEndpoint) handleCreateMultiplePost() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
ctx := domain.SetUserInfoFromGin(c)
|
||||
|
||||
interfaceId := Base64UrlDecode(c.Param("iface"))
|
||||
if interfaceId == "" {
|
||||
c.JSON(http.StatusBadRequest, model.Error{Code: http.StatusBadRequest, Message: "missing iface parameter"})
|
||||
return
|
||||
}
|
||||
|
||||
var req model.MultiPeerRequest
|
||||
err := c.BindJSON(&req)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, model.Error{Code: http.StatusBadRequest, Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
newPeers, err := e.app.CreateMultiplePeers(ctx, domain.InterfaceIdentifier(interfaceId), model.NewDomainPeerCreationRequest(&req))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, model.Error{Code: http.StatusInternalServerError, Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, model.NewPeers(newPeers))
|
||||
}
|
||||
}
|
||||
|
||||
// handleUpdatePut returns a gorm handler function.
|
||||
//
|
||||
// @ID peers_handleUpdatePut
|
||||
|
@ -131,3 +131,15 @@ func NewDomainPeer(src *Peer) *domain.Peer {
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
type MultiPeerRequest struct {
|
||||
Identifiers []string `json:"Identifiers"`
|
||||
Suffix string `json:"Suffix"`
|
||||
}
|
||||
|
||||
func NewDomainPeerCreationRequest(src *MultiPeerRequest) *domain.PeerCreationRequest {
|
||||
return &domain.PeerCreationRequest{
|
||||
Identifiers: src.Identifiers,
|
||||
Suffix: src.Suffix,
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ type WireGuardManager interface {
|
||||
PreparePeer(ctx context.Context, id domain.InterfaceIdentifier) (*domain.Peer, error)
|
||||
GetPeer(ctx context.Context, id domain.PeerIdentifier) (*domain.Peer, error)
|
||||
CreatePeer(ctx context.Context, p *domain.Peer) (*domain.Peer, error)
|
||||
CreateMultiplePeers(ctx context.Context, id domain.InterfaceIdentifier, r *domain.PeerCreationRequest) ([]domain.Peer, error)
|
||||
UpdatePeer(ctx context.Context, p *domain.Peer) (*domain.Peer, error)
|
||||
DeletePeer(ctx context.Context, id domain.PeerIdentifier) error
|
||||
}
|
||||
|
@ -775,6 +775,33 @@ func (m Manager) CreatePeer(ctx context.Context, peer *domain.Peer) (*domain.Pee
|
||||
return peer, nil
|
||||
}
|
||||
|
||||
func (m Manager) CreateMultiplePeers(ctx context.Context, interfaceId domain.InterfaceIdentifier, r *domain.PeerCreationRequest) ([]domain.Peer, error) {
|
||||
var newPeers []domain.Peer
|
||||
|
||||
for _, id := range r.Identifiers {
|
||||
freshPeer, err := m.PreparePeer(ctx, interfaceId)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to prepare peer for interface %s: %w", interfaceId, err)
|
||||
}
|
||||
|
||||
freshPeer.UserIdentifier = domain.UserIdentifier(id) // use id as user identifier. peers are allowed to have invalid user identifiers
|
||||
if r.Suffix != "" {
|
||||
freshPeer.DisplayName += " " + r.Suffix
|
||||
}
|
||||
|
||||
newPeers = append(newPeers, *freshPeer)
|
||||
}
|
||||
|
||||
for i, peer := range newPeers {
|
||||
_, err := m.CreatePeer(ctx, &newPeers[i])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create peer %s (uid: %s) for interface %s: %w", peer.Identifier, peer.UserIdentifier, interfaceId, err)
|
||||
}
|
||||
}
|
||||
|
||||
return newPeers, nil
|
||||
}
|
||||
|
||||
func (m Manager) UpdatePeer(ctx context.Context, peer *domain.Peer) (*domain.Peer, error) {
|
||||
existingPeer, err := m.db.GetPeer(ctx, peer.Identifier)
|
||||
if err != nil {
|
||||
|
@ -181,3 +181,8 @@ func MergeToPhysicalPeer(pp *PhysicalPeer, p *Peer) {
|
||||
pp.PublicKey = p.Interface.PublicKey
|
||||
pp.PersistentKeepalive = p.PersistentKeepalive.GetValue()
|
||||
}
|
||||
|
||||
type PeerCreationRequest struct {
|
||||
Identifiers []string
|
||||
Suffix string
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user