diff --git a/README.md b/README.md
index be524a5..51c1e85 100644
--- a/README.md
+++ b/README.md
@@ -46,7 +46,7 @@ The easiest way to run Wg Gen Web is using the container image
```
docker run --rm -it -v /tmp/wireguard:/data -p 8080:8080 -e "WG_CONF_DIR=/data" vx3r/wg-gen-web:latest
```
-Docker compose snippet, used for demo server
+Docker compose snippet, used for demo server, wg-json-api service is optional
```
version: '3.6'
wg-gen-web-demo:
@@ -70,6 +70,14 @@ version: '3.6'
- OAUTH2_REDIRECT_URL=https://wg-gen-web-demo.127-0-0-1.fr
volumes:
- /etc/wireguard:/data
+ wg-json-api:
+ image: james/wg-api:latest
+ container_name: wg-json-api
+ restart: unless-stopped
+ cap_add:
+ - NET_ADMIN
+ network_mode: "host"
+ command: wg-api --device wg0 --listen localhost:8182
```
Please note that mapping ```/etc/wireguard``` to ```/data``` inside the docker, will erase your host's current configuration.
If needed, please make sure to backup your files from ```/etc/wireguard```.
@@ -177,9 +185,21 @@ OAUTH2_CLIENT_SECRET=********************
OAUTH2_REDIRECT_URL=https://wg-gen-web-demo.127-0-0-1.fr
```
-Please fell free to test and report any bugs.
Wg Gen Web will only access your profile to get email address and your name, no other unnecessary scopes will be requested.
+## WireGuard Status Display
+Wg Gen Web integrates a [WireGuard API implementation](https://github.com/jamescun/wg-api) to display client stats.
+In order to enable the Status API integration, the following settings need to be configured:
+```
+# https://github.com/jamescun/wg-api integration, user and password (basic auth) are optional
+WG_STATS_API=http://localhost:8182
+WG_STATS_API_USER=
+WG_STATS_API_PASS=
+```
+To setup the WireGuard API take a look at [https://github.com/jamescun/wg-api/blob/master/README.md](https://github.com/jamescun/wg-api/blob/master/README.md).
+
+Please fell free to test and report any bugs.
+
## Need Help
* Join us on [Discord](https://discord.gg/fjx7gGJ)
diff --git a/api/v1/status/status.go b/api/v1/status/status.go
index f5a16de..f61f82b 100644
--- a/api/v1/status/status.go
+++ b/api/v1/status/status.go
@@ -2,6 +2,7 @@ package status
import (
"net/http"
+ "os"
"github.com/gin-gonic/gin"
log "github.com/sirupsen/logrus"
@@ -12,11 +13,16 @@ import (
func ApplyRoutes(r *gin.RouterGroup) {
g := r.Group("/status")
{
+ g.GET("/enabled", readEnabled)
g.GET("/interface", readInterfaceStatus)
g.GET("/clients", readClientStatus)
}
}
+func readEnabled(c *gin.Context) {
+ c.JSON(http.StatusOK, os.Getenv("WG_STATS_API") != "")
+}
+
func readInterfaceStatus(c *gin.Context) {
status, err := core.ReadInterfaceStatus()
if err != nil {
diff --git a/ui/src/components/Status.vue b/ui/src/components/Status.vue
index eb6f9f8..066b63e 100644
--- a/ui/src/components/Status.vue
+++ b/ui/src/components/Status.vue
@@ -80,7 +80,8 @@
No stats available...
- {{ error }}
+ {{ error }}
+ Status API integration not configured.
@@ -109,26 +110,32 @@
...mapGetters({
interface: 'status/interfaceStatus',
clients: 'status/clientStatus',
+ enabled: 'status/enabled',
error: 'status/error',
}),
dataLoaded: function () {
- return this.interface != null && this.interface.name !== "";
+ return this.enabled && this.interface != null && this.interface.name !== "";
}
},
mounted () {
- this.readStatus()
+ this.readEnabled()
+ if(this.enabled) {
+ this.readStatus()
+ }
},
methods: {
...mapActions('status', {
readStatus: 'read',
+ readEnabled: 'isEnabled',
}),
reload() {
this.readStatus()
},
+ // https://stackoverflow.com/questions/10420352/converting-file-size-in-bytes-to-human-readable-string
humanFileSize(bytes, si=false, dp=1) {
const thresh = si ? 1000 : 1024;
diff --git a/ui/src/services/api.service.js b/ui/src/services/api.service.js
index 9a5e6d2..237c308 100644
--- a/ui/src/services/api.service.js
+++ b/ui/src/services/api.service.js
@@ -10,9 +10,13 @@ const ApiService = {
get(resource) {
return Vue.axios.get(resource)
.then(response => response.data)
- .catch(error => {
- throw new Error(`ApiService: ${error}`)
- });
+ .catch(error => {
+ if(typeof error.response !== 'undefined') {
+ throw new Error(`${error.response.status} - ${error.response.statusText}: ${error.response.data}`)
+ } else {
+ throw new Error(`ApiService: ${error}`)
+ }
+ });
},
post(resource, params) {
diff --git a/ui/src/store/modules/status.js b/ui/src/store/modules/status.js
index fef5cd9..b1db23e 100644
--- a/ui/src/store/modules/status.js
+++ b/ui/src/store/modules/status.js
@@ -2,6 +2,7 @@ import ApiService from "../../services/api.service";
const state = {
error: null,
+ enabled: false,
interfaceStatus: null,
clientStatus: [],
version: '_ci_build_not_run_properly_',
@@ -12,6 +13,10 @@ const getters = {
return state.error;
},
+ enabled(state) {
+ return state.enabled;
+ },
+
interfaceStatus(state) {
return state.interfaceStatus;
},
@@ -48,6 +53,17 @@ const actions = {
commit('error', err)
});
},
+
+ isEnabled({ commit }){
+ ApiService.get("/status/enabled")
+ .then(resp => {
+ commit('enabled', resp)
+ })
+ .catch(err => {
+ commit('enabled', false);
+ commit('error', err.response.data)
+ });
+ },
}
const mutations = {
@@ -55,6 +71,10 @@ const mutations = {
state.error = error;
},
+ enabled(state, enabled) {
+ state.enabled = enabled;
+ },
+
interfaceStatus(state, interfaceStatus){
state.interfaceStatus = interfaceStatus
},