diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ff33b6df35e480043107cb8fc821d07a2416a36e..73df196ca778ff0a90ba57810c6e2bd44502c417 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,7 +7,7 @@ build-back: stage: build artifacts image: golang:latest script: - - GOOS=linux GOARCH=amd64 go build -ldflags="-X 'gitlab.127-0-0-1.fr/vx3r/wg-gen-web/util.Version=${CI_COMMIT_SHORT_SHA}'" -o ${CI_PROJECT_NAME}-linux-amd64 + - GOOS=linux GOARCH=amd64 go build -ldflags="-X 'gitlab.127-0-0-1.fr/vx3r/wg-gen-web/util.Version=${CI_COMMIT_SHA}'" -o ${CI_PROJECT_NAME}-linux-amd64 artifacts: paths: - ${CI_PROJECT_NAME}-linux-amd64 @@ -29,7 +29,7 @@ build: image: docker:latest script: - docker info - - docker build --build-arg COMMIT=${CI_COMMIT_SHORT_SHA} --network br_docker --tag ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHORT_SHA} . + - docker build --build-arg COMMIT=${CI_COMMIT_SHA} --network br_docker --tag ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHORT_SHA} . push: stage: push docker hub diff --git a/api/api.go b/api/api.go index b527996bc8d39eb10405d627f310ca12596e6fcf..faa36481d26b540014bd4b0ddb3d877e2f180dfd 100644 --- a/api/api.go +++ b/api/api.go @@ -6,6 +6,7 @@ import ( "github.com/skip2/go-qrcode" "gitlab.127-0-0-1.fr/vx3r/wg-gen-web/core" "gitlab.127-0-0-1.fr/vx3r/wg-gen-web/model" + "gitlab.127-0-0-1.fr/vx3r/wg-gen-web/template" "gitlab.127-0-0-1.fr/vx3r/wg-gen-web/util" "net/http" ) @@ -28,6 +29,7 @@ func ApplyRoutes(r *gin.Engine) { { server.GET("", readServer) server.PATCH("", updateServer) + server.GET("/config", configServer) server.GET("/version", version) } } @@ -203,6 +205,39 @@ func updateServer(c *gin.Context) { c.JSON(http.StatusOK, client) } +func configServer(c *gin.Context) { + clients, err := core.ReadClients() + if err != nil { + log.WithFields(log.Fields{ + "err": err, + }).Error("failed to read clients") + c.AbortWithStatus(http.StatusUnprocessableEntity) + return + } + + server, err := core.ReadServer() + if err != nil { + log.WithFields(log.Fields{ + "err": err, + }).Error("failed to read server") + c.AbortWithStatus(http.StatusUnprocessableEntity) + return + } + + configData, err := template.DumpServerWg(clients, server) + if err != nil { + log.WithFields(log.Fields{ + "err": err, + }).Error("failed to dump wg config") + c.AbortWithStatus(http.StatusUnprocessableEntity) + return + } + + // return config as txt file + c.Header("Content-Disposition", "attachment; filename=wg0.conf") + c.Data(http.StatusOK, "application/config", configData) +} + func version(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "version": util.Version, diff --git a/ui/src/App.vue b/ui/src/App.vue index 86b54f857ab43d99109b0fbe278dd5f79e72baae..2e2c6202c8e7dd8b5e74fdb8ac3536e42936112d 100644 --- a/ui/src/App.vue +++ b/ui/src/App.vue @@ -28,7 +28,17 @@ </v-content> <v-footer app> - <span>License <a class="pr-1 pl-1" href="http://www.wtfpl.net/" target="_blank">WTFPL</a> © {{ new Date().getFullYear() }} Created with</span><v-icon class="pr-1 pl-1">mdi-heart</v-icon><span>by</span><a class="pr-1 pl-1" href="mailto:vx3r@127-0-0-1.fr">vx3r</a><v-spacer></v-spacer><span>Version: {{ version }}</span> + <small>Copyright © {{ new Date().getFullYear() }}, Wg Gen Web.</small> + <small>This work is licensed under a <a class="pr-1 pl-1" href="http://www.wtfpl.net/" target="_blank">WTFPL License.</a></small> + + <v-spacer></v-spacer> + + <small>Created with</small> + <v-icon class="pr-1 pl-1">mdi-heart</v-icon><span>by</span><a class="pr-1 pl-1" href="mailto:vx3r@127-0-0-1.fr">vx3r</a> + + <v-spacer></v-spacer> + + <a :href="'https://github.com/vx3r/wg-gen-web/commit/' + version"><kbd>Version: {{ version.substring(0,7) }}</kbd></a> </v-footer> </v-app> diff --git a/ui/src/components/Server.vue b/ui/src/components/Server.vue index 9d689283f6968c065252cc3c0f7655cdb190df47..1d5523fd00a9e2712fd59921c19874ee569a3291 100644 --- a/ui/src/components/Server.vue +++ b/ui/src/components/Server.vue @@ -7,14 +7,6 @@ <v-list-item-content> <v-list-item-title class="headline">Server's interface configuration</v-list-item-title> </v-list-item-content> - <v-btn - class="ma-2" - color="warning" - @click="updateServer" - > - Update server configuration - <v-icon right dark>mdi-update</v-icon> - </v-btn> </v-list-item> <div class="d-flex flex-no-wrap justify-space-between"> <v-col cols="12"> @@ -67,14 +59,6 @@ <v-list-item-content> <v-list-item-title class="headline">Client's global configuration</v-list-item-title> </v-list-item-content> - <v-btn - class="ma-2" - color="warning" - @click="updateServer" - > - Update server configuration - <v-icon right dark>mdi-update</v-icon> - </v-btn> </v-list-item> <div class="d-flex flex-no-wrap justify-space-between"> <v-col cols="12"> @@ -130,14 +114,6 @@ <v-list-item-content> <v-list-item-title class="headline">Interface configuration hooks</v-list-item-title> </v-list-item-content> - <v-btn - class="ma-2" - color="warning" - @click="updateServer" - > - Update server configuration - <v-icon right dark>mdi-update</v-icon> - </v-btn> </v-list-item> <div class="d-flex flex-no-wrap justify-space-between"> <v-col cols="12"> @@ -162,13 +138,32 @@ </v-card> </v-col> </v-row> - <v-divider dark/> - <v-divider dark/> + <v-row> + <v-divider dark/> + <v-btn + class="ma-2" + color="success" + :href="`${apiBaseUrl}/server/config`" + > + Download server configuration + <v-icon right dark>mdi-cloud-download-outline</v-icon> + </v-btn> + <v-spacer></v-spacer> + <v-btn + class="ma-2" + color="warning" + @click="updateServer" + > + Update server configuration + <v-icon right dark>mdi-update</v-icon> + </v-btn> + <v-divider dark/> + </v-row> <Notification v-bind:notification="notification"/> </v-container> </template> <script> - import {ApiService} from "../services/ApiService"; + import {API_BASE_URL, ApiService} from "../services/ApiService"; import Notification from '../components/Notification' export default { @@ -181,6 +176,7 @@ data: () => ({ api: null, server: null, + apiBaseUrl: API_BASE_URL, notification: { show: false, color: '',