mirror of
https://github.com/donaldzou/WGDashboard.git
synced 2025-12-14 23:46:17 +00:00
Compare commits
104 Commits
v4.3.0.1
...
v4.3.0.4-d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b355d72e0a | ||
|
|
ec9131ea10 | ||
|
|
6fee7da633 | ||
|
|
2e8d2fe400 | ||
|
|
da3c34c250 | ||
|
|
d864d12793 | ||
|
|
36390a4d71 | ||
|
|
5db2baf1dc | ||
|
|
dc10da607d | ||
|
|
9b4abf19fa | ||
|
|
bf823e6cf8 | ||
|
|
880c94b8a3 | ||
|
|
656eba3a57 | ||
|
|
4154a27f4d | ||
|
|
785d0d6b06 | ||
|
|
9af2983a7b | ||
|
|
83b4753d5f | ||
|
|
f4f0ab27ef | ||
|
|
d51815e0f7 | ||
|
|
413b65e976 | ||
|
|
b1ea6d3c1d | ||
|
|
c7bed91626 | ||
|
|
b9e09bf91b | ||
|
|
839f686d73 | ||
|
|
1ead86dacc | ||
|
|
c4265b31a9 | ||
|
|
63e6c2040f | ||
|
|
35de3eb45a | ||
|
|
7c35f81af1 | ||
|
|
1a653bfe32 | ||
|
|
024072688f | ||
|
|
fa59de4a09 | ||
|
|
4756556c82 | ||
|
|
66ffc12864 | ||
|
|
9f609b01de | ||
|
|
a40df0481f | ||
|
|
2de46d97cf | ||
|
|
bd6d27f282 | ||
|
|
61c9f5aab7 | ||
|
|
aba3c5da64 | ||
|
|
2ee1b3b138 | ||
|
|
876a079be3 | ||
|
|
1fe03e1664 | ||
|
|
d55770c385 | ||
|
|
cd11e0495a | ||
|
|
24367db1f5 | ||
|
|
bfc3e285db | ||
|
|
58dc5a70dc | ||
|
|
c94b8a17bc | ||
|
|
b18ceca439 | ||
|
|
b794c342b1 | ||
|
|
230fa166b8 | ||
|
|
0ed5640499 | ||
|
|
931d547046 | ||
|
|
30dd9f3e54 | ||
|
|
c98a83e5b1 | ||
|
|
10c9b5635f | ||
|
|
9dd5341fd9 | ||
|
|
d763867566 | ||
|
|
18531b71c7 | ||
|
|
bbeae93c05 | ||
|
|
3c297cbb96 | ||
|
|
954f99b354 | ||
|
|
3f75c0aa3b | ||
|
|
33d8a1f991 | ||
|
|
616238735a | ||
|
|
649c1ad292 | ||
|
|
145b18c28c | ||
|
|
34e43de1a1 | ||
|
|
b7ed934331 | ||
|
|
d5a7632bb6 | ||
|
|
6621c5f910 | ||
|
|
09a3fddd87 | ||
|
|
45510165a2 | ||
|
|
508dbf8dc2 | ||
|
|
eb1d52ffba | ||
|
|
5db7351f8c | ||
|
|
5ae3a56337 | ||
|
|
e7068b472e | ||
|
|
3dc94a35a1 | ||
|
|
f82abd71a3 | ||
|
|
602238d794 | ||
|
|
4d4a15740b | ||
|
|
524d50ee07 | ||
|
|
fc591b7fe8 | ||
|
|
c2f06193d0 | ||
|
|
f2ead12315 | ||
|
|
ca8700ac2a | ||
|
|
10a8d22efd | ||
|
|
fc3ec61373 | ||
|
|
094d1c0718 | ||
|
|
0d814ec03c | ||
|
|
5ccfe07e12 | ||
|
|
101ac5e985 | ||
|
|
113a780eec | ||
|
|
cf77610a56 | ||
|
|
84675fe521 | ||
|
|
5db5b35311 | ||
|
|
ff345c9609 | ||
|
|
6cccfec923 | ||
|
|
8231dd1463 | ||
|
|
d8ff020d8c | ||
|
|
238fb91360 | ||
|
|
9ecc16fcc1 |
12
.github/dependabot.yml
vendored
12
.github/dependabot.yml
vendored
@@ -8,24 +8,24 @@ updates:
|
|||||||
- package-ecosystem: "pip"
|
- package-ecosystem: "pip"
|
||||||
directory: "/src"
|
directory: "/src"
|
||||||
schedule:
|
schedule:
|
||||||
interval: "daily"
|
interval: "weekly"
|
||||||
|
|
||||||
- package-ecosystem: "npm"
|
- package-ecosystem: "npm"
|
||||||
directory: "/"
|
directory: "/src/static/app"
|
||||||
schedule:
|
schedule:
|
||||||
interval: "daily"
|
interval: "weekly"
|
||||||
|
|
||||||
- package-ecosystem: "github-actions"
|
- package-ecosystem: "github-actions"
|
||||||
directory: "/.github"
|
directory: "/.github"
|
||||||
schedule:
|
schedule:
|
||||||
interval: "daily"
|
interval: "weekly"
|
||||||
|
|
||||||
- package-ecosystem: "docker"
|
- package-ecosystem: "docker"
|
||||||
directory: "/docker"
|
directory: "/docker"
|
||||||
schedule:
|
schedule:
|
||||||
interval: "daily"
|
interval: "weekly"
|
||||||
|
|
||||||
- package-ecosystem: "docker-compose"
|
- package-ecosystem: "docker-compose"
|
||||||
directory: "/docker"
|
directory: "/docker"
|
||||||
schedule:
|
schedule:
|
||||||
interval: "daily"
|
interval: "weekly"
|
||||||
|
|||||||
8
.github/workflows/codeql-analyze.yaml
vendored
8
.github/workflows/codeql-analyze.yaml
vendored
@@ -39,11 +39,11 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v3
|
uses: github/codeql-action/init@v4
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
@@ -54,7 +54,7 @@ jobs:
|
|||||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||||
# If this step fails, then you should remove it and run the build manually (see below)
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@v3
|
uses: github/codeql-action/autobuild@v4
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
# 📚 https://git.io/JvXDl
|
# 📚 https://git.io/JvXDl
|
||||||
@@ -68,4 +68,4 @@ jobs:
|
|||||||
# make release
|
# make release
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v3
|
uses: github/codeql-action/analyze@v4
|
||||||
|
|||||||
106
.github/workflows/docker-debug.yml
vendored
Normal file
106
.github/workflows/docker-debug.yml
vendored
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
name: MANUAL Docker workflow for debugging
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
DOCKERHUB_PREFIX: docker.io
|
||||||
|
GITHUB_CONTAINER_PREFIX: ghcr.io
|
||||||
|
DOCKER_IMAGE: WGDashboard
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker_build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Log in to Docker Hub
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ env.DOCKERHUB_PREFIX }}
|
||||||
|
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Log in to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ env.GITHUB_CONTAINER_PREFIX }}
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
with:
|
||||||
|
platforms: linux/amd64
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Extract Docker metadata from environment
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: |
|
||||||
|
${{ env.DOCKERHUB_PREFIX }}/donaldzou/${{ env.DOCKER_IMAGE }}
|
||||||
|
${{ env.GITHUB_CONTAINER_PREFIX }}/${{ github.repository_owner }}/${{ env.DOCKER_IMAGE }}
|
||||||
|
tags: |
|
||||||
|
type=ref,event=branch
|
||||||
|
type=ref,event=tag
|
||||||
|
type=sha,format=short,prefix=
|
||||||
|
|
||||||
|
- name: Build and export Docker image
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./docker/Dockerfile
|
||||||
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
platforms: linux/amd64
|
||||||
|
|
||||||
|
docker_scan:
|
||||||
|
if: ${{ github.event_name != 'pull_request' }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: docker_build
|
||||||
|
steps:
|
||||||
|
- name: Log in to Docker Hub
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ env.DOCKERHUB_PREFIX }}
|
||||||
|
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Log in to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ env.GITHUB_CONTAINER_PREFIX }}
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Docker Scout CVEs
|
||||||
|
uses: docker/scout-action@v1
|
||||||
|
with:
|
||||||
|
command: cves
|
||||||
|
image: ${{ env.GITHUB_CONTAINER_PREFIX }}/${{ github.repository_owner }}/${{ env.DOCKER_IMAGE }}:main
|
||||||
|
only-severities: critical,high
|
||||||
|
only-fixed: true
|
||||||
|
write-comment: true
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
exit-code: true
|
||||||
|
|
||||||
|
- name: Docker Scout Compare
|
||||||
|
uses: docker/scout-action@v1
|
||||||
|
with:
|
||||||
|
command: compare
|
||||||
|
# Set to Github for maximum compat
|
||||||
|
image: ${{ env.GITHUB_CONTAINER_PREFIX }}/${{ github.repository_owner }}/${{ env.DOCKER_IMAGE }}:main
|
||||||
|
to: ${{ env.GITHUB_CONTAINER_PREFIX }}/${{ github.repository_owner }}/${{ env.DOCKER_IMAGE }}:latest
|
||||||
|
only-severities: critical,high
|
||||||
|
ignore-unchanged: true
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
9
.github/workflows/docker.yml
vendored
9
.github/workflows/docker.yml
vendored
@@ -44,15 +44,12 @@ jobs:
|
|||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@v3
|
||||||
with:
|
with:
|
||||||
platforms: |
|
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||||
- linux/amd64
|
|
||||||
- linux/arm64
|
|
||||||
- linux/arm/v7
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
- name: Docker meta by docs https://github.com/docker/metadata-action
|
- name: Extract Docker metadata from environment
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v5
|
uses: docker/metadata-action@v5
|
||||||
with:
|
with:
|
||||||
@@ -64,7 +61,7 @@ jobs:
|
|||||||
type=ref,event=tag
|
type=ref,event=tag
|
||||||
type=sha,format=short,prefix=
|
type=sha,format=short,prefix=
|
||||||
|
|
||||||
- name: Build and export (multi-arch)
|
- name: Build and export Docker image
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
|
|||||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
|
*.tar
|
||||||
.vscode
|
.vscode
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.idea
|
.idea
|
||||||
@@ -10,7 +11,7 @@ src/static/pic.xd
|
|||||||
*.conf
|
*.conf
|
||||||
private_key.txt
|
private_key.txt
|
||||||
public_key.txt
|
public_key.txt
|
||||||
venv/**
|
*venv*
|
||||||
log/**
|
log/**
|
||||||
release/*
|
release/*
|
||||||
src/db/wgdashboard.db
|
src/db/wgdashboard.db
|
||||||
@@ -19,6 +20,8 @@ node_modules/**
|
|||||||
*/proxy.js
|
*/proxy.js
|
||||||
src/static/app/proxy.js
|
src/static/app/proxy.js
|
||||||
.secrets
|
.secrets
|
||||||
|
*.ini
|
||||||
|
*.pid
|
||||||
|
|
||||||
# Logs
|
# Logs
|
||||||
logs
|
logs
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
> [!TIP]
|
> [!TIP]
|
||||||
> 🎉 I'm excited to announce that WGDashboard is officially listed on DigitalOcean's Marketplace! For more information, please visit [Host WGDashboard & WireGuard with DigitalOcean](https://docs.wgdashboard.dev/host-wgdashboard-wireguard-with-digitalocean.html) for more information!
|
> 🎉 To help us better understand and improve WGDashboard’s performance, we’re launching the **WGDashboard Testing Program**. As part of this program, participants will receive free WireGuard VPN access to our server in Toronto, Canada, valid for **24 hours** or up to **1GB of total traffic**—whichever comes first. If you’d like to join, visit [https://wg.wgdashboard.dev/](https://wg.wgdashboard.dev/) for more details!
|
||||||
|
|
||||||
> [!NOTE]
|
|
||||||
> **Help Wanted 🎉**: Localizing WGDashboard to other languages! If you're willing to help, please visit https://github.com/WGDashboard/WGDashboard/issues/397. Many thanks!
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -26,6 +23,8 @@
|
|||||||
<a href="https://wakatime.com/badge/github/donaldzou/WGDashboard"><img src="https://wakatime.com/badge/github/donaldzou/WGDashboard.svg?style=for-the-badge" alt="wakatime"></a>
|
<a href="https://wakatime.com/badge/github/donaldzou/WGDashboard"><img src="https://wakatime.com/badge/github/donaldzou/WGDashboard.svg?style=for-the-badge" alt="wakatime"></a>
|
||||||
<a href="https://hitscounter.dev"><img src="https://hitscounter.dev/api/hit?url=https%3A%2F%2Fgithub.com%2Fdonaldzou%2FWGDashboard&label=Visitor&icon=github&color=%230a58ca&style=for-the-badge"></a>
|
<a href="https://hitscounter.dev"><img src="https://hitscounter.dev/api/hit?url=https%3A%2F%2Fgithub.com%2Fdonaldzou%2FWGDashboard&label=Visitor&icon=github&color=%230a58ca&style=for-the-badge"></a>
|
||||||
<img src="https://img.shields.io/docker/pulls/donaldzou/wgdashboard?logo=docker&label=Docker%20Image%20Pulls&labelColor=ffffff&style=for-the-badge">
|
<img src="https://img.shields.io/docker/pulls/donaldzou/wgdashboard?logo=docker&label=Docker%20Image%20Pulls&labelColor=ffffff&style=for-the-badge">
|
||||||
|
<img src="https://github.com/WGDashboard/WGDashboard/actions/workflows/docker.yml/badge.svg?style=for-the-badge">
|
||||||
|
<img src="https://github.com/WGDashboard/WGDashboard/actions/workflows/codeql-analyze.yaml/badge.svg">
|
||||||
</p>
|
</p>
|
||||||
<p align="center"><b>This project is supported by</b></p>
|
<p align="center"><b>This project is supported by</b></p>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
|
|||||||
@@ -4,7 +4,5 @@
|
|||||||
|
|
||||||
| Version | Supported |
|
| Version | Supported |
|
||||||
| ------- | ------------------ |
|
| ------- | ------------------ |
|
||||||
| 5.1.x | :white_check_mark: |
|
| 4.3 | :white_check_mark: |
|
||||||
| 5.0.x | :x: |
|
| < 4.3 | :x: |
|
||||||
| 4.0.x | :white_check_mark: |
|
|
||||||
| < 4.0 | :x: |
|
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
# Base: Alpine
|
# Base: Alpine
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# Pull the current golang-alpine image.
|
||||||
FROM golang:1.25-alpine AS awg-go
|
FROM golang:1.25-alpine AS awg-go
|
||||||
|
|
||||||
|
# Install build-dependencies.
|
||||||
RUN apk add --no-cache \
|
RUN apk add --no-cache \
|
||||||
git \
|
git \
|
||||||
gcc \
|
gcc \
|
||||||
@@ -14,18 +16,23 @@ RUN apk add --no-cache \
|
|||||||
RUN mkdir -p /workspace && \
|
RUN mkdir -p /workspace && \
|
||||||
git clone https://github.com/WGDashboard/amneziawg-go /workspace/awg
|
git clone https://github.com/WGDashboard/amneziawg-go /workspace/awg
|
||||||
|
|
||||||
|
# Enable CGO compilation for AmneziaWG
|
||||||
ENV CGO_ENABLED=1
|
ENV CGO_ENABLED=1
|
||||||
|
|
||||||
|
# Change directory
|
||||||
WORKDIR /workspace/awg
|
WORKDIR /workspace/awg
|
||||||
RUN go mod download && \
|
# Compile the binaries
|
||||||
|
RUN go version && \
|
||||||
|
go mod download && \
|
||||||
go mod verify && \
|
go mod verify && \
|
||||||
go build -ldflags '-linkmode external -extldflags "-fno-PIC -static"' -v -o /usr/bin
|
go build -ldflags '-linkmode external -extldflags "-fno-PIC -static"' -v -o /usr/bin
|
||||||
#
|
#
|
||||||
# AWG TOOLS BUILDING STAGE
|
# AWG TOOLS BUILDING STAGE
|
||||||
# Base: Debian
|
# Base: Alpine
|
||||||
#
|
#
|
||||||
FROM alpine:latest AS awg-tools
|
FROM alpine:latest AS awg-tools
|
||||||
|
|
||||||
|
# Install needed dependencies.
|
||||||
RUN apk add --no-cache \
|
RUN apk add --no-cache \
|
||||||
make \
|
make \
|
||||||
git \
|
git \
|
||||||
@@ -33,31 +40,47 @@ RUN apk add --no-cache \
|
|||||||
linux-headers \
|
linux-headers \
|
||||||
ca-certificates
|
ca-certificates
|
||||||
|
|
||||||
|
# Get the workspace ready
|
||||||
RUN mkdir -p /workspace && \
|
RUN mkdir -p /workspace && \
|
||||||
git clone https://github.com/WGDashboard/amneziawg-tools /workspace/awg-tools
|
git clone https://github.com/WGDashboard/amneziawg-tools /workspace/awg-tools
|
||||||
|
|
||||||
|
# Change directory
|
||||||
WORKDIR /workspace/awg-tools/src
|
WORKDIR /workspace/awg-tools/src
|
||||||
|
# Compile and change permissions
|
||||||
RUN make && chmod +x wg*
|
RUN make && chmod +x wg*
|
||||||
|
|
||||||
#
|
#
|
||||||
# PIP DEPENDENCY BUILDING
|
# PIP DEPENDENCY BUILDING
|
||||||
# Base: Alpine
|
# Base: Alpine
|
||||||
#
|
#
|
||||||
FROM python:3.13-alpine AS pip-builder
|
|
||||||
|
|
||||||
|
# Use the python-alpine image for building pip dependencies
|
||||||
|
FROM python:3.14-alpine AS pip-builder
|
||||||
|
|
||||||
|
ARG TARGETPLATFORM
|
||||||
|
|
||||||
|
# Add the build dependencies and create a Python virtual environment.
|
||||||
RUN apk add --no-cache \
|
RUN apk add --no-cache \
|
||||||
build-base \
|
build-base \
|
||||||
pkgconfig \
|
pkgconfig \
|
||||||
python3-dev \
|
python3-dev \
|
||||||
|
postgresql-dev \
|
||||||
libffi-dev \
|
libffi-dev \
|
||||||
|
libpq \
|
||||||
linux-headers \
|
linux-headers \
|
||||||
rust \
|
rust \
|
||||||
cargo \
|
cargo \
|
||||||
&& mkdir -p /opt/wgdashboard/src \
|
&& mkdir -p /opt/wgdashboard/src \
|
||||||
&& python3 -m venv /opt/wgdashboard/src/venv
|
&& python3 -m venv /opt/wgdashboard/src/venv
|
||||||
|
|
||||||
|
# Copy the requirements file into the build layer.
|
||||||
COPY ./src/requirements.txt /opt/wgdashboard/src
|
COPY ./src/requirements.txt /opt/wgdashboard/src
|
||||||
|
RUN if [ "$TARGETPLATFORM" = "linux/arm/v7" ]; then \
|
||||||
|
sed -i 's|psycopg\[binary\]|psycopg[c]|' /opt/wgdashboard/src/requirements.txt; \
|
||||||
|
fi; \
|
||||||
|
cat /opt/wgdashboard/src/requirements.txt
|
||||||
|
|
||||||
|
# Install the pip packages
|
||||||
RUN . /opt/wgdashboard/src/venv/bin/activate && \
|
RUN . /opt/wgdashboard/src/venv/bin/activate && \
|
||||||
pip3 install --upgrade pip && \
|
pip3 install --upgrade pip && \
|
||||||
pip3 install -r /opt/wgdashboard/src/requirements.txt
|
pip3 install -r /opt/wgdashboard/src/requirements.txt
|
||||||
@@ -66,19 +89,18 @@ RUN . /opt/wgdashboard/src/venv/bin/activate && \
|
|||||||
# WGDashboard RUNNING STAGE
|
# WGDashboard RUNNING STAGE
|
||||||
# Base: Alpine
|
# Base: Alpine
|
||||||
#
|
#
|
||||||
FROM python:3.13-alpine AS final
|
|
||||||
|
# Running with the python-alpine image.
|
||||||
|
FROM python:3.14-alpine AS final
|
||||||
LABEL maintainer="dselen@nerthus.nl"
|
LABEL maintainer="dselen@nerthus.nl"
|
||||||
|
|
||||||
# Install only the runtime dependencies
|
# Install only the runtime dependencies
|
||||||
RUN apk add --no-cache \
|
RUN apk add --no-cache \
|
||||||
iproute2 iptables \
|
iproute2 iptables \
|
||||||
bash curl \
|
bash curl procps \
|
||||||
wget unzip \
|
tzdata wireguard-tools
|
||||||
procps sudo \
|
|
||||||
tzdata wireguard-tools \
|
|
||||||
openresolv openrc
|
|
||||||
|
|
||||||
# Copy only the final binaries from the builders
|
# Copy only the final binaries from the AWG builder stages
|
||||||
COPY --from=awg-go /usr/bin/amneziawg-go /usr/bin/amneziawg-go
|
COPY --from=awg-go /usr/bin/amneziawg-go /usr/bin/amneziawg-go
|
||||||
COPY --from=awg-tools /workspace/awg-tools/src/wg /usr/bin/awg
|
COPY --from=awg-tools /workspace/awg-tools/src/wg /usr/bin/awg
|
||||||
COPY --from=awg-tools /workspace/awg-tools/src/wg-quick/linux.bash /usr/bin/awg-quick
|
COPY --from=awg-tools /workspace/awg-tools/src/wg-quick/linux.bash /usr/bin/awg-quick
|
||||||
@@ -92,14 +114,14 @@ ENV TZ="Europe/Amsterdam" \
|
|||||||
public_ip="" \
|
public_ip="" \
|
||||||
WGDASH=/opt/wgdashboard
|
WGDASH=/opt/wgdashboard
|
||||||
|
|
||||||
# Create directories
|
# Create directories needed for operation
|
||||||
RUN mkdir /data /configs -p ${WGDASH}/src /etc/amnezia/amneziawg
|
RUN mkdir /data /configs -p ${WGDASH}/src /etc/amnezia/amneziawg
|
||||||
|
|
||||||
# Copy app source and prebuilt venv only (no pip cache)
|
# Copy the python virtual environment from the pip-builder stage
|
||||||
COPY ./src ${WGDASH}/src
|
COPY ./src ${WGDASH}/src
|
||||||
COPY --from=pip-builder /opt/wgdashboard/src/venv /opt/wgdashboard/src/venv
|
COPY --from=pip-builder /opt/wgdashboard/src/venv /opt/wgdashboard/src/venv
|
||||||
|
|
||||||
# WireGuard interface template
|
# First WireGuard interface template
|
||||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||||
RUN out_adapt=$(ip -o -4 route show to default | awk '{print $NF}') \
|
RUN out_adapt=$(ip -o -4 route show to default | awk '{print $NF}') \
|
||||||
&& echo -e "[Interface]\n\
|
&& echo -e "[Interface]\n\
|
||||||
@@ -114,11 +136,14 @@ SaveConfig = true\n\
|
|||||||
DNS = ${global_dns}" > /configs/wg0.conf.template \
|
DNS = ${global_dns}" > /configs/wg0.conf.template \
|
||||||
&& chmod 600 /configs/wg0.conf.template
|
&& chmod 600 /configs/wg0.conf.template
|
||||||
|
|
||||||
|
# Set a healthcheck to determine the container its health
|
||||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||||
CMD sh -c 'pgrep gunicorn > /dev/null && pgrep tail > /dev/null' || exit 1
|
CMD sh -c 'pgrep gunicorn > /dev/null && pgrep tail > /dev/null' || exit 1
|
||||||
|
|
||||||
|
# Copy in the runtime script, essential.
|
||||||
COPY ./docker/entrypoint.sh /entrypoint.sh
|
COPY ./docker/entrypoint.sh /entrypoint.sh
|
||||||
|
|
||||||
|
# Expose ports on the container
|
||||||
EXPOSE 10086
|
EXPOSE 10086
|
||||||
WORKDIR $WGDASH/src
|
WORKDIR $WGDASH/src
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ Author: @DaanSelen<br>
|
|||||||
|
|
||||||
This document delves into how the WGDashboard Docker container has been built.<br>
|
This document delves into how the WGDashboard Docker container has been built.<br>
|
||||||
Of course there are two stages (simply said), one before run-time and one at/after run-time.<br>
|
Of course there are two stages (simply said), one before run-time and one at/after run-time.<br>
|
||||||
The `Dockerfile` describes how the container image is made, and the `entrypoint.sh` is executed after running the container. <br>
|
The `Dockerfile` describes how the container image is made, and the `entrypoint.sh` is executed after the container is started. <br>
|
||||||
In this example, WireGuard is integrated into the container itself, so it should be a run-and-go(/out-of-the-box).<br>
|
In this example, [WireGuard](https://www.wireguard.com/) is integrated into the container itself, so it should be a run-and-go(/out-of-the-box) experience.<br>
|
||||||
For more details on the source-code specific to this Docker image, refer to the source files, they have lots of comments.
|
For more details on the source-code specific to this Docker image, refer to the source files, they have lots of comments.
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
@@ -18,20 +18,24 @@ For more details on the source-code specific to this Docker image, refer to the
|
|||||||
/>
|
/>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
To get the container running you either pull the image from the repository, (docker.io)`donaldzou/wgdashboard:latest`.<br>
|
To get the container running you either pull the pre-made image from a remote repository, there are 2 official options.<br>
|
||||||
From there either use the environment variables describe below as parameters or use the Docker Compose file: `compose.yaml`.<br>
|
|
||||||
Be careful, the default generated WireGuard configuration file uses port 51820/udp. So use this port if you want to use it out of the box.<br>
|
- ghcr.io/wgdashboard/wgdashboard:<tag>
|
||||||
Otherwise edit the configuration file in `/etc/wireguard/wg0.conf`.
|
- docker.io/donaldzou/wgdashboard:<tag>
|
||||||
|
|
||||||
|
> tags should be either: latest, main, <version> or <commit-sha>.
|
||||||
|
|
||||||
|
From there either use the environment variables described below as parameters or use the Docker Compose file: `compose.yaml`.<br>
|
||||||
|
Be careful, the default generated WireGuard configuration file uses port 51820/udp. So make sure to use this port if you want to use it out of the box.<br>
|
||||||
|
Otherwise edit the configuration file in WGDashboard under `Configuration Settings` -> `Edit Raw Configuration File`.
|
||||||
|
|
||||||
|
> Otherwise you need to enter the container and edit: `/etc/wireguard/wg0.conf`.
|
||||||
|
|
||||||
# WGDashboard: 🐳 Docker Deployment Guide
|
# WGDashboard: 🐳 Docker Deployment Guide
|
||||||
|
|
||||||
To run the container, you can either pull the image from Docker Hub or build it yourself. The image is available at:
|
To run the container, you can either pull the image from the Github Container Registry (ghcr.io), Docker Hub (docker.io) or build it yourself. The image is available at:
|
||||||
|
|
||||||
```
|
> `docker.io` is in most cases automatically resolved by the Docker application. Therefor you can ofter specify: `donaldzou/wgdashboard:latest`
|
||||||
docker.io/donaldzou/wgdashboard:latest
|
|
||||||
```
|
|
||||||
|
|
||||||
> `docker.io` is in most cases automatically resolved by the Docker application.
|
|
||||||
|
|
||||||
### 🔧 Quick Docker Run Command
|
### 🔧 Quick Docker Run Command
|
||||||
|
|
||||||
@@ -44,7 +48,7 @@ docker run -d \
|
|||||||
-p 10086:10086/tcp \
|
-p 10086:10086/tcp \
|
||||||
-p 51820:51820/udp \
|
-p 51820:51820/udp \
|
||||||
--cap-add NET_ADMIN \
|
--cap-add NET_ADMIN \
|
||||||
donaldzou/wgdashboard:latest
|
ghcr.io/wgdashboard/wgdashboard:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
> ⚠️ The default WireGuard port is `51820/udp`. If you change this, update the `/etc/wireguard/wg0.conf` accordingly.
|
> ⚠️ The default WireGuard port is `51820/udp`. If you change this, update the `/etc/wireguard/wg0.conf` accordingly.
|
||||||
@@ -58,23 +62,24 @@ You can also use Docker Compose for easier configuration:
|
|||||||
```yaml
|
```yaml
|
||||||
services:
|
services:
|
||||||
wgdashboard:
|
wgdashboard:
|
||||||
image: donaldzou/wgdashboard:latest
|
image: ghcr.io/wgdashboard/wgdashboard:latest
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
container_name: wgdashboard
|
container_name: wgdashboard
|
||||||
environment:
|
|
||||||
# - tz=Europe/Amsterdam
|
|
||||||
# - global_dns=1.1.1.1
|
|
||||||
# - public_ip=YOUR_PUBLIC_IP
|
|
||||||
ports:
|
ports:
|
||||||
- 10086:10086/tcp
|
- 10086:10086/tcp
|
||||||
- 51820:51820/udp
|
- 51820:51820/udp
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
|
- aconf:/etc/amnezia/amneziawg
|
||||||
- conf:/etc/wireguard
|
- conf:/etc/wireguard
|
||||||
- data:/data
|
- data:/data
|
||||||
|
|
||||||
cap_add:
|
cap_add:
|
||||||
- NET_ADMIN
|
- NET_ADMIN
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
|
aconf:
|
||||||
conf:
|
conf:
|
||||||
data:
|
data:
|
||||||
```
|
```
|
||||||
@@ -85,7 +90,7 @@ volumes:
|
|||||||
|
|
||||||
## 🔄 Updating the Container
|
## 🔄 Updating the Container
|
||||||
|
|
||||||
Updating WGDashboard is currently in **alpha** stage. While the update process may work, it's still under testing.
|
Updating the WGDashboard container should be through 'The Docker Way' - by pulling the newest/newer image and replacing this old one.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,22 +1,41 @@
|
|||||||
services:
|
services:
|
||||||
wireguard-dashboard:
|
wgdashboard:
|
||||||
image: donaldzou/wgdashboard:latest
|
# Since the github organisation we recommend the ghcr.io.
|
||||||
|
# Alternatively we also still push to docker.io under donaldzou/wgdashboard.
|
||||||
|
# Both share the exact same tags. So they should be interchangable.
|
||||||
|
image: ghcr.io/wgdashboard/wgdashboard:latest
|
||||||
|
|
||||||
|
# Make sure to set the restart policy. Because for a VPN its important to come back IF it crashes.
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
container_name: wgdashboard
|
container_name: wgdashboard
|
||||||
|
|
||||||
|
# Environment variables can be used to configure certain values at startup. Without having to configure it from the dashboard.
|
||||||
|
# By default its all disabled, but uncomment the following lines to apply these. (uncommenting is removing the # character)
|
||||||
|
# Refer to the documentation on https://wgdashboard.dev/ for more info on what everything means.
|
||||||
#environment:
|
#environment:
|
||||||
#- tz= # <--- Set container timezone, default: Europe/Amsterdam.
|
#- tz= # <--- Set container timezone, default: Europe/Amsterdam.
|
||||||
#- public_ip= # <--- Set public IP to ensure the correct one is chosen, defaulting to the IP give by ifconfig.me.
|
#- public_ip= # <--- Set public IP to ensure the correct one is chosen, defaulting to the IP give by ifconfig.me.
|
||||||
#- wgd_port= # <--- Set the port WGDashboard will use for its web-server.
|
#- wgd_port= # <--- Set the port WGDashboard will use for its web-server.
|
||||||
|
|
||||||
|
# The following section, ports is very important for exposing more than one Wireguard/AmneziaWireguard interfaces.
|
||||||
|
# Once you create a new configuration and assign a port in the dashboard, don't forget to add it to the ports as well.
|
||||||
|
# Quick-tip: most Wireguard VPN tunnels use UDP. WGDashboard uses HTTP, so tcp.
|
||||||
ports:
|
ports:
|
||||||
- 10086:10086/tcp
|
- 10086:10086/tcp
|
||||||
- 51820:51820/udp
|
- 51820:51820/udp
|
||||||
|
|
||||||
|
# Volumes can be configured however you'd like. The default is using docker volumes.
|
||||||
|
# If you want to use local paths, replace the path before the : with your path.
|
||||||
volumes:
|
volumes:
|
||||||
- aconf:/etc/amnezia/amneziawg
|
- aconf:/etc/amnezia/amneziawg
|
||||||
- conf:/etc/wireguard
|
- conf:/etc/wireguard
|
||||||
- data:/data
|
- data:/data
|
||||||
|
|
||||||
|
# Needed for network administration.
|
||||||
cap_add:
|
cap_add:
|
||||||
- NET_ADMIN
|
- NET_ADMIN
|
||||||
|
|
||||||
|
# The following configuration is linked to the above default volumes.
|
||||||
volumes:
|
volumes:
|
||||||
aconf:
|
aconf:
|
||||||
conf:
|
conf:
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ trap 'stop_service' SIGTERM
|
|||||||
|
|
||||||
# Hash password with bcrypt
|
# Hash password with bcrypt
|
||||||
hash_password() {
|
hash_password() {
|
||||||
python3 -c "import bcrypt; print(bcrypt.hashpw('$1'.encode(), bcrypt.gensalt(12)).decode())"
|
${WGDASH}/src/venv/bin/python3 -c "import bcrypt; print(bcrypt.hashpw('$1'.encode(), bcrypt.gensalt(12)).decode())"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Function to set or update section/key/value in the INI file
|
# Function to set or update section/key/value in the INI file
|
||||||
@@ -22,7 +22,7 @@ set_ini() {
|
|||||||
if grep -q "^[[:space:]]*${key}[[:space:]]*=" "$config_file"; then
|
if grep -q "^[[:space:]]*${key}[[:space:]]*=" "$config_file"; then
|
||||||
current_value=$(grep "^[[:space:]]*${key}[[:space:]]*=" "$config_file" | cut -d= -f2- | xargs)
|
current_value=$(grep "^[[:space:]]*${key}[[:space:]]*=" "$config_file" | cut -d= -f2- | xargs)
|
||||||
|
|
||||||
# Don't display actual value if it's a password field
|
# Dont display actual value if it's a password field
|
||||||
if [[ "$key" == *"password"* ]]; then
|
if [[ "$key" == *"password"* ]]; then
|
||||||
if [ "$current_value" = "$value" ]; then
|
if [ "$current_value" = "$value" ]; then
|
||||||
echo "- $key is already set correctly (value hidden)"
|
echo "- $key is already set correctly (value hidden)"
|
||||||
@@ -96,16 +96,8 @@ ensure_installation() {
|
|||||||
ln -s "${config_file}" "${WGDASH}/src/wg-dashboard.ini"
|
ln -s "${config_file}" "${WGDASH}/src/wg-dashboard.ini"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Create the Python virtual environment.
|
|
||||||
. "${WGDASH}/src/venv/bin/activate"
|
|
||||||
|
|
||||||
# Use the bash interpreter to install WGDashboard according to the wgd.sh script.
|
|
||||||
/bin/bash ./wgd.sh install
|
|
||||||
|
|
||||||
echo "Looks like the installation succeeded. Moving on."
|
|
||||||
|
|
||||||
# Setup WireGuard if needed
|
# Setup WireGuard if needed
|
||||||
if [ ! -f "/etc/wireguard/wg0.conf" ]; then
|
if [ -z "$(ls -A /etc/wireguard)" ]; then
|
||||||
cp -a "/configs/wg0.conf.template" "/etc/wireguard/wg0.conf"
|
cp -a "/configs/wg0.conf.template" "/etc/wireguard/wg0.conf"
|
||||||
|
|
||||||
echo "Setting a secure private key."
|
echo "Setting a secure private key."
|
||||||
@@ -196,26 +188,56 @@ start_and_monitor() {
|
|||||||
chmod 600 /dev/net/tun
|
chmod 600 /dev/net/tun
|
||||||
|
|
||||||
# Actually starting WGDashboard
|
# Actually starting WGDashboard
|
||||||
echo "Activating Python venv and executing the WireGuard Dashboard service."
|
echo "Starting WGDashboard directly with Gunicorn..."
|
||||||
bash ./wgd.sh start
|
|
||||||
|
[[ ! -d ${WGDASH}/src/log ]] && mkdir ${WGDASH}/src/log
|
||||||
|
${WGDASH}/src/venv/bin/gunicorn --config ${WGDASH}/src/gunicorn.conf.py
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "Loading WGDashboard failed... Look above for details."
|
||||||
|
fi
|
||||||
|
|
||||||
# Wait a second before continuing, to give the python program some time to get ready.
|
# Wait a second before continuing, to give the python program some time to get ready.
|
||||||
sleep 1
|
|
||||||
echo -e "\nEnsuring container continuation."
|
echo -e "\nEnsuring container continuation."
|
||||||
|
|
||||||
# Find and monitor log file
|
max_rounds="10"
|
||||||
local logdir="${WGDASH}/src/log"
|
round="0"
|
||||||
latestErrLog=$(find "$logdir" -name "error_*.log" -type f -print | sort -r | head -n 1)
|
|
||||||
|
|
||||||
# Only tail the logs if they are found
|
# Hang in there for 10s for Gunicorn to get ready
|
||||||
if [ -n "$latestErrLog" ]; then
|
while true; do
|
||||||
tail -f "$latestErrLog" &
|
round=$((round + 1))
|
||||||
# Wait for the tail process to end.
|
latest_error=$(ls -t ${WGDASH}/src/log/error_*.log 2> /dev/null | head -n 1)
|
||||||
wait $!
|
|
||||||
else
|
if [[ $round -eq $max_rounds ]]; then
|
||||||
echo "No log files found to tail. Something went wrong, exiting..."
|
echo "Reached breaking point!"
|
||||||
|
break
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z $latest_error ]]; then
|
||||||
|
echo -e "Logs not yet present! Retrying in 1 second!"
|
||||||
|
sleep 1s
|
||||||
|
|
||||||
|
else
|
||||||
|
break
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z $latest_error ]]; then
|
||||||
|
echo -e "No error logs founds... Please investigate.\nExiting in 3 minutes..."
|
||||||
|
sleep 180s
|
||||||
exit 1
|
exit 1
|
||||||
|
|
||||||
|
else
|
||||||
|
tail -f "$latest_error" &
|
||||||
|
wait $!
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo "The blocking command has been broken! Script will exit in 3 minutes... Investigate!"
|
||||||
|
sleep 180s
|
||||||
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Main execution flow
|
# Main execution flow
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
version: "1.0"
|
|
||||||
linter: jetbrains/qodana-python:2024.3
|
|
||||||
profile:
|
|
||||||
name: qodana.recommended
|
|
||||||
include:
|
|
||||||
- name: CheckDependencyLicenses
|
|
||||||
@@ -93,8 +93,10 @@ def peerInformationBackgroundThread():
|
|||||||
c.getPeersEndpoint()
|
c.getPeersEndpoint()
|
||||||
c.getPeers()
|
c.getPeers()
|
||||||
if delay == 6:
|
if delay == 6:
|
||||||
c.logPeersTraffic()
|
if c.configurationInfo.PeerTrafficTracking:
|
||||||
c.logPeersHistoryEndpoint()
|
c.logPeersTraffic()
|
||||||
|
if c.configurationInfo.PeerHistoricalEndpointTracking:
|
||||||
|
c.logPeersHistoryEndpoint()
|
||||||
c.getRestrictedPeersList()
|
c.getRestrictedPeersList()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
app.logger.error(f"[WGDashboard] Background Thread #1 Error", e)
|
app.logger.error(f"[WGDashboard] Background Thread #1 Error", e)
|
||||||
@@ -194,7 +196,7 @@ with app.app_context():
|
|||||||
DashboardConfig = DashboardConfig()
|
DashboardConfig = DashboardConfig()
|
||||||
EmailSender = EmailSender(DashboardConfig)
|
EmailSender = EmailSender(DashboardConfig)
|
||||||
AllPeerShareLinks: PeerShareLinks = PeerShareLinks(DashboardConfig, WireguardConfigurations)
|
AllPeerShareLinks: PeerShareLinks = PeerShareLinks(DashboardConfig, WireguardConfigurations)
|
||||||
AllPeerJobs: PeerJobs = PeerJobs(DashboardConfig, WireguardConfigurations)
|
AllPeerJobs: PeerJobs = PeerJobs(DashboardConfig, WireguardConfigurations, AllPeerShareLinks)
|
||||||
DashboardLogger: DashboardLogger = DashboardLogger()
|
DashboardLogger: DashboardLogger = DashboardLogger()
|
||||||
DashboardPlugins: DashboardPlugins = DashboardPlugins(app, WireguardConfigurations)
|
DashboardPlugins: DashboardPlugins = DashboardPlugins(app, WireguardConfigurations)
|
||||||
DashboardWebHooks: DashboardWebHooks = DashboardWebHooks(DashboardConfig)
|
DashboardWebHooks: DashboardWebHooks = DashboardWebHooks(DashboardConfig)
|
||||||
@@ -223,13 +225,6 @@ def auth_req():
|
|||||||
return ResponseObject(True)
|
return ResponseObject(True)
|
||||||
|
|
||||||
DashboardConfig.APIAccessed = False
|
DashboardConfig.APIAccessed = False
|
||||||
if "api" in request.path:
|
|
||||||
if str(request.method) == "GET":
|
|
||||||
DashboardLogger.log(str(request.url), str(request.remote_addr), Message=str(request.args))
|
|
||||||
elif str(request.method) == "POST":
|
|
||||||
DashboardLogger.log(str(request.url), str(request.remote_addr), Message=f"Request Args: {str(request.args)} Body:{str(request.get_json())}")
|
|
||||||
|
|
||||||
|
|
||||||
authenticationRequired = DashboardConfig.GetConfig("Server", "auth_req")[1]
|
authenticationRequired = DashboardConfig.GetConfig("Server", "auth_req")[1]
|
||||||
d = request.headers
|
d = request.headers
|
||||||
if authenticationRequired:
|
if authenticationRequired:
|
||||||
@@ -1090,12 +1085,10 @@ def API_GetPeerTraffics():
|
|||||||
interval = request.args.get('interval', 30)
|
interval = request.args.get('interval', 30)
|
||||||
startDate = request.args.get('startDate', None)
|
startDate = request.args.get('startDate', None)
|
||||||
endDate = request.args.get('endDate', None)
|
endDate = request.args.get('endDate', None)
|
||||||
|
|
||||||
if type(interval) is str:
|
if type(interval) is str:
|
||||||
if not interval.isdigit():
|
if not interval.isdigit():
|
||||||
return ResponseObject(False, "Interval must be integers in minutes")
|
return ResponseObject(False, "Interval must be integers in minutes")
|
||||||
interval = int(interval)
|
interval = int(interval)
|
||||||
|
|
||||||
if startDate is None:
|
if startDate is None:
|
||||||
endDate = None
|
endDate = None
|
||||||
else:
|
else:
|
||||||
@@ -1113,6 +1106,44 @@ def API_GetPeerTraffics():
|
|||||||
return ResponseObject(data=p.getTraffics(interval, startDate, endDate))
|
return ResponseObject(data=p.getTraffics(interval, startDate, endDate))
|
||||||
return ResponseObject(False, "Peer does not exist")
|
return ResponseObject(False, "Peer does not exist")
|
||||||
|
|
||||||
|
@app.get(f'{APP_PREFIX}/api/getPeerTrackingTableCounts')
|
||||||
|
def API_GetPeerTrackingTableCounts():
|
||||||
|
configurationName = request.args.get("configurationName")
|
||||||
|
if configurationName not in WireguardConfigurations.keys():
|
||||||
|
return ResponseObject(False, "Configuration does not exist")
|
||||||
|
c = WireguardConfigurations.get(configurationName)
|
||||||
|
return ResponseObject(data={
|
||||||
|
"TrafficTrackingTableSize": c.getTransferTableSize(),
|
||||||
|
"HistoricalTrackingTableSize": c.getHistoricalEndpointTableSize()
|
||||||
|
})
|
||||||
|
|
||||||
|
@app.get(f'{APP_PREFIX}/api/downloadPeerTrackingTable')
|
||||||
|
def API_DownloadPeerTackingTable():
|
||||||
|
configurationName = request.args.get("configurationName")
|
||||||
|
table = request.args.get('table')
|
||||||
|
if configurationName not in WireguardConfigurations.keys():
|
||||||
|
return ResponseObject(False, "Configuration does not exist")
|
||||||
|
if table not in ['TrafficTrackingTable', 'HistoricalTrackingTable']:
|
||||||
|
return ResponseObject(False, "Table does not exist")
|
||||||
|
c = WireguardConfigurations.get(configurationName)
|
||||||
|
return ResponseObject(
|
||||||
|
data=c.downloadTransferTable() if table == 'TrafficTrackingTable'
|
||||||
|
else c.downloadHistoricalEndpointTable())
|
||||||
|
|
||||||
|
@app.post(f'{APP_PREFIX}/api/deletePeerTrackingTable')
|
||||||
|
def API_DeletePeerTrackingTable():
|
||||||
|
data = request.get_json()
|
||||||
|
configurationName = data.get('configurationName')
|
||||||
|
table = data.get('table')
|
||||||
|
if not configurationName or configurationName not in WireguardConfigurations.keys():
|
||||||
|
return ResponseObject(False, "Configuration does not exist")
|
||||||
|
if not table or table not in ['TrafficTrackingTable', 'HistoricalTrackingTable']:
|
||||||
|
return ResponseObject(False, "Table does not exist")
|
||||||
|
c = WireguardConfigurations.get(configurationName)
|
||||||
|
return ResponseObject(
|
||||||
|
status=c.deleteTransferTable() if table == 'TrafficTrackingTable'
|
||||||
|
else c.deleteHistoryEndpointTable())
|
||||||
|
|
||||||
@app.get(f'{APP_PREFIX}/api/getDashboardTheme')
|
@app.get(f'{APP_PREFIX}/api/getDashboardTheme')
|
||||||
def API_getDashboardTheme():
|
def API_getDashboardTheme():
|
||||||
return ResponseObject(data=DashboardConfig.GetConfig("Server", "dashboard_theme")[1])
|
return ResponseObject(data=DashboardConfig.GetConfig("Server", "dashboard_theme")[1])
|
||||||
|
|||||||
@@ -174,8 +174,6 @@ class AmneziaWireguardConfiguration(WireguardConfiguration):
|
|||||||
|
|
||||||
def getPeers(self):
|
def getPeers(self):
|
||||||
self.Peers.clear()
|
self.Peers.clear()
|
||||||
current_app.logger.info(f"Refreshing {self.Name} peer list")
|
|
||||||
|
|
||||||
if self.configurationFileChanged():
|
if self.configurationFileChanged():
|
||||||
with open(self.configPath, 'r') as configFile:
|
with open(self.configPath, 'r') as configFile:
|
||||||
p = []
|
p = []
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ from .DashboardAPIKey import DashboardAPIKey
|
|||||||
|
|
||||||
|
|
||||||
class DashboardConfig:
|
class DashboardConfig:
|
||||||
DashboardVersion = 'v4.3.0.1'
|
DashboardVersion = 'v4.3.0.4'
|
||||||
ConfigurationPath = os.getenv('CONFIGURATION_PATH', '.')
|
ConfigurationPath = os.getenv('CONFIGURATION_PATH', '.')
|
||||||
ConfigurationFilePath = os.path.join(ConfigurationPath, 'wg-dashboard.ini')
|
ConfigurationFilePath = os.path.join(ConfigurationPath, 'wg-dashboard.ini')
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,12 @@
|
|||||||
Peer Job Logger
|
Peer Job Logger
|
||||||
"""
|
"""
|
||||||
import uuid
|
import uuid
|
||||||
|
from typing import Sequence
|
||||||
|
|
||||||
import sqlalchemy as db
|
import sqlalchemy as db
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
|
from sqlalchemy import RowMapping
|
||||||
|
|
||||||
from .ConnectionString import ConnectionString
|
from .ConnectionString import ConnectionString
|
||||||
from .Log import Log
|
from .Log import Log
|
||||||
|
|
||||||
@@ -57,3 +61,42 @@ class PeerJobLogger:
|
|||||||
current_app.logger.error(f"Getting Peer Job Log Error", e)
|
current_app.logger.error(f"Getting Peer Job Log Error", e)
|
||||||
return logs
|
return logs
|
||||||
return logs
|
return logs
|
||||||
|
|
||||||
|
def getFailingJobs(self) -> Sequence[RowMapping]:
|
||||||
|
with self.engine.connect() as conn:
|
||||||
|
table = conn.execute(
|
||||||
|
db.select(
|
||||||
|
self.jobLogTable.c.JobID
|
||||||
|
).where(
|
||||||
|
(db.or_(
|
||||||
|
self.jobLogTable.c.Status == 'false',
|
||||||
|
self.jobLogTable.c.Status == 0
|
||||||
|
) if conn.dialect.name == 'sqlite' else self.jobLogTable.c.Status == 'false')
|
||||||
|
).group_by(
|
||||||
|
self.jobLogTable.c.JobID
|
||||||
|
).having(
|
||||||
|
db.func.count(
|
||||||
|
self.jobLogTable.c.JobID
|
||||||
|
) > 10
|
||||||
|
)
|
||||||
|
).mappings().fetchall()
|
||||||
|
return table
|
||||||
|
|
||||||
|
def deleteLogs(self, LogID = None, JobID = None):
|
||||||
|
with self.engine.begin() as conn:
|
||||||
|
print(f"[WGDashboard] Deleted stale logs of JobID: {JobID}")
|
||||||
|
conn.execute(
|
||||||
|
self.jobLogTable.delete().where(
|
||||||
|
db.and_(
|
||||||
|
(self.jobLogTable.c.LogID == LogID if LogID is not None else True),
|
||||||
|
(self.jobLogTable.c.JobID == JobID if JobID is not None else True),
|
||||||
|
db.or_(self.jobLogTable.c.Status == 0, self.jobLogTable.c.Status == 'false')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def vacuum(self):
|
||||||
|
with self.engine.begin() as conn:
|
||||||
|
if conn.dialect.name == 'sqlite':
|
||||||
|
print("[WGDashboard] SQLite Vacuuming PeerJogLogs Database")
|
||||||
|
conn.execute(db.text('VACUUM;'))
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
"""
|
"""
|
||||||
Peer Jobs
|
Peer Jobs
|
||||||
"""
|
"""
|
||||||
|
import sqlalchemy
|
||||||
|
|
||||||
from .ConnectionString import ConnectionString
|
from .ConnectionString import ConnectionString
|
||||||
from .PeerJob import PeerJob
|
from .PeerJob import PeerJob
|
||||||
from .PeerJobLogger import PeerJobLogger
|
from .PeerJobLogger import PeerJobLogger
|
||||||
@@ -9,7 +11,7 @@ from datetime import datetime
|
|||||||
from flask import current_app
|
from flask import current_app
|
||||||
|
|
||||||
class PeerJobs:
|
class PeerJobs:
|
||||||
def __init__(self, DashboardConfig, WireguardConfigurations):
|
def __init__(self, DashboardConfig, WireguardConfigurations, AllPeerShareLinks):
|
||||||
self.Jobs: list[PeerJob] = []
|
self.Jobs: list[PeerJob] = []
|
||||||
self.engine = db.create_engine(ConnectionString('wgdashboard_job'))
|
self.engine = db.create_engine(ConnectionString('wgdashboard_job'))
|
||||||
self.metadata = db.MetaData()
|
self.metadata = db.MetaData()
|
||||||
@@ -28,6 +30,8 @@ class PeerJobs:
|
|||||||
self.__getJobs()
|
self.__getJobs()
|
||||||
self.JobLogger: PeerJobLogger = PeerJobLogger(self, DashboardConfig)
|
self.JobLogger: PeerJobLogger = PeerJobLogger(self, DashboardConfig)
|
||||||
self.WireguardConfigurations = WireguardConfigurations
|
self.WireguardConfigurations = WireguardConfigurations
|
||||||
|
self.AllPeerShareLinks = AllPeerShareLinks
|
||||||
|
self.cleanJob(init=True)
|
||||||
|
|
||||||
def __getJobs(self):
|
def __getJobs(self):
|
||||||
self.Jobs.clear()
|
self.Jobs.clear()
|
||||||
@@ -116,7 +120,7 @@ class PeerJobs:
|
|||||||
}
|
}
|
||||||
).where(self.peerJobTable.columns.JobID == Job.JobID)
|
).where(self.peerJobTable.columns.JobID == Job.JobID)
|
||||||
)
|
)
|
||||||
self.JobLogger.log(Job.JobID, Message=f"Job is removed due to being deleted or finshed.")
|
self.JobLogger.log(Job.JobID, Message=f"Job is removed due to being deleted or finished.")
|
||||||
self.__getJobs()
|
self.__getJobs()
|
||||||
self.WireguardConfigurations.get(Job.Configuration).searchPeer(Job.Peer)[1].getJobs()
|
self.WireguardConfigurations.get(Job.Configuration).searchPeer(Job.Peer)[1].getJobs()
|
||||||
return True, None
|
return True, None
|
||||||
@@ -141,7 +145,7 @@ class PeerJobs:
|
|||||||
|
|
||||||
|
|
||||||
def runJob(self):
|
def runJob(self):
|
||||||
current_app.logger.info("Running scheduled jobs")
|
self.cleanJob()
|
||||||
needToDelete = []
|
needToDelete = []
|
||||||
self.__getJobs()
|
self.__getJobs()
|
||||||
for job in self.Jobs:
|
for job in self.Jobs:
|
||||||
@@ -162,7 +166,7 @@ class PeerJobs:
|
|||||||
if job.Action == "restrict":
|
if job.Action == "restrict":
|
||||||
s, msg = c.restrictPeers([fp.id])
|
s, msg = c.restrictPeers([fp.id])
|
||||||
elif job.Action == "delete":
|
elif job.Action == "delete":
|
||||||
s, msg = c.deletePeers([fp.id])
|
s, msg = c.deletePeers([fp.id], self, self.AllPeerShareLinks)
|
||||||
elif job.Action == "reset_total_data_usage":
|
elif job.Action == "reset_total_data_usage":
|
||||||
s = fp.resetDataUsage("total")
|
s = fp.resetDataUsage("total")
|
||||||
c.restrictPeers([fp.id])
|
c.restrictPeers([fp.id])
|
||||||
@@ -171,26 +175,42 @@ class PeerJobs:
|
|||||||
self.JobLogger.log(job.JobID, s,
|
self.JobLogger.log(job.JobID, s,
|
||||||
f"Peer {fp.id} from {c.Name} is successfully {job.Action}ed."
|
f"Peer {fp.id} from {c.Name} is successfully {job.Action}ed."
|
||||||
)
|
)
|
||||||
current_app.logger.info(f"Peer {fp.id} from {c.Name} is successfully {job.Action}ed.")
|
|
||||||
needToDelete.append(job)
|
needToDelete.append(job)
|
||||||
else:
|
else:
|
||||||
current_app.logger.info(f"Peer {fp.id} from {c.Name} is failed {job.Action}ed.")
|
|
||||||
self.JobLogger.log(job.JobID, s,
|
self.JobLogger.log(job.JobID, s,
|
||||||
f"Peer {fp.id} from {c.Name} failed {job.Action}ed."
|
f"Peer {fp.id} from {c.Name} failed {job.Action}ed."
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
current_app.logger.warning(f"Somehow can't find this peer {job.Peer} from {c.Name} failed {job.Action}ed.")
|
|
||||||
self.JobLogger.log(job.JobID, False,
|
self.JobLogger.log(job.JobID, False,
|
||||||
f"Somehow can't find this peer {job.Peer} from {c.Name} failed {job.Action}ed."
|
f"Somehow can't find this peer {job.Peer} from {c.Name} failed {job.Action}ed."
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
current_app.logger.warning(f"Somehow can't find this peer {job.Peer} from {c.Name} failed {job.Action}ed.")
|
|
||||||
self.JobLogger.log(job.JobID, False,
|
self.JobLogger.log(job.JobID, False,
|
||||||
f"Somehow can't find this peer {job.Peer} from {job.Configuration} failed {job.Action}ed."
|
f"Somehow can't find this peer {job.Peer} from {job.Configuration} failed {job.Action}ed."
|
||||||
)
|
)
|
||||||
for j in needToDelete:
|
for j in needToDelete:
|
||||||
self.deleteJob(j)
|
self.deleteJob(j)
|
||||||
|
|
||||||
|
def cleanJob(self, init = False):
|
||||||
|
failingJobs = self.JobLogger.getFailingJobs()
|
||||||
|
with self.engine.begin() as conn:
|
||||||
|
for job in failingJobs:
|
||||||
|
conn.execute(
|
||||||
|
self.peerJobTable.update().values(
|
||||||
|
{
|
||||||
|
"ExpireDate": datetime.now()
|
||||||
|
}
|
||||||
|
).where(self.peerJobTable.columns.JobID == job.get('JobID'))
|
||||||
|
)
|
||||||
|
self.JobLogger.deleteLogs(JobID=job.get('JobID'))
|
||||||
|
self.JobLogger.log(job.get('JobID'), Message=f"Job is removed due to being stale.")
|
||||||
|
|
||||||
|
with self.engine.connect() as conn:
|
||||||
|
if init and conn.dialect.name == 'sqlite':
|
||||||
|
print("[WGDashboard] SQLite Vacuuming PeerJobs Database")
|
||||||
|
self.JobLogger.vacuum()
|
||||||
|
conn.execute(sqlalchemy.text('VACUUM;'))
|
||||||
|
|
||||||
def __runJob_Compare(self, x: float | datetime, y: float | datetime, operator: str):
|
def __runJob_Compare(self, x: float | datetime, y: float | datetime, operator: str):
|
||||||
if operator == "eq":
|
if operator == "eq":
|
||||||
return x == y
|
return x == y
|
||||||
|
|||||||
@@ -160,18 +160,41 @@ class Processes:
|
|||||||
self.CPU_Top_10_Processes: list[Process] = []
|
self.CPU_Top_10_Processes: list[Process] = []
|
||||||
self.Memory_Top_10_Processes: list[Process] = []
|
self.Memory_Top_10_Processes: list[Process] = []
|
||||||
def getData(self):
|
def getData(self):
|
||||||
while True:
|
try:
|
||||||
try:
|
processes = list(psutil.process_iter())
|
||||||
processes = list(psutil.process_iter())
|
|
||||||
self.CPU_Top_10_Processes = sorted(
|
cpu_processes = []
|
||||||
list(map(lambda x : Process(x.name(), " ".join(x.cmdline()), x.pid, x.cpu_percent()), processes)),
|
memory_processes = []
|
||||||
key=lambda x : x.percent, reverse=True)[:20]
|
|
||||||
self.Memory_Top_10_Processes = sorted(
|
for proc in processes:
|
||||||
list(map(lambda x : Process(x.name(), " ".join(x.cmdline()), x.pid, x.memory_percent()), processes)),
|
try:
|
||||||
key=lambda x : x.percent, reverse=True)[:20]
|
name = proc.name()
|
||||||
break
|
cmdline = " ".join(proc.cmdline())
|
||||||
except Exception as e:
|
pid = proc.pid
|
||||||
current_app.logger.error("Get processes error", e)
|
cpu_percent = proc.cpu_percent()
|
||||||
|
mem_percent = proc.memory_percent()
|
||||||
|
|
||||||
|
# Create Process object for CPU and memory tracking
|
||||||
|
cpu_process = Process(name, cmdline, pid, cpu_percent)
|
||||||
|
mem_process = Process(name, cmdline, pid, mem_percent)
|
||||||
|
|
||||||
|
cpu_processes.append(cpu_process)
|
||||||
|
memory_processes.append(mem_process)
|
||||||
|
|
||||||
|
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
|
||||||
|
# Skip processes we can’t access or that no longer exist
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Sort by CPU and memory usage (descending order)
|
||||||
|
cpu_sorted = sorted(cpu_processes, key=lambda p: p.percent, reverse=True)
|
||||||
|
mem_sorted = sorted(memory_processes, key=lambda p: p.percent, reverse=True)
|
||||||
|
|
||||||
|
# Get top 20 processes for each
|
||||||
|
self.CPU_Top_10_Processes = cpu_sorted[:20]
|
||||||
|
self.Memory_Top_10_Processes = mem_sorted[:20]
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
current_app.logger.error("Get processes error", e)
|
||||||
|
|
||||||
def toJson(self):
|
def toJson(self):
|
||||||
self.getData()
|
self.getData()
|
||||||
|
|||||||
@@ -396,8 +396,6 @@ class WireguardConfiguration:
|
|||||||
|
|
||||||
def getPeers(self):
|
def getPeers(self):
|
||||||
tmpList = []
|
tmpList = []
|
||||||
current_app.logger.info(f"Refreshing {self.Name} peer list")
|
|
||||||
|
|
||||||
if self.configurationFileChanged():
|
if self.configurationFileChanged():
|
||||||
with open(self.configPath, 'r') as configFile:
|
with open(self.configPath, 'r') as configFile:
|
||||||
p = []
|
p = []
|
||||||
@@ -505,13 +503,22 @@ class WireguardConfiguration:
|
|||||||
if tempPeer.status == "running":
|
if tempPeer.status == "running":
|
||||||
endpoint = tempPeer.endpoint.rsplit(":", 1)
|
endpoint = tempPeer.endpoint.rsplit(":", 1)
|
||||||
if len(endpoint) == 2 and len(endpoint[0]) > 0:
|
if len(endpoint) == 2 and len(endpoint[0]) > 0:
|
||||||
conn.execute(
|
exist = conn.execute(
|
||||||
self.peersHistoryEndpointTable.insert().values({
|
self.peersHistoryEndpointTable.select().where(
|
||||||
"id": tempPeer.id,
|
sqlalchemy.and_(
|
||||||
"endpoint": endpoint[0],
|
self.peersHistoryEndpointTable.c.id == tempPeer.id,
|
||||||
"time": datetime.now()
|
self.peersHistoryEndpointTable.c.endpoint == endpoint[0]
|
||||||
})
|
)
|
||||||
)
|
)
|
||||||
|
).mappings().fetchone()
|
||||||
|
if not exist:
|
||||||
|
conn.execute(
|
||||||
|
self.peersHistoryEndpointTable.insert().values({
|
||||||
|
"id": tempPeer.id,
|
||||||
|
"endpoint": endpoint[0],
|
||||||
|
"time": datetime.now()
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
def addPeers(self, peers: list) -> tuple[bool, list, str]:
|
def addPeers(self, peers: list) -> tuple[bool, list, str]:
|
||||||
result = {
|
result = {
|
||||||
@@ -1188,7 +1195,7 @@ class WireguardConfiguration:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def updateConfigurationInfo(self, key: str, value: str | dict[str, str] | dict[str, dict]) -> tuple[bool, Any, str] | tuple[
|
def updateConfigurationInfo(self, key: str, value: str | dict[str, str] | dict[str, dict] | bool) -> tuple[bool, Any, str] | tuple[
|
||||||
bool, str, None] | tuple[bool, None, None]:
|
bool, str, None] | tuple[bool, None, None]:
|
||||||
if key == "Description":
|
if key == "Description":
|
||||||
self.configurationInfo.Description = value
|
self.configurationInfo.Description = value
|
||||||
@@ -1207,9 +1214,12 @@ class WireguardConfiguration:
|
|||||||
for name, data in value.items():
|
for name, data in value.items():
|
||||||
peerGroups[name] = PeerGroupsClass(**data)
|
peerGroups[name] = PeerGroupsClass(**data)
|
||||||
self.configurationInfo.PeerGroups = peerGroups
|
self.configurationInfo.PeerGroups = peerGroups
|
||||||
|
elif key == "PeerTrafficTracking":
|
||||||
|
self.configurationInfo.PeerTrafficTracking = value
|
||||||
|
elif key == "PeerHistoricalEndpointTracking":
|
||||||
|
self.configurationInfo.PeerHistoricalEndpointTracking = value
|
||||||
else:
|
else:
|
||||||
return False, "Key does not exist", None
|
return False, "Key does not exist", None
|
||||||
|
|
||||||
self.storeConfigurationInfo()
|
self.storeConfigurationInfo()
|
||||||
return True, None, None
|
return True, None, None
|
||||||
|
|
||||||
@@ -1227,3 +1237,58 @@ class WireguardConfiguration:
|
|||||||
msg = "Listen Port must be >= 1 and <= 65535"
|
msg = "Listen Port must be >= 1 and <= 65535"
|
||||||
return status, msg
|
return status, msg
|
||||||
|
|
||||||
|
def getTransferTableSize(self):
|
||||||
|
with self.engine.connect() as db:
|
||||||
|
row_count = db.execute(
|
||||||
|
sqlalchemy.select(sqlalchemy.func.count()).select_from(self.peersTransferTable)
|
||||||
|
).scalar()
|
||||||
|
return int(row_count)
|
||||||
|
|
||||||
|
def getHistoricalEndpointTableSize(self):
|
||||||
|
with self.engine.connect() as db:
|
||||||
|
row_count = db.execute(
|
||||||
|
sqlalchemy.select(sqlalchemy.func.count()).select_from(self.peersHistoryEndpointTable)
|
||||||
|
).scalar()
|
||||||
|
return int(row_count)
|
||||||
|
|
||||||
|
def downloadTransferTable(self):
|
||||||
|
with self.engine.connect() as db:
|
||||||
|
data = db.execute(
|
||||||
|
self.peersTransferTable.select()
|
||||||
|
).mappings().fetchall()
|
||||||
|
return data
|
||||||
|
|
||||||
|
def downloadHistoricalEndpointTable(self):
|
||||||
|
with self.engine.connect() as db:
|
||||||
|
data = db.execute(
|
||||||
|
self.peersHistoryEndpointTable.select()
|
||||||
|
).mappings().fetchall()
|
||||||
|
return data
|
||||||
|
|
||||||
|
def deleteTransferTable(self):
|
||||||
|
try:
|
||||||
|
with self.engine.begin() as db:
|
||||||
|
db.execute(
|
||||||
|
self.peersTransferTable.delete()
|
||||||
|
)
|
||||||
|
with self.engine.connect() as conn:
|
||||||
|
if conn.dialect.name == 'sqlite':
|
||||||
|
print("[WGDashboard] SQLite Vacuuming Database")
|
||||||
|
conn.execute(sqlalchemy.text('VACUUM;'))
|
||||||
|
except Exception as e:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def deleteHistoryEndpointTable(self):
|
||||||
|
try:
|
||||||
|
with self.engine.begin() as db:
|
||||||
|
db.execute(
|
||||||
|
self.peersHistoryEndpointTable.delete()
|
||||||
|
)
|
||||||
|
with self.engine.connect() as conn:
|
||||||
|
if conn.dialect.name == 'sqlite':
|
||||||
|
print("[WGDashboard] SQLite Vacuuming Database")
|
||||||
|
conn.execute(sqlalchemy.text('VACUUM;'))
|
||||||
|
except Exception as e:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
@@ -19,3 +19,5 @@ class WireguardConfigurationInfo(BaseModel):
|
|||||||
Description: str = ''
|
Description: str = ''
|
||||||
OverridePeerSettings: OverridePeerSettingsClass = OverridePeerSettingsClass(**{})
|
OverridePeerSettings: OverridePeerSettingsClass = OverridePeerSettingsClass(**{})
|
||||||
PeerGroups: dict[str, PeerGroupsClass] = {}
|
PeerGroups: dict[str, PeerGroupsClass] = {}
|
||||||
|
PeerTrafficTracking: bool = True
|
||||||
|
PeerHistoricalEndpointTracking: bool = True
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
bcrypt
|
bcrypt==5.0.0
|
||||||
ifcfg
|
ifcfg==0.24
|
||||||
psutil
|
psutil==7.1.3
|
||||||
pyotp
|
pyotp==2.9.0
|
||||||
Flask
|
Flask==3.1.2
|
||||||
flask-cors
|
flask-cors==6.0.1
|
||||||
icmplib
|
icmplib==3.0.4
|
||||||
gunicorn
|
gunicorn==23.0.0
|
||||||
requests
|
requests==2.32.5
|
||||||
tcconfig
|
tcconfig==0.30.1
|
||||||
sqlalchemy
|
sqlalchemy==2.0.44
|
||||||
sqlalchemy_utils
|
sqlalchemy_utils==0.42.0
|
||||||
psycopg
|
psycopg[binary]==3.3.2
|
||||||
PyMySQL
|
PyMySQL==1.1.2
|
||||||
tzlocal
|
tzlocal==5.3.1
|
||||||
python-jose
|
python-jose==3.5.0
|
||||||
pydantic
|
pydantic==2.12.5
|
||||||
|
|||||||
2349
src/static/app/package-lock.json
generated
2349
src/static/app/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "app",
|
"name": "app",
|
||||||
"version": "4.3.0.1",
|
"version": "4.3.0.4",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"module": "es2022",
|
"module": "es2022",
|
||||||
@@ -12,11 +12,11 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@volar/language-server": "2.4.23",
|
"@volar/language-server": "2.4.26",
|
||||||
"@vue/language-server": "3.0.5",
|
"@vue/language-server": "3.1.8",
|
||||||
"@vuepic/vue-datepicker": "^11.0.2",
|
"@vuepic/vue-datepicker": "^12.1.0",
|
||||||
"@vueuse/core": "^13.5.0",
|
"@vueuse/core": "^14.0.0",
|
||||||
"@vueuse/shared": "^13.5.0",
|
"@vueuse/shared": "^14.1.0",
|
||||||
"animate.css": "^4.1.1",
|
"animate.css": "^4.1.1",
|
||||||
"bootstrap": "^5.3.2",
|
"bootstrap": "^5.3.2",
|
||||||
"bootstrap-icons": "^1.11.3",
|
"bootstrap-icons": "^1.11.3",
|
||||||
@@ -26,21 +26,21 @@
|
|||||||
"electron-builder": "^26.0.12",
|
"electron-builder": "^26.0.12",
|
||||||
"fuse.js": "^7.0.0",
|
"fuse.js": "^7.0.0",
|
||||||
"i": "^0.3.7",
|
"i": "^0.3.7",
|
||||||
"is-cidr": "^5.0.3",
|
"is-cidr": "^6.0.1",
|
||||||
"npm": "^10.5.0",
|
"npm": "^11.6.4",
|
||||||
"ol": "^10.2.1",
|
"ol": "^10.7.0",
|
||||||
"pinia": "^3.0.3",
|
"pinia": "^3.0.3",
|
||||||
"pinia-plugin-persistedstate": "^4.5.0",
|
"pinia-plugin-persistedstate": "^4.7.1",
|
||||||
"qrcode": "^1.5.3",
|
"qrcode": "^1.5.3",
|
||||||
"qrcodejs": "^1.0.0",
|
"qrcodejs": "^1.0.0",
|
||||||
"simple-code-editor": "^2.0.9",
|
"simple-code-editor": "^2.0.9",
|
||||||
"uuid": "^11.1.0",
|
"uuid": "^13.0.0",
|
||||||
"vue": "^3.5.17",
|
"vue": "^3.5.24",
|
||||||
"vue-chartjs": "^5.3.0",
|
"vue-chartjs": "^5.3.0",
|
||||||
"vue-router": "^4.2.5"
|
"vue-router": "^4.6.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-vue": "^6.0.0",
|
"@vitejs/plugin-vue": "^6.0.0",
|
||||||
"vite": "^7.0.5"
|
"vite": "^7.2.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,11 +77,11 @@ const emits = defineEmits(["backup", "close"])
|
|||||||
</div>
|
</div>
|
||||||
<div v-else-if="backups.length > 0">
|
<div v-else-if="backups.length > 0">
|
||||||
<i class="bi bi-check-circle-fill me-2"></i>
|
<i class="bi bi-check-circle-fill me-2"></i>
|
||||||
<LocaleText :t="'This configuration have ' + backups.length + ' backups'"></LocaleText>
|
<LocaleText :t="'This configuration has ' + backups.length + ' backups'"></LocaleText>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="d-flex align-items-center gap-2">
|
<div v-else class="d-flex align-items-center gap-2">
|
||||||
<i class="bi bi-x-circle-fill me-2"></i>
|
<i class="bi bi-x-circle-fill me-2"></i>
|
||||||
<LocaleText t="This configuration have no backup"></LocaleText>
|
<LocaleText t="This configuration has no backup"></LocaleText>
|
||||||
<a role="button"
|
<a role="button"
|
||||||
@click="emits('backup')"
|
@click="emits('backup')"
|
||||||
class="ms-auto btn btn-sm btn-primary rounded-3">
|
class="ms-auto btn btn-sm btn-primary rounded-3">
|
||||||
|
|||||||
@@ -146,8 +146,8 @@ export default {
|
|||||||
<td v-if="showLogID"><samp class="text-muted">{{log.LogID}}</samp></td>
|
<td v-if="showLogID"><samp class="text-muted">{{log.LogID}}</samp></td>
|
||||||
<td v-if="showJobID"><samp class="text-muted">{{log.JobID}}</samp></td>
|
<td v-if="showJobID"><samp class="text-muted">{{log.JobID}}</samp></td>
|
||||||
<td>
|
<td>
|
||||||
<span class="badge" :class="[log.Status === '1' ? 'text-success-emphasis bg-success-subtle':'text-danger-emphasis bg-danger-subtle']">
|
<span class="badge" :class="[(log.Status === '1' || log.Status === 'true') ? 'text-success-emphasis bg-success-subtle':'text-danger-emphasis bg-danger-subtle']">
|
||||||
{{log.Status === "1" ? 'Success': 'Failed'}}
|
{{(log.Status === "1" || log.Status === "true") ? 'Success': 'Failed'}}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td>{{log.Message}}</td>
|
<td>{{log.Message}}</td>
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<script setup>
|
||||||
|
|
||||||
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
|
import ConfigurationTracking
|
||||||
|
from "@/components/settingsComponent/dashboardWireguardConfigurationTrackingComponents/configurationTracking.vue";
|
||||||
|
import {WireguardConfigurationsStore} from "@/stores/WireguardConfigurationsStore.js";
|
||||||
|
|
||||||
|
const store = WireguardConfigurationsStore()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h6 class="my-2">
|
||||||
|
<LocaleText t="Peer Tracking"></LocaleText>
|
||||||
|
</h6>
|
||||||
|
</div>
|
||||||
|
<div class="card-body d-flex flex-column gap-3">
|
||||||
|
<ConfigurationTracking :configuration="configuration" v-for="configuration in store.Configurations"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,192 @@
|
|||||||
|
<script setup>
|
||||||
|
import {fetchGet, fetchPost} from "@/utilities/fetch.js";
|
||||||
|
import {onMounted, ref, watch} from "vue";
|
||||||
|
import LocaleText from "@/components/text/localeText.vue";
|
||||||
|
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||||
|
|
||||||
|
const props = defineProps(['configuration'])
|
||||||
|
const sizes = ref({
|
||||||
|
HistoricalTrackingTableSize: 0,
|
||||||
|
TrafficTrackingTableSize: 0
|
||||||
|
})
|
||||||
|
const sizeDataLoaded = ref(false)
|
||||||
|
const toggling = ref(false)
|
||||||
|
|
||||||
|
await onMounted(async () => {
|
||||||
|
await loadSizeData();
|
||||||
|
})
|
||||||
|
|
||||||
|
const loadSizeData = async () => {
|
||||||
|
sizeDataLoaded.value = false;
|
||||||
|
await fetchGet("/api/getPeerTrackingTableCounts", {
|
||||||
|
configurationName: props.configuration.Name
|
||||||
|
}, (res) => {
|
||||||
|
sizes.value = res.data;
|
||||||
|
sizeDataLoaded.value = true;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateToggle = async (key) => {
|
||||||
|
toggling.value = true;
|
||||||
|
await fetchPost('/api/updateWireguardConfigurationInfo', {
|
||||||
|
Name: props.configuration.Name,
|
||||||
|
Key: key,
|
||||||
|
Value: props.configuration.Info[key]
|
||||||
|
}, (res) => {
|
||||||
|
console.log(res)
|
||||||
|
toggling.value = false;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const downloading = ref(undefined);
|
||||||
|
const download = async (key) => {
|
||||||
|
downloading.value = key;
|
||||||
|
await fetchGet("/api/downloadPeerTrackingTable", {
|
||||||
|
configurationName: props.configuration.Name,
|
||||||
|
table: key
|
||||||
|
}, (res) => {
|
||||||
|
if (res.status){
|
||||||
|
const s = JSON.stringify(res.data, null, 2)
|
||||||
|
const b = new Blob([s], {
|
||||||
|
type: "application/json"
|
||||||
|
})
|
||||||
|
const url = URL.createObjectURL(b)
|
||||||
|
const a = document.createElement('a')
|
||||||
|
a.href = url;
|
||||||
|
a.download = `${props.configuration.Name}_${key}.json`
|
||||||
|
a.click()
|
||||||
|
downloading.value = undefined;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const confirmDelete = ref("")
|
||||||
|
const deleting = ref(undefined)
|
||||||
|
const dashboardStore = DashboardConfigurationStore()
|
||||||
|
const deleteRecord = async (key) => {
|
||||||
|
deleting.value = true;
|
||||||
|
await fetchPost('/api/deletePeerTrackingTable', {
|
||||||
|
configurationName: props.configuration.Name,
|
||||||
|
table: key
|
||||||
|
}, async(res) => {
|
||||||
|
if (res.status){
|
||||||
|
dashboardStore.newMessage('Server', 'Record deleted', 'success')
|
||||||
|
}else{
|
||||||
|
dashboardStore.newMessage('Server', 'Record delete failed', 'danger')
|
||||||
|
}
|
||||||
|
await loadSizeData()
|
||||||
|
deleting.value = false;
|
||||||
|
confirmDelete.value = ''
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
{{ configuration.Name }}
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row gy-2">
|
||||||
|
<div class="col-sm">
|
||||||
|
<small class="text-muted fw-bold">Peer Traffic Tracking</small>
|
||||||
|
<div class="form-check form-switch">
|
||||||
|
<input class="form-check-input" type="checkbox"
|
||||||
|
:disabled="toggling"
|
||||||
|
@change="updateToggle('PeerTrafficTracking')"
|
||||||
|
v-model="configuration.Info.PeerTrafficTracking" :id="configuration.Name + '_traffic_tracking'">
|
||||||
|
<label class="form-check-label" :for="configuration.Name + '_traffic_tracking'">
|
||||||
|
{{ configuration.Info.PeerTrafficTracking ? 'On':'Off'}}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
<div class="d-flex align-items-start align-items-md-center flex-column flex-md-row gap-2">
|
||||||
|
<h6 class="mb-0">
|
||||||
|
{{ sizes.TrafficTrackingTableSize }} <span class="text-muted fw-normal"><LocaleText t="Records"></LocaleText></span>
|
||||||
|
</h6>
|
||||||
|
<div class="ms-md-auto d-flex gap-2" v-if="confirmDelete !== 'TrafficTrackingTable'">
|
||||||
|
<button class="btn btn-sm bg-primary-subtle text-primary-emphasis rounded-3"
|
||||||
|
:class="{disabled: downloading === 'TrafficTrackingTable'}"
|
||||||
|
@click="download('TrafficTrackingTable')"
|
||||||
|
>
|
||||||
|
<i class="bi bi-download me-2 "></i>
|
||||||
|
<LocaleText :t="downloading === 'TrafficTrackingTable' ? 'Downloading...':'Download'"></LocaleText>
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-sm bg-danger-subtle text-danger-emphasis rounded-3" @click="confirmDelete = 'TrafficTrackingTable'">
|
||||||
|
<i class="bi bi-trash me-2 "></i>Delete
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="ms-md-auto d-flex gap-2 align-items-center" v-else-if="confirmDelete === 'TrafficTrackingTable'">
|
||||||
|
<small>
|
||||||
|
<LocaleText t="Are you sure to delete?"></LocaleText>
|
||||||
|
</small>
|
||||||
|
<button class="btn btn-sm bg-danger-subtle text-danger-emphasis rounded-3"
|
||||||
|
:class="{disabled: deleting}"
|
||||||
|
@click="deleteRecord('TrafficTrackingTable')">
|
||||||
|
<i class="bi bi-check me-2 "></i>Yes
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
:class="{disabled: deleting}"
|
||||||
|
class="btn btn-sm bg-secondary-subtle text-secondary-emphasis rounded-3" @click="confirmDelete = ''">
|
||||||
|
<i class="bi bi-x me-2 "></i>No
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm">
|
||||||
|
<small class="text-muted fw-bold">Peer Historical Endpoint Tracking</small>
|
||||||
|
<div class="form-check form-switch">
|
||||||
|
<input class="form-check-input"
|
||||||
|
:disabled="toggling"
|
||||||
|
@change="updateToggle('PeerHistoricalEndpointTracking')"
|
||||||
|
type="checkbox" v-model="configuration.Info.PeerHistoricalEndpointTracking" :id="configuration.Name + '_historicalEndpoint_tracking'">
|
||||||
|
<label class="form-check-label" :for="configuration.Name + '_historicalEndpoint_tracking'">
|
||||||
|
{{ configuration.Info.PeerHistoricalEndpointTracking ? 'On':'Off'}}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
<div class="d-flex align-items-start align-items-md-center flex-column flex-md-row gap-2">
|
||||||
|
<div>
|
||||||
|
<h6 class="placeholder animate__animated animate__flash animate__infinite animate__slower w-100 mb-0" v-if="!sizeDataLoaded"></h6>
|
||||||
|
<h6 v-else class="mb-0">
|
||||||
|
{{ sizes.HistoricalTrackingTableSize }} <span class="text-muted fw-normal"><LocaleText t="Records"></LocaleText></span>
|
||||||
|
</h6>
|
||||||
|
</div>
|
||||||
|
<div class="ms-md-auto d-flex gap-2" v-if="confirmDelete !== 'HistoricalTrackingTable'">
|
||||||
|
<button
|
||||||
|
@click="download('HistoricalTrackingTable')"
|
||||||
|
:class="{disabled: downloading === 'HistoricalTrackingTable'}"
|
||||||
|
class="btn btn-sm bg-primary-subtle text-primary-emphasis rounded-3">
|
||||||
|
<i class="bi bi-download me-2 "></i>
|
||||||
|
<LocaleText :t="downloading === 'HistoricalTrackingTable' ? 'Downloading...':'Download'"></LocaleText>
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-sm bg-danger-subtle text-danger-emphasis rounded-3" @click="confirmDelete = 'HistoricalTrackingTable'">
|
||||||
|
<i class="bi bi-trash me-2 "></i>Delete
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="ms-md-auto d-flex gap-2 align-items-center" v-else-if="confirmDelete === 'HistoricalTrackingTable'">
|
||||||
|
<small>
|
||||||
|
<LocaleText t="Are you sure to delete?"></LocaleText>
|
||||||
|
</small>
|
||||||
|
<button class="btn btn-sm bg-danger-subtle text-danger-emphasis rounded-3"
|
||||||
|
:class="{disabled: deleting}"
|
||||||
|
@click="deleteRecord('HistoricalTrackingTable')">
|
||||||
|
<i class="bi bi-check me-2 "></i>Yes
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
:class="{disabled: deleting}"
|
||||||
|
class="btn btn-sm bg-secondary-subtle text-secondary-emphasis rounded-3" @click="confirmDelete = ''">
|
||||||
|
<i class="bi bi-x me-2 "></i>No
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -4,6 +4,8 @@ import DashboardSettingsInputWireguardConfigurationPath
|
|||||||
from "@/components/settingsComponent/dashboardSettingsInputWireguardConfigurationPath.vue";
|
from "@/components/settingsComponent/dashboardSettingsInputWireguardConfigurationPath.vue";
|
||||||
import DashboardSettingsWireguardConfigurationAutostart
|
import DashboardSettingsWireguardConfigurationAutostart
|
||||||
from "@/components/settingsComponent/dashboardSettingsWireguardConfigurationAutostart.vue";
|
from "@/components/settingsComponent/dashboardSettingsWireguardConfigurationAutostart.vue";
|
||||||
|
import DashboardWireguardConfigurationTracking
|
||||||
|
from "@/components/settingsComponent/dashboardWireguardConfigurationTracking.vue";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -16,6 +18,7 @@ import DashboardSettingsWireguardConfigurationAutostart
|
|||||||
>
|
>
|
||||||
</DashboardSettingsInputWireguardConfigurationPath>
|
</DashboardSettingsInputWireguardConfigurationPath>
|
||||||
<DashboardSettingsWireguardConfigurationAutostart></DashboardSettingsWireguardConfigurationAutostart>
|
<DashboardSettingsWireguardConfigurationAutostart></DashboardSettingsWireguardConfigurationAutostart>
|
||||||
|
<DashboardWireguardConfigurationTracking/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
import{a7 as A,r as n,D as S,g as l,z as v}from"./index-BQYwwrw6.js";const b=A("DashboardClientAssignmentStore",()=>{const f=n({}),d=n([]),o=n({}),c=n([]),g=n(!1),r=n(""),i=S(),w=async()=>{await l("/api/clients/allClients",{},s=>{o.value=s.data})},y=async()=>{await l("/api/clients/allClientsRaw",{},s=>{c.value=s.data,console.log(c.value)})},m=s=>Object.values(o.value).flat().find(e=>e.ClientID===s),u=async(s,e)=>{await l("/api/clients/assignedClients",{ConfigurationName:s,Peer:e},a=>{d.value=a.data})};return{assignments:d,getAssignedClients:u,getClients:w,getClientsRaw:y,clients:o,unassignClient:async(s,e,a)=>{g.value=!0,await v("/api/clients/unassignClient",{AssignmentID:a},async t=>{t.status?(i.newMessage("Server","Unassign successfully!","success"),s&&e&&await u(s,e)):(i.newMessage("Server","Unassign Failed. Reason: "+t.message,"success"),console.error("Unassign Failed. Reason: "+t.message)),g.value=!1})},assignClient:async(s,e,a,t=!0)=>{r.value=a,await v("/api/clients/assignClient",{ConfigurationName:s,Peer:e,ClientID:a},async C=>{C.status?(i.newMessage("Server","Assign successfully!","success"),t&&await u(s,e)):(i.newMessage("Server","Assign Failed. Reason: "+C.message,"success"),console.error("Assign Failed. Reason: "+C.message)),r.value=""})},getClientById:m,unassigning:g,assigning:r,clientsRaw:c,allConfigurationsPeers:f,getAllConfigurationsPeers:async()=>{await l("/api/clients/allConfigurationsPeers",{},s=>{f.value=s.data})}}});export{b as D};
|
import{a7 as A,r as n,D as S,g as l,z as v}from"./index-BuOf6BZp.js";const b=A("DashboardClientAssignmentStore",()=>{const f=n({}),d=n([]),o=n({}),c=n([]),g=n(!1),r=n(""),i=S(),w=async()=>{await l("/api/clients/allClients",{},s=>{o.value=s.data})},y=async()=>{await l("/api/clients/allClientsRaw",{},s=>{c.value=s.data,console.log(c.value)})},m=s=>Object.values(o.value).flat().find(e=>e.ClientID===s),u=async(s,e)=>{await l("/api/clients/assignedClients",{ConfigurationName:s,Peer:e},a=>{d.value=a.data})};return{assignments:d,getAssignedClients:u,getClients:w,getClientsRaw:y,clients:o,unassignClient:async(s,e,a)=>{g.value=!0,await v("/api/clients/unassignClient",{AssignmentID:a},async t=>{t.status?(i.newMessage("Server","Unassign successfully!","success"),s&&e&&await u(s,e)):(i.newMessage("Server","Unassign Failed. Reason: "+t.message,"success"),console.error("Unassign Failed. Reason: "+t.message)),g.value=!1})},assignClient:async(s,e,a,t=!0)=>{r.value=a,await v("/api/clients/assignClient",{ConfigurationName:s,Peer:e,ClientID:a},async C=>{C.status?(i.newMessage("Server","Assign successfully!","success"),t&&await u(s,e)):(i.newMessage("Server","Assign Failed. Reason: "+C.message,"success"),console.error("Assign Failed. Reason: "+C.message)),r.value=""})},getClientById:m,unassigning:g,assigning:r,clientsRaw:c,allConfigurationsPeers:f,getAllConfigurationsPeers:async()=>{await l("/api/clients/allConfigurationsPeers",{},s=>{f.value=s.data})}}});export{b as D};
|
||||||
File diff suppressed because one or more lines are too long
1
src/static/dist/WGDashboardAdmin/assets/clientViewer-7U41rXJo.js
vendored
Normal file
1
src/static/dist/WGDashboardAdmin/assets/clientViewer-7U41rXJo.js
vendored
Normal file
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
@@ -1 +1 @@
|
|||||||
import{_ as r,c as i,a as e,d as o,w as t,k as l,j as a,l as _,S as d,h as u}from"./index-BQYwwrw6.js";const m={name:"configuration"},p={class:"mt-md-5 mt-3 text-body"};function f(h,k,x,w,$,v){const n=u("RouterView");return e(),i("div",p,[o(n,null,{default:t(({Component:s,route:c})=>[o(l,{name:"fade2",mode:"out-in"},{default:t(()=>[(e(),a(d,null,{default:t(()=>[(e(),a(_(s),{key:c.path,class:"z-1"}))]),_:2},1024))]),_:2},1024)]),_:1})])}const B=r(m,[["render",f]]);export{B as default};
|
import{_ as r,c as i,a as e,d as o,w as t,k as l,j as a,l as _,S as d,h as u}from"./index-BuOf6BZp.js";const m={name:"configuration"},p={class:"mt-md-5 mt-3 text-body"};function f(h,k,x,w,$,v){const n=u("RouterView");return e(),i("div",p,[o(n,null,{default:t(({Component:s,route:c})=>[o(l,{name:"fade2",mode:"out-in"},{default:t(()=>[(e(),a(d,null,{default:t(()=>[(e(),a(_(s),{key:c.path,class:"z-1"}))]),_:2},1024))]),_:2},1024)]),_:1})])}const B=r(m,[["render",f]]);export{B as default};
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{_ as f,c as i,a as n,b as t,d as u,h as w,e as k,m as x,y,n as p,t as v,z as _,D as m,W as b,A as S,r as D,q as $,F as W,i as V}from"./index-BQYwwrw6.js";import{L as C}from"./localeText-C3GiyveB.js";const F={name:"dashboardSettingsInputWireguardConfigurationPath",components:{LocaleText:C},props:{targetData:String,title:String,warning:!1,warningText:""},setup(){const o=m(),s=b(),r=`input_${S()}`;return{store:o,uuid:r,WireguardConfigurationStore:s}},data(){return{value:"",invalidFeedback:"",showInvalidFeedback:!1,isValid:!1,timeout:void 0,changed:!1,updating:!1}},mounted(){this.value=this.store.Configuration.Server[this.targetData]},methods:{async useValidation(){this.changed&&(this.updating=!0,await _("/api/updateDashboardConfigurationItem",{section:"Server",key:this.targetData,value:this.value},o=>{o.status?(this.isValid=!0,this.showInvalidFeedback=!1,this.store.Configuration.Account[this.targetData]=this.value,clearTimeout(this.timeout),this.timeout=setTimeout(()=>this.isValid=!1,5e3),this.WireguardConfigurationStore.getConfigurations(),this.store.newMessage("Server","WireGuard configuration path saved","success")):(this.isValid=!1,this.showInvalidFeedback=!0,this.invalidFeedback=o.message),this.changed=!1,this.updating=!1}))}}},I={class:"card"},T={class:"card-header"},A={class:"my-2"},L={class:"card-body"},M={class:"form-group"},N=["for"],P={class:"d-flex gap-2 align-items-start"},B={class:"flex-grow-1"},G=["id","disabled"],z={class:"invalid-feedback fw-bold"},U=["disabled"],q={key:0,class:"bi bi-save2-fill"},E={key:1,class:"spinner-border spinner-border-sm"},K={key:0,class:"px-2 py-1 text-warning-emphasis bg-warning-subtle border border-warning-subtle rounded-2 d-inline-block mt-1 mb-2"};function j(o,s,r,a,c,g){const d=w("LocaleText");return n(),i("div",I,[t("div",T,[t("h6",A,[u(d,{t:"Path"})])]),t("div",L,[t("div",M,[t("label",{for:this.uuid,class:"text-muted mb-1"},[t("strong",null,[t("small",null,[u(d,{t:this.title},null,8,["t"])])])],8,N),t("div",P,[t("div",B,[x(t("input",{type:"text",class:p(["form-control rounded-3",{"is-invalid":this.showInvalidFeedback,"is-valid":this.isValid}]),id:this.uuid,"onUpdate:modelValue":s[0]||(s[0]=e=>this.value=e),onKeydown:s[1]||(s[1]=e=>this.changed=!0),disabled:this.updating},null,42,G),[[y,this.value]]),t("div",z,v(this.invalidFeedback),1)]),t("button",{onClick:s[2]||(s[2]=e=>this.useValidation()),disabled:!this.changed,class:"ms-auto btn rounded-3 border-success-subtle bg-success-subtle text-success-emphasis"},[this.updating?(n(),i("span",E)):(n(),i("i",q))],8,U)]),r.warning?(n(),i("div",K,[t("small",null,[s[3]||(s[3]=t("i",{class:"bi bi-exclamation-triangle-fill me-2"},null,-1)),u(d,{t:r.warningText},null,8,["t"])])])):k("",!0)])])])}const et=f(F,[["render",j]]),H={class:"card rounded-3"},J={class:"card-header"},O={class:"my-2"},Q={class:"card-body d-flex gap-2"},R={class:"list-group w-100"},X=["onClick"],Y={__name:"dashboardSettingsWireguardConfigurationAutostart",setup(o){const s=m(),r=b(),a=D(s.Configuration.WireGuardConfiguration.autostart),c=$(()=>r.Configurations.map(e=>e.Name)),g=async()=>{await _("/api/updateDashboardConfigurationItem",{section:"WireGuardConfiguration",key:"autostart",value:a.value},async e=>{e.status?(s.newMessage("Server","Start up configurations saved","success"),a.value=e.data):s.newMessage("Server","Start up configurations failed to save","danger")})},d=e=>{a.value.includes(e)?a.value=a.value.filter(h=>h!==e):a.value.push(e),g()};return(e,h)=>(n(),i("div",H,[t("div",J,[t("h6",O,[u(C,{t:"Toggle When Start Up"})])]),t("div",Q,[t("div",R,[(n(!0),i(W,null,V(c.value,l=>(n(),i("button",{type:"button",key:l,onClick:Z=>d(l),class:"list-group-item list-group-item-action py-2 w-100 d-flex align-items-center"},[t("samp",null,v(l),1),t("i",{class:p(["ms-auto",[a.value.includes(l)?"bi-check-circle-fill":"bi-circle"]])},null,2)],8,X))),128))])])]))}},at=f(Y,[["__scopeId","data-v-4aa2aed9"]]);export{et as D,at as a};
|
import{_ as f,c as i,a as n,b as t,d as u,h as w,e as k,m as x,y,n as p,t as v,z as _,D as m,W as b,A as S,r as D,q as $,F as W,i as V}from"./index-BuOf6BZp.js";import{L as C}from"./localeText-CzYZfO0n.js";const F={name:"dashboardSettingsInputWireguardConfigurationPath",components:{LocaleText:C},props:{targetData:String,title:String,warning:!1,warningText:""},setup(){const o=m(),s=b(),r=`input_${S()}`;return{store:o,uuid:r,WireguardConfigurationStore:s}},data(){return{value:"",invalidFeedback:"",showInvalidFeedback:!1,isValid:!1,timeout:void 0,changed:!1,updating:!1}},mounted(){this.value=this.store.Configuration.Server[this.targetData]},methods:{async useValidation(){this.changed&&(this.updating=!0,await _("/api/updateDashboardConfigurationItem",{section:"Server",key:this.targetData,value:this.value},o=>{o.status?(this.isValid=!0,this.showInvalidFeedback=!1,this.store.Configuration.Account[this.targetData]=this.value,clearTimeout(this.timeout),this.timeout=setTimeout(()=>this.isValid=!1,5e3),this.WireguardConfigurationStore.getConfigurations(),this.store.newMessage("Server","WireGuard configuration path saved","success")):(this.isValid=!1,this.showInvalidFeedback=!0,this.invalidFeedback=o.message),this.changed=!1,this.updating=!1}))}}},I={class:"card"},T={class:"card-header"},A={class:"my-2"},L={class:"card-body"},M={class:"form-group"},N=["for"],P={class:"d-flex gap-2 align-items-start"},B={class:"flex-grow-1"},G=["id","disabled"],z={class:"invalid-feedback fw-bold"},U=["disabled"],q={key:0,class:"bi bi-save2-fill"},E={key:1,class:"spinner-border spinner-border-sm"},K={key:0,class:"px-2 py-1 text-warning-emphasis bg-warning-subtle border border-warning-subtle rounded-2 d-inline-block mt-1 mb-2"};function j(o,s,r,a,c,g){const d=w("LocaleText");return n(),i("div",I,[t("div",T,[t("h6",A,[u(d,{t:"Path"})])]),t("div",L,[t("div",M,[t("label",{for:this.uuid,class:"text-muted mb-1"},[t("strong",null,[t("small",null,[u(d,{t:this.title},null,8,["t"])])])],8,N),t("div",P,[t("div",B,[x(t("input",{type:"text",class:p(["form-control rounded-3",{"is-invalid":this.showInvalidFeedback,"is-valid":this.isValid}]),id:this.uuid,"onUpdate:modelValue":s[0]||(s[0]=e=>this.value=e),onKeydown:s[1]||(s[1]=e=>this.changed=!0),disabled:this.updating},null,42,G),[[y,this.value]]),t("div",z,v(this.invalidFeedback),1)]),t("button",{onClick:s[2]||(s[2]=e=>this.useValidation()),disabled:!this.changed,class:"ms-auto btn rounded-3 border-success-subtle bg-success-subtle text-success-emphasis"},[this.updating?(n(),i("span",E)):(n(),i("i",q))],8,U)]),r.warning?(n(),i("div",K,[t("small",null,[s[3]||(s[3]=t("i",{class:"bi bi-exclamation-triangle-fill me-2"},null,-1)),u(d,{t:r.warningText},null,8,["t"])])])):k("",!0)])])])}const et=f(F,[["render",j]]),H={class:"card rounded-3"},J={class:"card-header"},O={class:"my-2"},Q={class:"card-body d-flex gap-2"},R={class:"list-group w-100"},X=["onClick"],Y={__name:"dashboardSettingsWireguardConfigurationAutostart",setup(o){const s=m(),r=b(),a=D(s.Configuration.WireGuardConfiguration.autostart),c=$(()=>r.Configurations.map(e=>e.Name)),g=async()=>{await _("/api/updateDashboardConfigurationItem",{section:"WireGuardConfiguration",key:"autostart",value:a.value},async e=>{e.status?(s.newMessage("Server","Start up configurations saved","success"),a.value=e.data):s.newMessage("Server","Start up configurations failed to save","danger")})},d=e=>{a.value.includes(e)?a.value=a.value.filter(h=>h!==e):a.value.push(e),g()};return(e,h)=>(n(),i("div",H,[t("div",J,[t("h6",O,[u(C,{t:"Toggle When Start Up"})])]),t("div",Q,[t("div",R,[(n(!0),i(W,null,V(c.value,l=>(n(),i("button",{type:"button",key:l,onClick:Z=>d(l),class:"list-group-item list-group-item-action py-2 w-100 d-flex align-items-center"},[t("samp",null,v(l),1),t("i",{class:p(["ms-auto",[a.value.includes(l)?"bi-check-circle-fill":"bi-circle"]])},null,2)],8,X))),128))])])]))}},at=f(Y,[["__scopeId","data-v-4aa2aed9"]]);export{et as D,at as a};
|
||||||
1
src/static/dist/WGDashboardAdmin/assets/dashboardWebHooks-DNskYzZ9.js
vendored
Normal file
1
src/static/dist/WGDashboardAdmin/assets/dashboardWebHooks-DNskYzZ9.js
vendored
Normal file
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
File diff suppressed because one or more lines are too long
7
src/static/dist/WGDashboardAdmin/assets/editConfiguration-Dk2eVqyr.js
vendored
Normal file
7
src/static/dist/WGDashboardAdmin/assets/editConfiguration-Dk2eVqyr.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
|
|||||||
import{B as Vs,U as Ws,V as qe,X as Vn,r as Wn,o as Nn,Y as jn,H as $n,Z as Ge,$ as Ns,a0 as Yn}from"./index-BQYwwrw6.js";/*!
|
import{B as Vs,U as Ws,V as qe,X as Vn,r as Wn,o as Nn,Y as jn,I as $n,Z as Ge,$ as Ns,a0 as Yn}from"./index-BuOf6BZp.js";/*!
|
||||||
* @kurkle/color v0.3.4
|
* @kurkle/color v0.3.4
|
||||||
* https://github.com/kurkle/color#readme
|
* https://github.com/kurkle/color#readme
|
||||||
* (c) 2024 Jukka Kurkela
|
* (c) 2024 Jukka Kurkela
|
||||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{_ as e,G as t,c as o,a,t as c}from"./index-BQYwwrw6.js";const s={name:"localeText",props:{t:""},computed:{getLocaleText(){return t(this.t)}}};function n(r,p,l,_,i,x){return a(),o("span",null,c(this.getLocaleText),1)}const u=e(s,[["render",n]]);export{u as L};
|
import{_ as e,G as t,c as o,a,t as c}from"./index-BuOf6BZp.js";const s={name:"localeText",props:{t:""},computed:{getLocaleText(){return t(this.t)}}};function n(r,p,l,_,i,x){return a(),o("span",null,c(this.getLocaleText),1)}const u=e(s,[["render",n]]);export{u as L};
|
||||||
@@ -1 +1 @@
|
|||||||
import{L as l}from"./localeText-C3GiyveB.js";import{d as c}from"./dayjs.min-CzHDLgWx.js";import{_ as h,c as o,a,b as e,d as i,w as u,f as p,h as g,t as n,k as f,n as _}from"./index-BQYwwrw6.js";const x={name:"message",methods:{dayjs:c,hide(){this.ct(),this.message.show=!1},show(){this.timeout=setTimeout(()=>{this.message.show=!1},5e3)},ct(){clearTimeout(this.timeout)}},components:{LocaleText:l},props:{message:Object},mounted(){this.show()},data(){return{dismiss:!1,timeout:null}}},v=["id"],b={key:0,class:"d-flex"},w={class:"fw-bold d-block",style:{"text-transform":"uppercase"}},y={class:"ms-auto"},k={key:1},T={class:"card-body d-flex align-items-center gap-3"};function M(C,s,L,j,t,m){const d=g("LocaleText");return a(),o("div",{onMouseenter:s[1]||(s[1]=r=>{t.dismiss=!0,this.ct()}),onMouseleave:s[2]||(s[2]=r=>{t.dismiss=!1,this.show()}),class:"card shadow rounded-3 position-relative message ms-auto",id:this.message.id},[e("div",{class:_([{"text-bg-danger":this.message.type==="danger","text-bg-success":this.message.type==="success","text-bg-warning":this.message.type==="warning"},"card-header pos"])},[i(f,{name:"zoom",mode:"out-in"},{default:u(()=>[t.dismiss?(a(),o("div",k,[e("small",{onClick:s[0]||(s[0]=r=>m.hide()),class:"d-block mx-auto w-100 text-center",style:{cursor:"pointer"}},[s[3]||(s[3]=e("i",{class:"bi bi-x-lg me-2"},null,-1)),i(d,{t:"Dismiss"})])])):(a(),o("div",b,[e("small",w,[i(d,{t:"FROM "}),p(" "+n(this.message.from),1)]),e("small",y,n(m.dayjs().format("hh:mm A")),1)]))]),_:1})],2),e("div",T,[e("div",null,n(this.message.content),1)])],40,v)}const z=h(x,[["render",M],["__scopeId","data-v-94c76b54"]]);export{z as M};
|
import{L as l}from"./localeText-CzYZfO0n.js";import{d as c}from"./dayjs.min-BzBvZaAI.js";import{_ as h,c as o,a,b as e,d as i,w as u,f as p,h as g,t as n,k as f,n as _}from"./index-BuOf6BZp.js";const x={name:"message",methods:{dayjs:c,hide(){this.ct(),this.message.show=!1},show(){this.timeout=setTimeout(()=>{this.message.show=!1},5e3)},ct(){clearTimeout(this.timeout)}},components:{LocaleText:l},props:{message:Object},mounted(){this.show()},data(){return{dismiss:!1,timeout:null}}},v=["id"],b={key:0,class:"d-flex"},w={class:"fw-bold d-block",style:{"text-transform":"uppercase"}},y={class:"ms-auto"},k={key:1},T={class:"card-body d-flex align-items-center gap-3"};function M(C,s,L,j,t,m){const d=g("LocaleText");return a(),o("div",{onMouseenter:s[1]||(s[1]=r=>{t.dismiss=!0,this.ct()}),onMouseleave:s[2]||(s[2]=r=>{t.dismiss=!1,this.show()}),class:"card shadow rounded-3 position-relative message ms-auto",id:this.message.id},[e("div",{class:_([{"text-bg-danger":this.message.type==="danger","text-bg-success":this.message.type==="success","text-bg-warning":this.message.type==="warning"},"card-header pos"])},[i(f,{name:"zoom",mode:"out-in"},{default:u(()=>[t.dismiss?(a(),o("div",k,[e("small",{onClick:s[0]||(s[0]=r=>m.hide()),class:"d-block mx-auto w-100 text-center",style:{cursor:"pointer"}},[s[3]||(s[3]=e("i",{class:"bi bi-x-lg me-2"},null,-1)),i(d,{t:"Dismiss"})])])):(a(),o("div",b,[e("small",w,[i(d,{t:"FROM "}),p(" "+n(this.message.from),1)]),e("small",y,n(m.dayjs().format("hh:mm A")),1)]))]),_:1})],2),e("div",T,[e("div",null,n(this.message.content),1)])],40,v)}const z=h(x,[["render",M],["__scopeId","data-v-94c76b54"]]);export{z as M};
|
||||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{S as C,e as y,c as w,m as _,a as L,f as S,l as v,i as M,b as k,d as x,g as A,h as F,j as R,M as D,V as P,T as b,k as l,O as E,n as O,F as h,P as c,o as T,p as f,C as V,q as u,r as X}from"./Vector-zgNB5xDX.js";import{_ as Y,D as G,c as $,e as j,a as q}from"./index-BQYwwrw6.js";class r extends C{constructor(t,e){super(),this.flatMidpoint_=null,this.flatMidpointRevision_=-1,this.maxDelta_=-1,this.maxDeltaRevision_=-1,e!==void 0&&!Array.isArray(t[0])?this.setFlatCoordinates(e,t):this.setCoordinates(t,e)}appendCoordinate(t){y(this.flatCoordinates,t),this.changed()}clone(){const t=new r(this.flatCoordinates.slice(),this.layout);return t.applyProperties(this),t}closestPointXY(t,e,o,n){return n<w(this.getExtent(),t,e)?n:(this.maxDeltaRevision_!=this.getRevision()&&(this.maxDelta_=Math.sqrt(_(this.flatCoordinates,0,this.flatCoordinates.length,this.stride,0)),this.maxDeltaRevision_=this.getRevision()),L(this.flatCoordinates,0,this.flatCoordinates.length,this.stride,this.maxDelta_,!1,t,e,o,n))}forEachSegment(t){return S(this.flatCoordinates,0,this.flatCoordinates.length,this.stride,t)}getCoordinateAtM(t,e){return this.layout!="XYM"&&this.layout!="XYZM"?null:(e=e!==void 0?e:!1,v(this.flatCoordinates,0,this.flatCoordinates.length,this.stride,t,e))}getCoordinates(){return M(this.flatCoordinates,0,this.flatCoordinates.length,this.stride)}getCoordinateAt(t,e){return k(this.flatCoordinates,0,this.flatCoordinates.length,this.stride,t,e,this.stride)}getLength(){return x(this.flatCoordinates,0,this.flatCoordinates.length,this.stride)}getFlatMidpoint(){return this.flatMidpointRevision_!=this.getRevision()&&(this.flatMidpoint_=this.getCoordinateAt(.5,this.flatMidpoint_??void 0),this.flatMidpointRevision_=this.getRevision()),this.flatMidpoint_}getSimplifiedGeometryInternal(t){const e=[];return e.length=A(this.flatCoordinates,0,this.flatCoordinates.length,this.stride,t,e,0),new r(e,"XY")}getType(){return"LineString"}intersectsExtent(t){return F(this.flatCoordinates,0,this.flatCoordinates.length,this.stride,t,this.getExtent())}setCoordinates(t,e){this.setLayout(e,t,1),this.flatCoordinates||(this.flatCoordinates=[]),this.flatCoordinates.length=R(this.flatCoordinates,0,t,this.stride),this.changed()}}const B={name:"osmap",props:{type:"",d:Object||Array},data(){return{osmAvailable:!0}},setup(){return{store:G()}},methods:{getLastLonLat(){if(this.type==="traceroute"){const i=this.d.findLast(t=>t.geo&&t.geo.lat&&t.geo.lon);return i?[i.geo.lon,i.geo.lat]:[0,0]}return[this.d.geo.lon,this.d.geo.lat]}},async mounted(){await fetch("https://tile.openstreetmap.org/",{signal:AbortSignal.timeout(1500)}).then(i=>{const t=new D({target:"map",layers:[new b({source:new E})],view:new P({center:l(this.getLastLonLat()),zoom:this.type==="traceroute"?3:10})}),e=[],o=new O;if(this.type==="traceroute")this.d.forEach(s=>{if(s.geo&&s.geo.lat&&s.geo.lon){const a=l([s.geo.lon,s.geo.lat]);e.push(a);const g=this.getLastLonLat(),m=new h({geometry:new c(a),last:s.geo.lon===g[0]&&s.geo.lat===g[1]});o.addFeature(m)}});else{const s=l([this.d.geo.lon,this.d.geo.lat]);e.push(s);const a=new h({geometry:new c(s)});o.addFeature(a)}const n=new r(e),d=new h({geometry:n});o.addFeature(d);const p=new T({source:o,style:function(s){if(s.getGeometry().getType()==="Point")return new f({image:new V({radius:10,fill:new X({color:s.get("last")?"#dc3545":"#0d6efd"}),stroke:new u({color:"white",width:5})})});if(s.getGeometry().getType()==="LineString")return new f({stroke:new u({color:"#0d6efd",width:2})})}});t.addLayer(p)}).catch(i=>{this.osmAvailable=!1})}},z={key:0,id:"map",class:"w-100 rounded-3"};function I(i,t,e,o,n,d){return this.osmAvailable?(q(),$("div",z)):j("",!0)}const H=Y(B,[["render",I]]);export{H as O};
|
import{S as C,e as y,c as w,m as _,a as L,f as S,l as v,i as M,b as k,d as x,g as A,h as F,j as R,M as D,V as P,T as b,k as l,O as E,n as O,F as h,P as c,o as T,p as f,C as V,q as u,r as X}from"./Vector-zgNB5xDX.js";import{_ as Y,D as G,c as $,e as j,a as q}from"./index-BuOf6BZp.js";class r extends C{constructor(t,e){super(),this.flatMidpoint_=null,this.flatMidpointRevision_=-1,this.maxDelta_=-1,this.maxDeltaRevision_=-1,e!==void 0&&!Array.isArray(t[0])?this.setFlatCoordinates(e,t):this.setCoordinates(t,e)}appendCoordinate(t){y(this.flatCoordinates,t),this.changed()}clone(){const t=new r(this.flatCoordinates.slice(),this.layout);return t.applyProperties(this),t}closestPointXY(t,e,o,n){return n<w(this.getExtent(),t,e)?n:(this.maxDeltaRevision_!=this.getRevision()&&(this.maxDelta_=Math.sqrt(_(this.flatCoordinates,0,this.flatCoordinates.length,this.stride,0)),this.maxDeltaRevision_=this.getRevision()),L(this.flatCoordinates,0,this.flatCoordinates.length,this.stride,this.maxDelta_,!1,t,e,o,n))}forEachSegment(t){return S(this.flatCoordinates,0,this.flatCoordinates.length,this.stride,t)}getCoordinateAtM(t,e){return this.layout!="XYM"&&this.layout!="XYZM"?null:(e=e!==void 0?e:!1,v(this.flatCoordinates,0,this.flatCoordinates.length,this.stride,t,e))}getCoordinates(){return M(this.flatCoordinates,0,this.flatCoordinates.length,this.stride)}getCoordinateAt(t,e){return k(this.flatCoordinates,0,this.flatCoordinates.length,this.stride,t,e,this.stride)}getLength(){return x(this.flatCoordinates,0,this.flatCoordinates.length,this.stride)}getFlatMidpoint(){return this.flatMidpointRevision_!=this.getRevision()&&(this.flatMidpoint_=this.getCoordinateAt(.5,this.flatMidpoint_??void 0),this.flatMidpointRevision_=this.getRevision()),this.flatMidpoint_}getSimplifiedGeometryInternal(t){const e=[];return e.length=A(this.flatCoordinates,0,this.flatCoordinates.length,this.stride,t,e,0),new r(e,"XY")}getType(){return"LineString"}intersectsExtent(t){return F(this.flatCoordinates,0,this.flatCoordinates.length,this.stride,t,this.getExtent())}setCoordinates(t,e){this.setLayout(e,t,1),this.flatCoordinates||(this.flatCoordinates=[]),this.flatCoordinates.length=R(this.flatCoordinates,0,t,this.stride),this.changed()}}const B={name:"osmap",props:{type:"",d:Object||Array},data(){return{osmAvailable:!0}},setup(){return{store:G()}},methods:{getLastLonLat(){if(this.type==="traceroute"){const i=this.d.findLast(t=>t.geo&&t.geo.lat&&t.geo.lon);return i?[i.geo.lon,i.geo.lat]:[0,0]}return[this.d.geo.lon,this.d.geo.lat]}},async mounted(){await fetch("https://tile.openstreetmap.org/",{signal:AbortSignal.timeout(1500)}).then(i=>{const t=new D({target:"map",layers:[new b({source:new E})],view:new P({center:l(this.getLastLonLat()),zoom:this.type==="traceroute"?3:10})}),e=[],o=new O;if(this.type==="traceroute")this.d.forEach(s=>{if(s.geo&&s.geo.lat&&s.geo.lon){const a=l([s.geo.lon,s.geo.lat]);e.push(a);const g=this.getLastLonLat(),m=new h({geometry:new c(a),last:s.geo.lon===g[0]&&s.geo.lat===g[1]});o.addFeature(m)}});else{const s=l([this.d.geo.lon,this.d.geo.lat]);e.push(s);const a=new h({geometry:new c(s)});o.addFeature(a)}const n=new r(e),d=new h({geometry:n});o.addFeature(d);const p=new T({source:o,style:function(s){if(s.getGeometry().getType()==="Point")return new f({image:new V({radius:10,fill:new X({color:s.get("last")?"#dc3545":"#0d6efd"}),stroke:new u({color:"white",width:5})})});if(s.getGeometry().getType()==="LineString")return new f({stroke:new u({color:"#0d6efd",width:2})})}});t.addLayer(p)}).catch(i=>{this.osmAvailable=!1})}},z={key:0,id:"map",class:"w-100 rounded-3"};function I(i,t,e,o,n,d){return this.osmAvailable?(q(),$("div",z)):j("",!0)}const H=Y(B,[["render",I]]);export{H as O};
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{_ as v,D as g,r as o,o as h,L as x,g as y,c as i,a as n,b as s,d as c,e as w,n as C,w as k,k as F}from"./index-BQYwwrw6.js";import{L as T}from"./localeText-C3GiyveB.js";import"./browser-BmbEXfbp.js";import"./galois-field-I2lBzzs-.js";const M={class:"peerSettingContainer w-100 h-100 position-absolute top-0 start-0"},S={class:"container d-flex h-100 w-100"},D={class:"m-auto modal-dialog-centered dashboardModal justify-content-center"},L={class:"card rounded-3 shadow w-100"},P={class:"card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-0"},B={class:"mb-0"},G={class:"card-body p-4 d-flex flex-column gap-3"},N={style:{height:"300px"},class:"d-flex"},V=["value"],j={key:0,class:"spinner-border m-auto",role:"status"},I={class:"d-flex"},W=["disabled"],$={key:0,class:"d-block"},q={key:1,class:"d-block",id:"check"},z={__name:"peerConfigurationFile",props:{selectedPeer:Object},emits:["close"],setup(u,{emit:p}){const m=p,f=u,r=g(),t=o(!1),l=o(""),a=o(!0);o({error:!1,message:void 0}),h(()=>{const d=x();y("/api/downloadPeer/"+d.params.id,{id:f.selectedPeer.id},e=>{e.status?(l.value=e.data.file,a.value=!1):this.dashboardStore.newMessage("Server",e.message,"danger")})});const b=async()=>{navigator.clipboard&&navigator.clipboard.writeText?navigator.clipboard.writeText(l.value).then(()=>{t.value=!0,setTimeout(()=>{t.value=!1},3e3)}).catch(()=>{r.newMessage("WGDashboard","Failed to copy","danger")}):(document.querySelector("#peerConfigurationFile").select(),document.execCommand("copy")?(t.value=!0,setTimeout(()=>{t.value=!1},3e3)):r.newMessage("WGDashboard","Failed to copy","danger"))};return(d,e)=>(n(),i("div",M,[s("div",S,[s("div",D,[s("div",L,[s("div",P,[s("h4",B,[c(T,{t:"Peer Configuration File"})]),s("button",{type:"button",class:"btn-close ms-auto",onClick:e[0]||(e[0]=_=>m("close"))})]),s("div",G,[s("div",N,[s("textarea",{style:{height:"300px"},class:C(["form-control w-100 rounded-3 animate__fadeIn animate__faster animate__animated",{"d-none":a.value}]),id:"peerConfigurationFile",value:l.value},null,10,V),a.value?(n(),i("div",j,[...e[2]||(e[2]=[s("span",{class:"visually-hidden"},"Loading...",-1)])])):w("",!0)]),s("div",I,[s("button",{onClick:e[1]||(e[1]=_=>b()),disabled:t.value||a.value,class:"ms-auto btn bg-primary-subtle border-primary-subtle text-primary-emphasis rounded-3 position-relative"},[c(F,{name:"slide-up",mode:"out-in"},{default:k(()=>[t.value?(n(),i("span",q,[...e[4]||(e[4]=[s("i",{class:"bi bi-check-circle-fill"},null,-1)])])):(n(),i("span",$,[...e[3]||(e[3]=[s("i",{class:"bi bi-clipboard-fill"},null,-1)])]))]),_:1})],8,W)])])])])])]))}},H=v(z,[["__scopeId","data-v-b0ea2d46"]]);export{H as default};
|
import{_ as v,D as g,r as o,o as h,L as x,g as y,c as i,a as n,b as s,d as c,e as w,n as C,w as k,k as F}from"./index-BuOf6BZp.js";import{L as T}from"./localeText-CzYZfO0n.js";import"./browser-CdT-qU-v.js";import"./galois-field-I2lBzzs-.js";const M={class:"peerSettingContainer w-100 h-100 position-absolute top-0 start-0"},S={class:"container d-flex h-100 w-100"},D={class:"m-auto modal-dialog-centered dashboardModal justify-content-center"},L={class:"card rounded-3 shadow w-100"},P={class:"card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-0"},B={class:"mb-0"},G={class:"card-body p-4 d-flex flex-column gap-3"},N={style:{height:"300px"},class:"d-flex"},V=["value"],j={key:0,class:"spinner-border m-auto",role:"status"},I={class:"d-flex"},W=["disabled"],$={key:0,class:"d-block"},q={key:1,class:"d-block",id:"check"},z={__name:"peerConfigurationFile",props:{selectedPeer:Object},emits:["close"],setup(u,{emit:p}){const m=p,f=u,r=g(),t=o(!1),l=o(""),a=o(!0);o({error:!1,message:void 0}),h(()=>{const d=x();y("/api/downloadPeer/"+d.params.id,{id:f.selectedPeer.id},e=>{e.status?(l.value=e.data.file,a.value=!1):this.dashboardStore.newMessage("Server",e.message,"danger")})});const b=async()=>{navigator.clipboard&&navigator.clipboard.writeText?navigator.clipboard.writeText(l.value).then(()=>{t.value=!0,setTimeout(()=>{t.value=!1},3e3)}).catch(()=>{r.newMessage("WGDashboard","Failed to copy","danger")}):(document.querySelector("#peerConfigurationFile").select(),document.execCommand("copy")?(t.value=!0,setTimeout(()=>{t.value=!1},3e3)):r.newMessage("WGDashboard","Failed to copy","danger"))};return(d,e)=>(n(),i("div",M,[s("div",S,[s("div",D,[s("div",L,[s("div",P,[s("h4",B,[c(T,{t:"Peer Configuration File"})]),s("button",{type:"button",class:"btn-close ms-auto",onClick:e[0]||(e[0]=_=>m("close"))})]),s("div",G,[s("div",N,[s("textarea",{style:{height:"300px"},class:C(["form-control w-100 rounded-3 animate__fadeIn animate__faster animate__animated",{"d-none":a.value}]),id:"peerConfigurationFile",value:l.value},null,10,V),a.value?(n(),i("div",j,[...e[2]||(e[2]=[s("span",{class:"visually-hidden"},"Loading...",-1)])])):w("",!0)]),s("div",I,[s("button",{onClick:e[1]||(e[1]=_=>b()),disabled:t.value||a.value,class:"ms-auto btn bg-primary-subtle border-primary-subtle text-primary-emphasis rounded-3 position-relative"},[c(F,{name:"slide-up",mode:"out-in"},{default:k(()=>[t.value?(n(),i("span",q,[...e[4]||(e[4]=[s("i",{class:"bi bi-check-circle-fill"},null,-1)])])):(n(),i("span",$,[...e[3]||(e[3]=[s("i",{class:"bi bi-clipboard-fill"},null,-1)])]))]),_:1})],8,W)])])])])])]))}},H=v(z,[["__scopeId","data-v-b0ea2d46"]]);export{H as default};
|
||||||
@@ -1 +1 @@
|
|||||||
import{L as o}from"./localeText-C3GiyveB.js";import{P as t}from"./peersDefaultSettingsInput-De2pvmfF.js";import{B as s,c as l,a as n,b as a,d as e}from"./index-BQYwwrw6.js";const r={class:"d-flex gap-3 flex-column"},i={class:"card rounded-3"},d={class:"card-header"},c={class:"my-2"},_={class:"card-body"},D=s({__name:"peerDefaultSettings",setup(p){return(g,m)=>(n(),l("div",r,[a("div",i,[a("div",d,[a("h6",c,[e(o,{t:"Peer Default Settings"})])]),a("div",_,[a("div",null,[e(t,{targetData:"peer_global_dns",title:"DNS"}),e(t,{targetData:"peer_endpoint_allowed_ip",title:"Endpoint Allowed IPs"}),e(t,{targetData:"peer_mtu",title:"MTU"}),e(t,{targetData:"peer_keep_alive",title:"Persistent Keepalive"}),e(t,{targetData:"remote_endpoint",title:"Peer Remote Endpoint",warning:!0,warningText:"This will be changed globally, and will be apply to all peer's QR code and configuration file."})])])])]))}});export{D as default};
|
import{L as o}from"./localeText-CzYZfO0n.js";import{P as t}from"./peersDefaultSettingsInput-BYUvwHVp.js";import{B as s,c as l,a as n,b as a,d as e}from"./index-BuOf6BZp.js";const r={class:"d-flex gap-3 flex-column"},i={class:"card rounded-3"},d={class:"card-header"},c={class:"my-2"},_={class:"card-body"},D=s({__name:"peerDefaultSettings",setup(p){return(g,m)=>(n(),l("div",r,[a("div",i,[a("div",d,[a("h6",c,[e(o,{t:"Peer Default Settings"})])]),a("div",_,[a("div",null,[e(t,{targetData:"peer_global_dns",title:"DNS"}),e(t,{targetData:"peer_endpoint_allowed_ip",title:"Endpoint Allowed IPs"}),e(t,{targetData:"peer_mtu",title:"MTU"}),e(t,{targetData:"peer_keep_alive",title:"Persistent Keepalive"}),e(t,{targetData:"remote_endpoint",title:"Peer Remote Endpoint",warning:!0,warningText:"This will be changed globally, and will be apply to all peer's QR code and configuration file."})])])])]))}});export{D as default};
|
||||||
@@ -1 +1 @@
|
|||||||
import{a as p,S as b}from"./schedulePeerJob-Bx58TbYr.js";import{_ as h,h as i,c as a,a as o,b as e,d as r,w as u,e as m,F as _,i as v,j as f,T as J,A as x,W as g}from"./index-BQYwwrw6.js";import{L as w}from"./localeText-C3GiyveB.js";import"./vue-datepicker-g3vsoQR2.js";import"./dayjs.min-CzHDLgWx.js";const P={name:"peerJobs",setup(){return{store:g()}},props:{selectedPeer:Object},components:{LocaleText:w,SchedulePeerJob:b,ScheduleDropdown:p},data(){return{}},methods:{deleteJob(d){this.selectedPeer.jobs=this.selectedPeer.jobs.filter(t=>t.JobID!==d.JobID)},addJob(){this.selectedPeer.jobs.unshift(JSON.parse(JSON.stringify({JobID:x().toString(),Configuration:this.selectedPeer.configuration.Name,Peer:this.selectedPeer.id,Field:this.store.PeerScheduleJobs.dropdowns.Field[0].value,Operator:this.store.PeerScheduleJobs.dropdowns.Operator[0].value,Value:"",CreationDate:"",ExpireDate:"",Action:this.store.PeerScheduleJobs.dropdowns.Action[0].value})))}}},S={class:"peerSettingContainer w-100 h-100 position-absolute top-0 start-0 overflow-y-scroll"},y={class:"container d-flex h-100 w-100"},$={class:"m-auto modal-dialog-centered dashboardModal"},C={class:"card rounded-3 shadow",style:{width:"700px"}},D={class:"card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-2"},j={class:"mb-0 fw-normal"},k={class:"card-body px-4 pb-4 pt-2 position-relative"},T={class:"d-flex align-items-center mb-3"},N={class:"card shadow-sm",key:"none",style:{height:"153px"}},I={class:"card-body text-muted text-center d-flex"},L={class:"m-auto"};function O(d,t,B,F,V,A){const n=i("LocaleText"),l=i("SchedulePeerJob");return o(),a("div",S,[e("div",y,[e("div",$,[e("div",C,[e("div",D,[e("h4",j,[r(n,{t:"Schedule Jobs"})]),e("button",{type:"button",class:"btn-close ms-auto",onClick:t[0]||(t[0]=s=>this.$emit("close"))})]),e("div",k,[e("div",T,[e("button",{class:"btn bg-primary-subtle border-1 border-primary-subtle text-primary-emphasis rounded-3 shadow",onClick:t[1]||(t[1]=s=>this.addJob())},[t[3]||(t[3]=e("i",{class:"bi bi-plus-lg me-2"},null,-1)),r(n,{t:"Job"})])]),r(J,{name:"schedulePeerJobTransition",tag:"div",class:"position-relative"},{default:u(()=>[(o(!0),a(_,null,v(this.selectedPeer.jobs,(s,E)=>(o(),f(l,{onRefresh:t[2]||(t[2]=c=>this.$emit("refresh")),onDelete:c=>this.deleteJob(s),dropdowns:this.store.PeerScheduleJobs.dropdowns,key:s.JobID,pjob:s},null,8,["onDelete","dropdowns","pjob"]))),128)),this.selectedPeer.jobs.length===0?(o(),a("div",N,[e("div",I,[e("h6",L,[r(n,{t:"This peer does not have any job yet."})])])])):m("",!0)]),_:1})])])])])])}const z=h(P,[["render",O],["__scopeId","data-v-5bbdd42b"]]);export{z as default};
|
import{a as p,S as b}from"./schedulePeerJob-DR3TE-YH.js";import{_ as h,h as i,c as a,a as o,b as e,d as r,w as u,e as m,F as _,i as v,j as f,T as J,A as x,W as g}from"./index-BuOf6BZp.js";import{L as w}from"./localeText-CzYZfO0n.js";import"./vue-datepicker-B81xP9h3.js";import"./dayjs.min-BzBvZaAI.js";const P={name:"peerJobs",setup(){return{store:g()}},props:{selectedPeer:Object},components:{LocaleText:w,SchedulePeerJob:b,ScheduleDropdown:p},data(){return{}},methods:{deleteJob(d){this.selectedPeer.jobs=this.selectedPeer.jobs.filter(t=>t.JobID!==d.JobID)},addJob(){this.selectedPeer.jobs.unshift(JSON.parse(JSON.stringify({JobID:x().toString(),Configuration:this.selectedPeer.configuration.Name,Peer:this.selectedPeer.id,Field:this.store.PeerScheduleJobs.dropdowns.Field[0].value,Operator:this.store.PeerScheduleJobs.dropdowns.Operator[0].value,Value:"",CreationDate:"",ExpireDate:"",Action:this.store.PeerScheduleJobs.dropdowns.Action[0].value})))}}},S={class:"peerSettingContainer w-100 h-100 position-absolute top-0 start-0 overflow-y-scroll"},y={class:"container d-flex h-100 w-100"},$={class:"m-auto modal-dialog-centered dashboardModal"},C={class:"card rounded-3 shadow",style:{width:"700px"}},D={class:"card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-2"},j={class:"mb-0 fw-normal"},k={class:"card-body px-4 pb-4 pt-2 position-relative"},T={class:"d-flex align-items-center mb-3"},N={class:"card shadow-sm",key:"none",style:{height:"153px"}},I={class:"card-body text-muted text-center d-flex"},L={class:"m-auto"};function O(d,t,B,F,V,A){const n=i("LocaleText"),l=i("SchedulePeerJob");return o(),a("div",S,[e("div",y,[e("div",$,[e("div",C,[e("div",D,[e("h4",j,[r(n,{t:"Schedule Jobs"})]),e("button",{type:"button",class:"btn-close ms-auto",onClick:t[0]||(t[0]=s=>this.$emit("close"))})]),e("div",k,[e("div",T,[e("button",{class:"btn bg-primary-subtle border-1 border-primary-subtle text-primary-emphasis rounded-3 shadow",onClick:t[1]||(t[1]=s=>this.addJob())},[t[3]||(t[3]=e("i",{class:"bi bi-plus-lg me-2"},null,-1)),r(n,{t:"Job"})])]),r(J,{name:"schedulePeerJobTransition",tag:"div",class:"position-relative"},{default:u(()=>[(o(!0),a(_,null,v(this.selectedPeer.jobs,(s,E)=>(o(),f(l,{onRefresh:t[2]||(t[2]=c=>this.$emit("refresh")),onDelete:c=>this.deleteJob(s),dropdowns:this.store.PeerScheduleJobs.dropdowns,key:s.JobID,pjob:s},null,8,["onDelete","dropdowns","pjob"]))),128)),this.selectedPeer.jobs.length===0?(o(),a("div",N,[e("div",I,[e("h6",L,[r(n,{t:"This peer does not have any job yet."})])])])):m("",!0)]),_:1})])])])])])}const z=h(P,[["render",O],["__scopeId","data-v-5bbdd42b"]]);export{z as default};
|
||||||
@@ -1 +1 @@
|
|||||||
import{S as _}from"./schedulePeerJob-Bx58TbYr.js";import{_ as g,h as c,c as r,a as t,b as e,d as l,F as p,i as b,e as v,t as m,j as f,W as y}from"./index-BQYwwrw6.js";import{L as x}from"./localeText-C3GiyveB.js";import"./vue-datepicker-g3vsoQR2.js";import"./dayjs.min-CzHDLgWx.js";const J={name:"peerJobsAllModal",setup(){return{store:y()}},components:{LocaleText:x,SchedulePeerJob:_},props:{configurationPeers:Array[Object]},computed:{getAllJobs(){return this.configurationPeers.filter(a=>a.jobs.length>0)}}},w={class:"peerSettingContainer w-100 h-100 position-absolute top-0 start-0 overflow-y-scroll"},$={class:"container d-flex h-100 w-100"},k={class:"m-auto modal-dialog-centered dashboardModal"},A={class:"card rounded-3 shadow",style:{width:"900px"}},L={class:"card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-2"},S={class:"mb-0 fw-normal"},j={class:"card-body px-4 pb-4 pt-2"},C={key:0,class:"accordion",id:"peerJobsLogsModalAccordion"},P={class:"accordion-header"},M=["data-bs-target"],B={key:0},N={class:"text-muted"},D=["id"],T={class:"accordion-body"},V={key:1,class:"card shadow-sm",style:{height:"153px"}},F={class:"card-body text-muted text-center d-flex"},O={class:"m-auto"};function W(a,o,E,I,R,q){const n=c("LocaleText"),u=c("SchedulePeerJob");return t(),r("div",w,[e("div",$,[e("div",k,[e("div",A,[e("div",L,[e("h4",S,[l(n,{t:"All Active Jobs"})]),e("button",{type:"button",class:"btn-close ms-auto",onClick:o[0]||(o[0]=s=>this.$emit("close"))})]),e("div",j,[e("button",{class:"btn bg-primary-subtle border-1 border-primary-subtle text-primary-emphasis rounded-3 shadow mb-2",onClick:o[1]||(o[1]=s=>this.$emit("allLogs"))},[o[4]||(o[4]=e("i",{class:"bi bi-clock me-2"},null,-1)),l(n,{t:"Logs"})]),this.getAllJobs.length>0?(t(),r("div",C,[(t(!0),r(p,null,b(this.getAllJobs,(s,d)=>(t(),r("div",{class:"accordion-item",key:s.id},[e("h2",P,[e("button",{class:"accordion-button collapsed",type:"button","data-bs-toggle":"collapse","data-bs-target":"#collapse_"+d},[e("small",null,[e("strong",null,[s.name?(t(),r("span",B,m(s.name)+" • ",1)):v("",!0),e("samp",N,m(s.id),1)])])],8,M)]),e("div",{id:"collapse_"+d,class:"accordion-collapse collapse","data-bs-parent":"#peerJobsLogsModalAccordion"},[e("div",T,[(t(!0),r(p,null,b(s.jobs,i=>(t(),f(u,{onDelete:o[2]||(o[2]=h=>this.$emit("refresh")),onRefresh:o[3]||(o[3]=h=>this.$emit("refresh")),dropdowns:this.store.PeerScheduleJobs.dropdowns,viewOnly:!0,key:i.JobID,pjob:i},null,8,["dropdowns","pjob"]))),128))])],8,D)]))),128))])):(t(),r("div",V,[e("div",F,[e("span",O,[l(n,{t:"No active job at the moment."})])])]))])])])])])}const U=g(J,[["render",W]]);export{U as default};
|
import{S as _}from"./schedulePeerJob-DR3TE-YH.js";import{_ as g,h as c,c as r,a as t,b as e,d as l,F as p,i as b,e as v,t as m,j as f,W as y}from"./index-BuOf6BZp.js";import{L as x}from"./localeText-CzYZfO0n.js";import"./vue-datepicker-B81xP9h3.js";import"./dayjs.min-BzBvZaAI.js";const J={name:"peerJobsAllModal",setup(){return{store:y()}},components:{LocaleText:x,SchedulePeerJob:_},props:{configurationPeers:Array[Object]},computed:{getAllJobs(){return this.configurationPeers.filter(a=>a.jobs.length>0)}}},w={class:"peerSettingContainer w-100 h-100 position-absolute top-0 start-0 overflow-y-scroll"},$={class:"container d-flex h-100 w-100"},k={class:"m-auto modal-dialog-centered dashboardModal"},A={class:"card rounded-3 shadow",style:{width:"900px"}},L={class:"card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-2"},S={class:"mb-0 fw-normal"},j={class:"card-body px-4 pb-4 pt-2"},C={key:0,class:"accordion",id:"peerJobsLogsModalAccordion"},P={class:"accordion-header"},M=["data-bs-target"],B={key:0},N={class:"text-muted"},D=["id"],T={class:"accordion-body"},V={key:1,class:"card shadow-sm",style:{height:"153px"}},F={class:"card-body text-muted text-center d-flex"},O={class:"m-auto"};function W(a,o,E,I,R,q){const n=c("LocaleText"),u=c("SchedulePeerJob");return t(),r("div",w,[e("div",$,[e("div",k,[e("div",A,[e("div",L,[e("h4",S,[l(n,{t:"All Active Jobs"})]),e("button",{type:"button",class:"btn-close ms-auto",onClick:o[0]||(o[0]=s=>this.$emit("close"))})]),e("div",j,[e("button",{class:"btn bg-primary-subtle border-1 border-primary-subtle text-primary-emphasis rounded-3 shadow mb-2",onClick:o[1]||(o[1]=s=>this.$emit("allLogs"))},[o[4]||(o[4]=e("i",{class:"bi bi-clock me-2"},null,-1)),l(n,{t:"Logs"})]),this.getAllJobs.length>0?(t(),r("div",C,[(t(!0),r(p,null,b(this.getAllJobs,(s,d)=>(t(),r("div",{class:"accordion-item",key:s.id},[e("h2",P,[e("button",{class:"accordion-button collapsed",type:"button","data-bs-toggle":"collapse","data-bs-target":"#collapse_"+d},[e("small",null,[e("strong",null,[s.name?(t(),r("span",B,m(s.name)+" • ",1)):v("",!0),e("samp",N,m(s.id),1)])])],8,M)]),e("div",{id:"collapse_"+d,class:"accordion-collapse collapse","data-bs-parent":"#peerJobsLogsModalAccordion"},[e("div",T,[(t(!0),r(p,null,b(s.jobs,i=>(t(),f(u,{onDelete:o[2]||(o[2]=h=>this.$emit("refresh")),onRefresh:o[3]||(o[3]=h=>this.$emit("refresh")),dropdowns:this.store.PeerScheduleJobs.dropdowns,viewOnly:!0,key:i.JobID,pjob:i},null,8,["dropdowns","pjob"]))),128))])],8,D)]))),128))])):(t(),r("div",V,[e("div",F,[e("span",O,[l(n,{t:"No active job at the moment."})])])]))])])])])])}const U=g(J,[["render",W]]);export{U as default};
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{Q as l}from"./browser-BmbEXfbp.js";import{L as _}from"./localeText-C3GiyveB.js";import{_ as h,h as f,c,a as s,b as e,d as p,e as i,j as m,n as u,g,D as v}from"./index-BQYwwrw6.js";import"./galois-field-I2lBzzs-.js";const w={name:"peerQRCode",components:{LocaleText:_},props:{selectedPeer:Object},setup(){return{dashboardStore:v()}},data(){return{loading:!0}},mounted(){g("/api/downloadPeer/"+this.$route.params.id,{id:this.selectedPeer.id},o=>{if(this.loading=!1,o.status){let t="";if(this.selectedPeer.configuration.Protocol==="awg"){let a={containers:[{awg:{isThirdPartyConfig:!0,last_config:o.data.file,port:this.selectedPeer.configuration.ListenPort,transport_proto:"udp"},container:"amnezia-awg"}],defaultContainer:"amnezia-awg",description:this.selectedPeer.name,hostName:this.dashboardStore.Configuration.Peers.remote_endpoint};l.toCanvas(document.querySelector("#awg_vpn_qrcode"),btoa(JSON.stringify(a)),d=>{d&&console.error(d)})}t=o.data.file,l.toCanvas(document.querySelector("#qrcode"),t,a=>{a&&console.error(a)})}else this.dashboardStore.newMessage("Server",o.message,"danger")})}},b={class:"peerSettingContainer w-100 h-100 position-absolute top-0 start-0"},x={class:"container d-flex h-100 w-100"},P={class:"m-auto modal-dialog-centered dashboardModal justify-content-center"},C={class:"card rounded-3 shadow"},y={class:"card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-0"},S={class:"mb-0"},k={class:"card-body p-4"},q={class:"d-flex gap-2 flex-column"},L={class:"d-flex flex-column gap-2 align-items-center"},N={key:0,class:"d-flex flex-column gap-2 align-items-center"},Q={key:1,class:"spinner-border m-auto",role:"status"};function z(o,t,a,d,r,A){const n=f("LocaleText");return s(),c("div",b,[e("div",x,[e("div",P,[e("div",C,[e("div",y,[e("h4",S,[p(n,{t:"QR Code"})]),e("button",{type:"button",class:"btn-close ms-auto",onClick:t[0]||(t[0]=R=>this.$emit("close"))})]),e("div",k,[e("div",q,[e("div",L,[e("canvas",{id:"qrcode",style:{width:"200px !important",height:"200px !important"},class:u(["rounded-3 shadow animate__animated animate__fadeIn animate__faster qrcode",{"d-none":r.loading}])},null,2),this.selectedPeer.configuration.Protocol==="wg"?(s(),m(n,{key:0,t:"Scan with WireGuard App",class:"text-muted"})):i("",!0),this.selectedPeer.configuration.Protocol==="awg"?(s(),m(n,{key:1,t:"Scan with AmneziaWG App",class:"text-muted"})):i("",!0)]),this.selectedPeer.configuration.Protocol==="awg"?(s(),c("div",N,[e("canvas",{id:"awg_vpn_qrcode",class:u(["rounded-3 shadow animate__animated animate__fadeIn animate__faster qrcode",{"d-none":r.loading}])},null,2),p(n,{t:"Scan with AmneziaVPN App",class:"text-muted"})])):i("",!0),r.loading?(s(),c("div",Q,[...t[1]||(t[1]=[e("span",{class:"visually-hidden"},"Loading...",-1)])])):i("",!0)])])])])])])}const $=h(w,[["render",z],["__scopeId","data-v-02f2240d"]]);export{$ as default};
|
import{Q as l}from"./browser-CdT-qU-v.js";import{L as _}from"./localeText-CzYZfO0n.js";import{_ as h,h as f,c,a as s,b as e,d as p,e as i,j as m,n as u,g,D as v}from"./index-BuOf6BZp.js";import"./galois-field-I2lBzzs-.js";const w={name:"peerQRCode",components:{LocaleText:_},props:{selectedPeer:Object},setup(){return{dashboardStore:v()}},data(){return{loading:!0}},mounted(){g("/api/downloadPeer/"+this.$route.params.id,{id:this.selectedPeer.id},o=>{if(this.loading=!1,o.status){let t="";if(this.selectedPeer.configuration.Protocol==="awg"){let a={containers:[{awg:{isThirdPartyConfig:!0,last_config:o.data.file,port:this.selectedPeer.configuration.ListenPort,transport_proto:"udp"},container:"amnezia-awg"}],defaultContainer:"amnezia-awg",description:this.selectedPeer.name,hostName:this.dashboardStore.Configuration.Peers.remote_endpoint};l.toCanvas(document.querySelector("#awg_vpn_qrcode"),btoa(JSON.stringify(a)),d=>{d&&console.error(d)})}t=o.data.file,l.toCanvas(document.querySelector("#qrcode"),t,a=>{a&&console.error(a)})}else this.dashboardStore.newMessage("Server",o.message,"danger")})}},b={class:"peerSettingContainer w-100 h-100 position-absolute top-0 start-0"},x={class:"container d-flex h-100 w-100"},P={class:"m-auto modal-dialog-centered dashboardModal justify-content-center"},C={class:"card rounded-3 shadow"},y={class:"card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-0"},S={class:"mb-0"},k={class:"card-body p-4"},q={class:"d-flex gap-2 flex-column"},L={class:"d-flex flex-column gap-2 align-items-center"},N={key:0,class:"d-flex flex-column gap-2 align-items-center"},Q={key:1,class:"spinner-border m-auto",role:"status"};function z(o,t,a,d,r,A){const n=f("LocaleText");return s(),c("div",b,[e("div",x,[e("div",P,[e("div",C,[e("div",y,[e("h4",S,[p(n,{t:"QR Code"})]),e("button",{type:"button",class:"btn-close ms-auto",onClick:t[0]||(t[0]=R=>this.$emit("close"))})]),e("div",k,[e("div",q,[e("div",L,[e("canvas",{id:"qrcode",style:{width:"200px !important",height:"200px !important"},class:u(["rounded-3 shadow animate__animated animate__fadeIn animate__faster qrcode",{"d-none":r.loading}])},null,2),this.selectedPeer.configuration.Protocol==="wg"?(s(),m(n,{key:0,t:"Scan with WireGuard App",class:"text-muted"})):i("",!0),this.selectedPeer.configuration.Protocol==="awg"?(s(),m(n,{key:1,t:"Scan with AmneziaWG App",class:"text-muted"})):i("",!0)]),this.selectedPeer.configuration.Protocol==="awg"?(s(),c("div",N,[e("canvas",{id:"awg_vpn_qrcode",class:u(["rounded-3 shadow animate__animated animate__fadeIn animate__faster qrcode",{"d-none":r.loading}])},null,2),p(n,{t:"Scan with AmneziaVPN App",class:"text-muted"})])):i("",!0),r.loading?(s(),c("div",Q,[...t[1]||(t[1]=[e("span",{class:"visually-hidden"},"Loading...",-1)])])):i("",!0)])])])])])])}const $=h(w,[["render",z],["__scopeId","data-v-02f2240d"]]);export{$ as default};
|
||||||
@@ -1 +1 @@
|
|||||||
import{_ as p,q as m,G as f,W as h,r as u,a2 as _,L as v,K as g,o as x,a3 as S,c as b,e as y,a as B,b as s,m as w,y as T}from"./index-BQYwwrw6.js";const q={key:0,class:"fixed-bottom w-100 bottom-0 z-2 p-3",style:{"z-index":"1"}},C={class:"d-flex flex-column searchPeersContainer ms-auto p-2 rounded-5",style:{width:"300px"}},P={class:"rounded-5 border border-white p-2 d-flex align-items-center gap-1 w-100"},R=["placeholder"],k={__name:"peerSearchBar",props:["ConfigurationInfo"],emits:["close"],setup(V,{emit:z}){const l=m(()=>f("Search Peers..."));let r;const t=h(),e=u(t.searchString),d=()=>{r?(clearTimeout(r),r=setTimeout(()=>{t.searchString=e.value},300)):r=setTimeout(()=>{t.searchString=e.value},300)};_("searchBar");const a=v(),i=g();a.query.peer&&(e.value=a.query.peer,i.replace({query:null}));const n=u(!0);return x(()=>{document.querySelector("#searchPeers").focus()}),S(()=>{n.value=!1}),(G,o)=>n.value?(B(),b("div",q,[s("div",C,[s("div",P,[w(s("input",{ref:"searchBar",class:"flex-grow-1 form-control form-control-sm rounded-5 bg-transparent border-0 border-secondary-subtle",placeholder:l.value,id:"searchPeers",onKeyup:o[0]||(o[0]=c=>d()),"onUpdate:modelValue":o[1]||(o[1]=c=>e.value=c)},null,40,R),[[T,e.value]])])])])):y("",!0)}},K=p(k,[["__scopeId","data-v-576347d8"]]);export{K as default};
|
import{_ as p,q as m,G as f,W as h,r as u,a2 as _,L as v,K as g,o as x,a3 as S,c as b,e as y,a as B,b as s,m as w,y as T}from"./index-BuOf6BZp.js";const q={key:0,class:"fixed-bottom w-100 bottom-0 z-2 p-3",style:{"z-index":"1"}},C={class:"d-flex flex-column searchPeersContainer ms-auto p-2 rounded-5",style:{width:"300px"}},P={class:"rounded-5 border border-white p-2 d-flex align-items-center gap-1 w-100"},R=["placeholder"],k={__name:"peerSearchBar",props:["ConfigurationInfo"],emits:["close"],setup(V,{emit:z}){const l=m(()=>f("Search Peers..."));let r;const t=h(),e=u(t.searchString),d=()=>{r?(clearTimeout(r),r=setTimeout(()=>{t.searchString=e.value},300)):r=setTimeout(()=>{t.searchString=e.value},300)};_("searchBar");const a=v(),i=g();a.query.peer&&(e.value=a.query.peer,i.replace({query:null}));const n=u(!0);return x(()=>{document.querySelector("#searchPeers").focus()}),S(()=>{n.value=!1}),(G,o)=>n.value?(B(),b("div",q,[s("div",C,[s("div",P,[w(s("input",{ref:"searchBar",class:"flex-grow-1 form-control form-control-sm rounded-5 bg-transparent border-0 border-secondary-subtle",placeholder:l.value,id:"searchPeers",onKeyup:o[0]||(o[0]=c=>d()),"onUpdate:modelValue":o[1]||(o[1]=c=>e.value=c)},null,40,R),[[T,e.value]])])])])):y("",!0)}},K=p(k,[["__scopeId","data-v-576347d8"]]);export{K as default};
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{_ as h,c as o,a as d,b as e,m as c,e as m,d as r,h as f,y as g,n as v,t as p,z as b,D as w,A as x}from"./index-BQYwwrw6.js";import{L as _}from"./localeText-C3GiyveB.js";const k={components:{LocaleText:_},props:{targetData:String,title:String,warning:!1,warningText:""},setup(){const s=w(),t=`input_${x()}`;return{store:s,uuid:t}},data(){return{value:"",invalidFeedback:"",showInvalidFeedback:!1,isValid:!1,timeout:void 0,changed:!1,updating:!1}},mounted(){this.value=this.store.Configuration.Peers[this.targetData]},methods:{async useValidation(){this.changed&&await b("/api/updateDashboardConfigurationItem",{section:"Peers",key:this.targetData,value:this.value},s=>{s.status?(this.isValid=!0,this.showInvalidFeedback=!1,this.store.Configuration.Peers[this.targetData]=this.value,clearTimeout(this.timeout),this.timeout=setTimeout(()=>this.isValid=!1,5e3)):(this.isValid=!1,this.showInvalidFeedback=!0,this.invalidFeedback=s.message),this.changed=!1,this.updating=!1})}}},V={class:"form-group mb-2"},D=["for"],y=["id","disabled"],T={class:"invalid-feedback"},C={key:0,class:"px-2 py-1 text-warning-emphasis bg-warning-subtle border border-warning-subtle rounded-2 d-inline-block mt-1"};function F(s,t,a,I,n,u){const l=f("LocaleText");return d(),o("div",V,[e("label",{for:this.uuid,class:"text-muted mb-1"},[e("strong",null,[e("small",null,[r(l,{t:this.title},null,8,["t"])])])],8,D),c(e("input",{type:"text",class:v(["form-control",{"is-invalid":n.showInvalidFeedback,"is-valid":n.isValid}]),id:this.uuid,"onUpdate:modelValue":t[0]||(t[0]=i=>this.value=i),onKeydown:t[1]||(t[1]=i=>this.changed=!0),onBlur:t[2]||(t[2]=i=>u.useValidation()),disabled:this.updating},null,42,y),[[g,this.value]]),e("div",T,p(this.invalidFeedback),1),a.warning?(d(),o("div",C,[e("small",null,[t[3]||(t[3]=e("i",{class:"bi bi-exclamation-triangle-fill me-2"},null,-1)),r(l,{t:a.warningText},null,8,["t"])])])):m("",!0)])}const B=h(k,[["render",F]]);export{B as P};
|
import{_ as h,c as o,a as d,b as e,m as c,e as m,d as r,h as f,y as g,n as v,t as p,z as b,D as w,A as x}from"./index-BuOf6BZp.js";import{L as _}from"./localeText-CzYZfO0n.js";const k={components:{LocaleText:_},props:{targetData:String,title:String,warning:!1,warningText:""},setup(){const s=w(),t=`input_${x()}`;return{store:s,uuid:t}},data(){return{value:"",invalidFeedback:"",showInvalidFeedback:!1,isValid:!1,timeout:void 0,changed:!1,updating:!1}},mounted(){this.value=this.store.Configuration.Peers[this.targetData]},methods:{async useValidation(){this.changed&&await b("/api/updateDashboardConfigurationItem",{section:"Peers",key:this.targetData,value:this.value},s=>{s.status?(this.isValid=!0,this.showInvalidFeedback=!1,this.store.Configuration.Peers[this.targetData]=this.value,clearTimeout(this.timeout),this.timeout=setTimeout(()=>this.isValid=!1,5e3)):(this.isValid=!1,this.showInvalidFeedback=!0,this.invalidFeedback=s.message),this.changed=!1,this.updating=!1})}}},V={class:"form-group mb-2"},D=["for"],y=["id","disabled"],T={class:"invalid-feedback"},C={key:0,class:"px-2 py-1 text-warning-emphasis bg-warning-subtle border border-warning-subtle rounded-2 d-inline-block mt-1"};function F(s,t,a,I,n,u){const l=f("LocaleText");return d(),o("div",V,[e("label",{for:this.uuid,class:"text-muted mb-1"},[e("strong",null,[e("small",null,[r(l,{t:this.title},null,8,["t"])])])],8,D),c(e("input",{type:"text",class:v(["form-control",{"is-invalid":n.showInvalidFeedback,"is-valid":n.isValid}]),id:this.uuid,"onUpdate:modelValue":t[0]||(t[0]=i=>this.value=i),onKeydown:t[1]||(t[1]=i=>this.changed=!0),onBlur:t[2]||(t[2]=i=>u.useValidation()),disabled:this.updating},null,42,y),[[g,this.value]]),e("div",T,p(this.invalidFeedback),1),a.warning?(d(),o("div",C,[e("small",null,[t[3]||(t[3]=e("i",{class:"bi bi-exclamation-triangle-fill me-2"},null,-1)),r(l,{t:a.warningText},null,8,["t"])])])):m("",!0)])}const B=h(k,[["render",F]]);export{B as P};
|
||||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{L as n}from"./localeText-C3GiyveB.js";import{c as a,a as e,e as r,f as s,j as i}from"./index-BQYwwrw6.js";const d={class:"position-relative"},c={key:0,class:"badge wireguardBg rounded-3 shadow z-1"},l={key:1,class:"badge amneziawgBg rounded-3 shadow"},p={__name:"protocolBadge",props:{protocol:String,mini:!1},setup(o){return(m,t)=>(e(),a("div",d,[o.protocol==="wg"?(e(),a("span",c,[t[0]||(t[0]=s(" WireGuard ",-1)),o.mini?r("",!0):(e(),i(n,{key:0,t:"Configuration"}))])):o.protocol==="awg"?(e(),a("span",l,[t[1]||(t[1]=s(" AmneziaWG ",-1)),o.mini?r("",!0):(e(),i(n,{key:0,t:"Configuration"}))])):r("",!0)]))}};export{p as _};
|
import{L as n}from"./localeText-CzYZfO0n.js";import{c as a,a as e,e as r,f as s,j as i}from"./index-BuOf6BZp.js";const d={class:"position-relative"},c={key:0,class:"badge wireguardBg rounded-3 shadow z-1"},l={key:1,class:"badge amneziawgBg rounded-3 shadow"},p={__name:"protocolBadge",props:{protocol:String,mini:!1},setup(o){return(m,t)=>(e(),a("div",d,[o.protocol==="wg"?(e(),a("span",c,[t[0]||(t[0]=s(" WireGuard ",-1)),o.mini?r("",!0):(e(),i(n,{key:0,t:"Configuration"}))])):o.protocol==="awg"?(e(),a("span",l,[t[1]||(t[1]=s(" AmneziaWG ",-1)),o.mini?r("",!0):(e(),i(n,{key:0,t:"Configuration"}))])):r("",!0)]))}};export{p as _};
|
||||||
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
@@ -1 +1 @@
|
|||||||
import{_ as c,z as D,D as m,A as x,c as i,a as o,b as t,t as S,m as l,y as u,f as p,d as n,F as $,i as w,h as r,w as I}from"./index-BQYwwrw6.js";import{P}from"./peersDefaultSettingsInput-De2pvmfF.js";import{A as k,a as A,D as y,b as C,c as V,d as F,e as T,_ as L}from"./dashboardEmailSettings-p_Bw0Z58.js";import{D as R,a as W}from"./dashboardSettingsWireguardConfigurationAutostart-cyw0vUzN.js";import{L as U}from"./localeText-C3GiyveB.js";import"./dayjs.min-CzHDLgWx.js";import"./vue-datepicker-g3vsoQR2.js";const B={name:"dashboardSettingsInputIPAddressAndPort",props:{},setup(){const e=m(),s=`input_${x()}`;return{store:e,uuid:s}},data(){return{app_ip:"",app_port:"",invalidFeedback:"",showInvalidFeedback:!1,isValid:!1,timeout:void 0,changed:!1,updating:!1}},mounted(){this.app_ip=this.store.Configuration.Server.app_ip,this.app_port=this.store.Configuration.Server.app_port},methods:{async useValidation(){this.changed&&await D("/api/updateDashboardConfigurationItem",{section:"Server",key:this.targetData,value:this.value},e=>{e.status?(this.isValid=!0,this.showInvalidFeedback=!1,this.store.Configuration.Account[this.targetData]=this.value,clearTimeout(this.timeout),this.timeout=setTimeout(()=>this.isValid=!1,5e3)):(this.isValid=!1,this.showInvalidFeedback=!0,this.invalidFeedback=e.message)})}}},G={class:"invalid-feedback d-block mt-0"},N={class:"row"},E={class:"form-group mb-2 col-sm"},M=["for"],j=["id"],z={class:"form-group col-sm"},K=["for"],q=["id"];function H(e,s,h,_,b,f){return o(),i("div",null,[t("div",G,S(this.invalidFeedback),1),t("div",N,[t("div",E,[t("label",{for:"app_ip_"+this.uuid,class:"text-muted mb-1"},[...s[2]||(s[2]=[t("strong",null,[t("small",null,"Dashboard IP Address")],-1)])],8,M),l(t("input",{type:"text",class:"form-control mb-2",id:"app_ip_"+this.uuid,"onUpdate:modelValue":s[0]||(s[0]=a=>this.app_ip=a)},null,8,j),[[u,this.app_ip]]),s[3]||(s[3]=t("div",{class:"px-2 py-1 text-warning-emphasis bg-warning-subtle border border-warning-subtle rounded-2 d-inline-block"},[t("small",null,[t("i",{class:"bi bi-exclamation-triangle-fill me-2"}),t("code",null,"0.0.0.0"),p(" means it can be access by anyone with your server IP Address.")])],-1))]),t("div",z,[t("label",{for:"app_port_"+this.uuid,class:"text-muted mb-1"},[...s[4]||(s[4]=[t("strong",null,[t("small",null,"Dashboard Port")],-1)])],8,K),l(t("input",{type:"text",class:"form-control mb-2",id:"app_port_"+this.uuid,"onUpdate:modelValue":s[1]||(s[1]=a=>this.app_port=a)},null,8,q),[[u,this.app_port]])])]),s[5]||(s[5]=t("button",{class:"btn btn-success btn-sm fw-bold rounded-3"},[t("i",{class:"bi bi-floppy-fill me-2"}),p("Update Dashboard Settings & Restart ")],-1))])}const J=c(B,[["render",H]]),O={name:"settings",components:{DashboardEmailSettings:L,DashboardSettingsWireguardConfigurationAutostart:W,DashboardIPPortInput:T,DashboardLanguage:F,LocaleText:U,AccountSettingsMFA:V,DashboardAPIKeys:C,DashboardSettingsInputIPAddressAndPort:J,DashboardTheme:y,DashboardSettingsInputWireguardConfigurationPath:R,AccountSettingsInputPassword:A,AccountSettingsInputUsername:k,PeersDefaultSettingsInput:P},setup(){return{dashboardConfigurationStore:m()}},data(){return{activeTab:"WGDashboard",tabs:[{id:"",title:"WGDashboard Settings"},{id:"peers_settings",title:"Peers Settings"},{id:"wireguard_settings",title:"WireGuard Configuration Settings"}]}}},Q={class:"mt-md-5 mt-3 text-body mb-3"},X={class:"container-md d-flex flex-column gap-3"},Y={class:"border-bottom pb-3"},Z={class:"nav nav-pills nav-justified align-items-center gap-2"},tt={class:"nav-item"},st={class:"my-2"};function et(e,s,h,_,b,f){const a=r("LocaleText"),g=r("RouterLink"),v=r("RouterView");return o(),i("div",Q,[t("div",X,[t("div",Y,[t("ul",Z,[(o(!0),i($,null,w(this.tabs,d=>(o(),i("li",tt,[n(g,{to:{name:d.title},class:"nav-link rounded-3","exact-active-class":"active",role:"button"},{default:I(()=>[t("h6",st,[n(a,{t:d.title},null,8,["t"])])]),_:2},1032,["to"])]))),256))])]),n(v)])])}const ut=c(O,[["render",et]]);export{ut as default};
|
import{_ as c,z as D,D as m,A as x,c as i,a as o,b as t,t as S,m as l,y as u,f as p,d as n,F as $,i as w,h as r,w as I}from"./index-BuOf6BZp.js";import{P}from"./peersDefaultSettingsInput-BYUvwHVp.js";import{A as k,a as A,D as y,b as C,c as V,d as F,e as T,_ as L}from"./dashboardEmailSettings-CPNkx_Qa.js";import{D as R,a as W}from"./dashboardSettingsWireguardConfigurationAutostart-Ci0ScLhC.js";import{L as U}from"./localeText-CzYZfO0n.js";import"./dayjs.min-BzBvZaAI.js";import"./vue-datepicker-B81xP9h3.js";const B={name:"dashboardSettingsInputIPAddressAndPort",props:{},setup(){const e=m(),s=`input_${x()}`;return{store:e,uuid:s}},data(){return{app_ip:"",app_port:"",invalidFeedback:"",showInvalidFeedback:!1,isValid:!1,timeout:void 0,changed:!1,updating:!1}},mounted(){this.app_ip=this.store.Configuration.Server.app_ip,this.app_port=this.store.Configuration.Server.app_port},methods:{async useValidation(){this.changed&&await D("/api/updateDashboardConfigurationItem",{section:"Server",key:this.targetData,value:this.value},e=>{e.status?(this.isValid=!0,this.showInvalidFeedback=!1,this.store.Configuration.Account[this.targetData]=this.value,clearTimeout(this.timeout),this.timeout=setTimeout(()=>this.isValid=!1,5e3)):(this.isValid=!1,this.showInvalidFeedback=!0,this.invalidFeedback=e.message)})}}},G={class:"invalid-feedback d-block mt-0"},N={class:"row"},E={class:"form-group mb-2 col-sm"},M=["for"],j=["id"],z={class:"form-group col-sm"},K=["for"],q=["id"];function H(e,s,h,_,b,f){return o(),i("div",null,[t("div",G,S(this.invalidFeedback),1),t("div",N,[t("div",E,[t("label",{for:"app_ip_"+this.uuid,class:"text-muted mb-1"},[...s[2]||(s[2]=[t("strong",null,[t("small",null,"Dashboard IP Address")],-1)])],8,M),l(t("input",{type:"text",class:"form-control mb-2",id:"app_ip_"+this.uuid,"onUpdate:modelValue":s[0]||(s[0]=a=>this.app_ip=a)},null,8,j),[[u,this.app_ip]]),s[3]||(s[3]=t("div",{class:"px-2 py-1 text-warning-emphasis bg-warning-subtle border border-warning-subtle rounded-2 d-inline-block"},[t("small",null,[t("i",{class:"bi bi-exclamation-triangle-fill me-2"}),t("code",null,"0.0.0.0"),p(" means it can be access by anyone with your server IP Address.")])],-1))]),t("div",z,[t("label",{for:"app_port_"+this.uuid,class:"text-muted mb-1"},[...s[4]||(s[4]=[t("strong",null,[t("small",null,"Dashboard Port")],-1)])],8,K),l(t("input",{type:"text",class:"form-control mb-2",id:"app_port_"+this.uuid,"onUpdate:modelValue":s[1]||(s[1]=a=>this.app_port=a)},null,8,q),[[u,this.app_port]])])]),s[5]||(s[5]=t("button",{class:"btn btn-success btn-sm fw-bold rounded-3"},[t("i",{class:"bi bi-floppy-fill me-2"}),p("Update Dashboard Settings & Restart ")],-1))])}const J=c(B,[["render",H]]),O={name:"settings",components:{DashboardEmailSettings:L,DashboardSettingsWireguardConfigurationAutostart:W,DashboardIPPortInput:T,DashboardLanguage:F,LocaleText:U,AccountSettingsMFA:V,DashboardAPIKeys:C,DashboardSettingsInputIPAddressAndPort:J,DashboardTheme:y,DashboardSettingsInputWireguardConfigurationPath:R,AccountSettingsInputPassword:A,AccountSettingsInputUsername:k,PeersDefaultSettingsInput:P},setup(){return{dashboardConfigurationStore:m()}},data(){return{activeTab:"WGDashboard",tabs:[{id:"",title:"WGDashboard Settings"},{id:"peers_settings",title:"Peers Settings"},{id:"wireguard_settings",title:"WireGuard Configuration Settings"}]}}},Q={class:"mt-md-5 mt-3 text-body mb-3"},X={class:"container-md d-flex flex-column gap-3"},Y={class:"border-bottom pb-3"},Z={class:"nav nav-pills nav-justified align-items-center gap-2"},tt={class:"nav-item"},st={class:"my-2"};function et(e,s,h,_,b,f){const a=r("LocaleText"),g=r("RouterLink"),v=r("RouterView");return o(),i("div",Q,[t("div",X,[t("div",Y,[t("ul",Z,[(o(!0),i($,null,w(this.tabs,d=>(o(),i("li",tt,[n(g,{to:{name:d.title},class:"nav-link rounded-3","exact-active-class":"active",role:"button"},{default:I(()=>[t("h6",st,[n(a,{t:d.title},null,8,["t"])])]),_:2},1032,["to"])]))),256))])]),n(v)])])}const ut=c(O,[["render",et]]);export{ut as default};
|
||||||
@@ -1 +1 @@
|
|||||||
import{_ as u,c as r,a as i,b as e,d as o,h as m,f as p,e as c,t as h,m as l,y as d,z as f,D as w}from"./index-BQYwwrw6.js";import{L as g}from"./localeText-C3GiyveB.js";const b={name:"setup",components:{LocaleText:g},setup(){return{store:w()}},data(){return{setup:{username:"",newPassword:"",repeatNewPassword:"",enable_totp:!0},loading:!1,errorMessage:"",done:!1}},computed:{goodToSubmit(){return this.setup.username&&this.setup.newPassword.length>=8&&this.setup.repeatNewPassword.length>=8&&this.setup.newPassword===this.setup.repeatNewPassword}},methods:{submit(){this.loading=!0,f("/api/Welcome_Finish",this.setup,n=>{n.status?(this.done=!0,this.$router.push("/2FASetup")):(document.querySelectorAll("#createAccount input").forEach(s=>s.classList.add("is-invalid")),this.errorMessage=n.message,document.querySelector(".login-container-fluid").scrollTo({top:0,left:0,behavior:"smooth"})),this.loading=!1})}}},_=["data-bs-theme"],x={class:"m-auto text-body",style:{width:"500px"}},v={class:"dashboardLogo display-4"},y={class:"mb-5"},P={key:0,class:"alert alert-danger"},N={class:"d-flex flex-column gap-3"},k={id:"createAccount",class:"d-flex flex-column gap-2"},S={class:"form-group text-body"},T={for:"username",class:"mb-1 text-muted"},C={class:"form-group text-body"},L={for:"password",class:"mb-1 text-muted"},V={class:"form-group text-body"},$={for:"confirmPassword",class:"mb-1 text-muted"},q=["disabled"],A={key:0,class:"d-flex align-items-center w-100"},M={key:1,class:"d-flex align-items-center w-100"};function B(n,s,D,E,U,F){const t=m("LocaleText");return i(),r("div",{class:"container-fluid login-container-fluid d-flex main pt-5 overflow-scroll","data-bs-theme":this.store.Configuration.Server.dashboard_theme},[e("div",x,[e("span",v,[o(t,{t:"Nice to meet you!"})]),e("p",y,[o(t,{t:"Please fill in the following fields to finish setup"}),s[4]||(s[4]=p(" 😊",-1))]),e("div",null,[e("h3",null,[o(t,{t:"Create an account"})]),this.errorMessage?(i(),r("div",P,h(this.errorMessage),1)):c("",!0),e("div",N,[e("form",k,[e("div",S,[e("label",T,[e("small",null,[o(t,{t:"Enter an username you like"})])]),l(e("input",{type:"text",autocomplete:"username","onUpdate:modelValue":s[0]||(s[0]=a=>this.setup.username=a),class:"form-control",id:"username",name:"username",required:""},null,512),[[d,this.setup.username]])]),e("div",C,[e("label",L,[e("small",null,[o(t,{t:"Enter a password"}),e("code",null,[o(t,{t:"(At least 8 characters and make sure is strong enough!)"})])])]),l(e("input",{type:"password",autocomplete:"new-password","onUpdate:modelValue":s[1]||(s[1]=a=>this.setup.newPassword=a),class:"form-control",id:"password",name:"password",required:""},null,512),[[d,this.setup.newPassword]])]),e("div",V,[e("label",$,[e("small",null,[o(t,{t:"Confirm password"})])]),l(e("input",{type:"password",autocomplete:"confirm-new-password","onUpdate:modelValue":s[2]||(s[2]=a=>this.setup.repeatNewPassword=a),class:"form-control",id:"confirmPassword",name:"confirmPassword",required:""},null,512),[[d,this.setup.repeatNewPassword]])])]),e("button",{class:"btn btn-dark btn-lg mb-5 d-flex btn-brand shadow align-items-center",ref:"signInBtn",disabled:!this.goodToSubmit||this.loading||this.done,onClick:s[3]||(s[3]=a=>this.submit())},[!this.loading&&!this.done?(i(),r("span",A,[o(t,{t:"Next"}),s[5]||(s[5]=e("i",{class:"bi bi-chevron-right ms-auto"},null,-1))])):(i(),r("span",M,[o(t,{t:"Saving..."}),s[6]||(s[6]=e("span",{class:"spinner-border ms-auto spinner-border-sm",role:"status"},[e("span",{class:"visually-hidden"},"Loading...")],-1))]))],8,q)])])])],8,_)}const W=u(b,[["render",B]]);export{W as default};
|
import{_ as u,c as r,a as i,b as e,d as o,h as m,f as p,e as c,t as h,m as l,y as d,z as f,D as w}from"./index-BuOf6BZp.js";import{L as g}from"./localeText-CzYZfO0n.js";const b={name:"setup",components:{LocaleText:g},setup(){return{store:w()}},data(){return{setup:{username:"",newPassword:"",repeatNewPassword:"",enable_totp:!0},loading:!1,errorMessage:"",done:!1}},computed:{goodToSubmit(){return this.setup.username&&this.setup.newPassword.length>=8&&this.setup.repeatNewPassword.length>=8&&this.setup.newPassword===this.setup.repeatNewPassword}},methods:{submit(){this.loading=!0,f("/api/Welcome_Finish",this.setup,n=>{n.status?(this.done=!0,this.$router.push("/2FASetup")):(document.querySelectorAll("#createAccount input").forEach(s=>s.classList.add("is-invalid")),this.errorMessage=n.message,document.querySelector(".login-container-fluid").scrollTo({top:0,left:0,behavior:"smooth"})),this.loading=!1})}}},_=["data-bs-theme"],x={class:"m-auto text-body",style:{width:"500px"}},v={class:"dashboardLogo display-4"},y={class:"mb-5"},P={key:0,class:"alert alert-danger"},N={class:"d-flex flex-column gap-3"},k={id:"createAccount",class:"d-flex flex-column gap-2"},S={class:"form-group text-body"},T={for:"username",class:"mb-1 text-muted"},C={class:"form-group text-body"},L={for:"password",class:"mb-1 text-muted"},V={class:"form-group text-body"},$={for:"confirmPassword",class:"mb-1 text-muted"},q=["disabled"],A={key:0,class:"d-flex align-items-center w-100"},M={key:1,class:"d-flex align-items-center w-100"};function B(n,s,D,E,U,F){const t=m("LocaleText");return i(),r("div",{class:"container-fluid login-container-fluid d-flex main pt-5 overflow-scroll","data-bs-theme":this.store.Configuration.Server.dashboard_theme},[e("div",x,[e("span",v,[o(t,{t:"Nice to meet you!"})]),e("p",y,[o(t,{t:"Please fill in the following fields to finish setup"}),s[4]||(s[4]=p(" 😊",-1))]),e("div",null,[e("h3",null,[o(t,{t:"Create an account"})]),this.errorMessage?(i(),r("div",P,h(this.errorMessage),1)):c("",!0),e("div",N,[e("form",k,[e("div",S,[e("label",T,[e("small",null,[o(t,{t:"Enter an username you like"})])]),l(e("input",{type:"text",autocomplete:"username","onUpdate:modelValue":s[0]||(s[0]=a=>this.setup.username=a),class:"form-control",id:"username",name:"username",required:""},null,512),[[d,this.setup.username]])]),e("div",C,[e("label",L,[e("small",null,[o(t,{t:"Enter a password"}),e("code",null,[o(t,{t:"(At least 8 characters and make sure is strong enough!)"})])])]),l(e("input",{type:"password",autocomplete:"new-password","onUpdate:modelValue":s[1]||(s[1]=a=>this.setup.newPassword=a),class:"form-control",id:"password",name:"password",required:""},null,512),[[d,this.setup.newPassword]])]),e("div",V,[e("label",$,[e("small",null,[o(t,{t:"Confirm password"})])]),l(e("input",{type:"password",autocomplete:"confirm-new-password","onUpdate:modelValue":s[2]||(s[2]=a=>this.setup.repeatNewPassword=a),class:"form-control",id:"confirmPassword",name:"confirmPassword",required:""},null,512),[[d,this.setup.repeatNewPassword]])])]),e("button",{class:"btn btn-dark btn-lg mb-5 d-flex btn-brand shadow align-items-center",ref:"signInBtn",disabled:!this.goodToSubmit||this.loading||this.done,onClick:s[3]||(s[3]=a=>this.submit())},[!this.loading&&!this.done?(i(),r("span",A,[o(t,{t:"Next"}),s[5]||(s[5]=e("i",{class:"bi bi-chevron-right ms-auto"},null,-1))])):(i(),r("span",M,[o(t,{t:"Saving..."}),s[6]||(s[6]=e("span",{class:"spinner-border ms-auto spinner-border-sm",role:"status"},[e("span",{class:"visually-hidden"},"Loading...")],-1))]))],8,q)])])])],8,_)}const W=u(b,[["render",B]]);export{W as default};
|
||||||
@@ -1 +1 @@
|
|||||||
import{_,c as m,a as f,b as t,d as r,h as p,r as c,D as h,g as u,L as b}from"./index-BQYwwrw6.js";import{Q as v}from"./browser-BmbEXfbp.js";import{L as y}from"./localeText-C3GiyveB.js";import"./galois-field-I2lBzzs-.js";const g={name:"share",components:{LocaleText:y},async setup(){const o=b(),e=c(!1),s=h(),n=c(""),i=c(void 0),d=c(new Blob);await u("/api/getDashboardTheme",{},l=>{n.value=l.data});const a=o.query.ShareID;return a===void 0||a.length===0?(i.value=void 0,e.value=!0):await u("/api/sharePeer/get",{ShareID:a},l=>{l.status?(i.value=l.data,d.value=new Blob([i.value.file],{type:"text/plain"})):i.value=void 0,e.value=!0}),{store:s,theme:n,peerConfiguration:i,blob:d}},mounted(){this.peerConfiguration&&v.toCanvas(document.querySelector("#qrcode"),this.peerConfiguration.file,o=>{o&&console.error(o)})},methods:{download(){const o=new Blob([this.peerConfiguration.file],{type:"text/plain"}),e=URL.createObjectURL(o),s=`${this.peerConfiguration.fileName}.conf`,n=document.createElement("a");n.href=e,n.download=s,n.click()}},computed:{getBlob(){return URL.createObjectURL(this.blob)}}},x=["data-bs-theme"],w={class:"m-auto text-body",style:{width:"500px"}},C={key:0,class:"text-center position-relative",style:{}},U={class:"position-absolute w-100 h-100 top-0 start-0 d-flex animate__animated animate__fadeInUp",style:{"animation-delay":"0.1s"}},L={class:"m-auto"},I={key:1,class:"d-flex align-items-center flex-column gap-3"},B={class:"h1 dashboardLogo text-center animate__animated animate__fadeInUp"},k={id:"qrcode",class:"rounded-3 shadow animate__animated animate__fadeInUp mb-3",ref:"qrcode"},R={class:"text-muted animate__animated animate__fadeInUp mb-1",style:{"animation-delay":"0.2s"}},D=["download","href"];function q(o,e,s,n,i,d){const a=p("LocaleText");return f(),m("div",{class:"container-fluid login-container-fluid d-flex main pt-5 overflow-scroll","data-bs-theme":this.theme},[t("div",w,[this.peerConfiguration?(f(),m("div",I,[t("div",B,[e[1]||(e[1]=t("h6",null,"WGDashboard",-1)),r(a,{t:"Scan QR Code with the WireGuard App to add peer"})]),t("canvas",k,null,512),t("p",R,[r(a,{t:"or click the button below to download the "}),e[2]||(e[2]=t("samp",null,".conf",-1)),r(a,{t:" file"})]),t("a",{download:this.peerConfiguration.fileName+".conf",href:d.getBlob,class:"btn btn-lg bg-primary-subtle text-primary-emphasis border-1 border-primary-subtle animate__animated animate__fadeInUp shadow-sm",style:{"animation-delay":"0.25s"}},[...e[3]||(e[3]=[t("i",{class:"bi bi-download"},null,-1)])],8,D)])):(f(),m("div",C,[e[0]||(e[0]=t("div",{class:"animate__animated animate__fadeInUp"},[t("h1",{style:{"font-size":"20rem",filter:"blur(1rem)","animation-duration":"7s"},class:"animate__animated animate__flash animate__infinite"},[t("i",{class:"bi bi-file-binary"})])],-1)),t("div",U,[t("h3",L,[r(a,{t:"Oh no... This link is either expired or invalid."})])])]))])],8,x)}const O=_(g,[["render",q],["__scopeId","data-v-1b44aacd"]]);export{O as default};
|
import{_,c as m,a as f,b as t,d as r,h as p,r as c,D as h,g as u,L as b}from"./index-BuOf6BZp.js";import{Q as v}from"./browser-CdT-qU-v.js";import{L as y}from"./localeText-CzYZfO0n.js";import"./galois-field-I2lBzzs-.js";const g={name:"share",components:{LocaleText:y},async setup(){const o=b(),e=c(!1),s=h(),n=c(""),i=c(void 0),d=c(new Blob);await u("/api/getDashboardTheme",{},l=>{n.value=l.data});const a=o.query.ShareID;return a===void 0||a.length===0?(i.value=void 0,e.value=!0):await u("/api/sharePeer/get",{ShareID:a},l=>{l.status?(i.value=l.data,d.value=new Blob([i.value.file],{type:"text/plain"})):i.value=void 0,e.value=!0}),{store:s,theme:n,peerConfiguration:i,blob:d}},mounted(){this.peerConfiguration&&v.toCanvas(document.querySelector("#qrcode"),this.peerConfiguration.file,o=>{o&&console.error(o)})},methods:{download(){const o=new Blob([this.peerConfiguration.file],{type:"text/plain"}),e=URL.createObjectURL(o),s=`${this.peerConfiguration.fileName}.conf`,n=document.createElement("a");n.href=e,n.download=s,n.click()}},computed:{getBlob(){return URL.createObjectURL(this.blob)}}},x=["data-bs-theme"],w={class:"m-auto text-body",style:{width:"500px"}},C={key:0,class:"text-center position-relative",style:{}},U={class:"position-absolute w-100 h-100 top-0 start-0 d-flex animate__animated animate__fadeInUp",style:{"animation-delay":"0.1s"}},L={class:"m-auto"},I={key:1,class:"d-flex align-items-center flex-column gap-3"},B={class:"h1 dashboardLogo text-center animate__animated animate__fadeInUp"},k={id:"qrcode",class:"rounded-3 shadow animate__animated animate__fadeInUp mb-3",ref:"qrcode"},R={class:"text-muted animate__animated animate__fadeInUp mb-1",style:{"animation-delay":"0.2s"}},D=["download","href"];function q(o,e,s,n,i,d){const a=p("LocaleText");return f(),m("div",{class:"container-fluid login-container-fluid d-flex main pt-5 overflow-scroll","data-bs-theme":this.theme},[t("div",w,[this.peerConfiguration?(f(),m("div",I,[t("div",B,[e[1]||(e[1]=t("h6",null,"WGDashboard",-1)),r(a,{t:"Scan QR Code with the WireGuard App to add peer"})]),t("canvas",k,null,512),t("p",R,[r(a,{t:"or click the button below to download the "}),e[2]||(e[2]=t("samp",null,".conf",-1)),r(a,{t:" file"})]),t("a",{download:this.peerConfiguration.fileName+".conf",href:d.getBlob,class:"btn btn-lg bg-primary-subtle text-primary-emphasis border-1 border-primary-subtle animate__animated animate__fadeInUp shadow-sm",style:{"animation-delay":"0.25s"}},[...e[3]||(e[3]=[t("i",{class:"bi bi-download"},null,-1)])],8,D)])):(f(),m("div",C,[e[0]||(e[0]=t("div",{class:"animate__animated animate__fadeInUp"},[t("h1",{style:{"font-size":"20rem",filter:"blur(1rem)","animation-duration":"7s"},class:"animate__animated animate__flash animate__infinite"},[t("i",{class:"bi bi-file-binary"})])],-1)),t("div",U,[t("h3",L,[r(a,{t:"Oh no... This link is either expired or invalid."})])])]))])],8,x)}const O=_(g,[["render",q],["__scopeId","data-v-1b44aacd"]]);export{O as default};
|
||||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{_ as p,r as b,q as f,c as t,a as r,d as n,w as x,e as v,n as g,s as l,b as c,f as C,t as d,k as w,p as y}from"./index-BQYwwrw6.js";import{L as _}from"./localeText-C3GiyveB.js";const k={class:"text-muted me-2"},N={class:"fw-bold"},q={__name:"cpuCore",props:{core_number:Number,percentage:Number,align:Boolean,square:Boolean},setup(e){y(i=>({"60cb52de":s.value}));const u=e,o=b(!1),s=f(()=>u.square?"40px":"25px");return(i,a)=>(r(),t("div",{class:"flex-grow-1 square rounded-3 border position-relative p-2",onMouseenter:a[0]||(a[0]=m=>o.value=!0),onMouseleave:a[1]||(a[1]=m=>o.value=!1),style:l({"background-color":`rgb(13 110 253 / ${e.percentage*10}%)`})},[n(w,{name:"zoomReversed"},{default:x(()=>[o.value?(r(),t("div",{key:0,style:l([{"white-space":"nowrap"},{top:s.value}]),class:g(["floatingLabel z-3 border position-absolute d-block p-1 px-2 bg-body text-body rounded-3 border shadow d-flex",[e.align?"end-0":"start-0"]])},[c("small",k,[n(_,{t:"Core"}),C(" #"+d(e.core_number+1),1)]),c("small",N,d(e.percentage)+"% ",1)],6)):v("",!0)]),_:1})],36))}},h=p(q,[["__scopeId","data-v-f8963858"]]);export{h as C};
|
import{_ as p,r as b,q as f,c as t,a as r,d as n,w as x,e as v,n as g,s as l,b as c,f as C,t as d,k as w,p as y}from"./index-BuOf6BZp.js";import{L as _}from"./localeText-CzYZfO0n.js";const k={class:"text-muted me-2"},N={class:"fw-bold"},q={__name:"cpuCore",props:{core_number:Number,percentage:Number,align:Boolean,square:Boolean},setup(e){y(i=>({"60cb52de":s.value}));const u=e,o=b(!1),s=f(()=>u.square?"40px":"25px");return(i,a)=>(r(),t("div",{class:"flex-grow-1 square rounded-3 border position-relative p-2",onMouseenter:a[0]||(a[0]=m=>o.value=!0),onMouseleave:a[1]||(a[1]=m=>o.value=!1),style:l({"background-color":`rgb(13 110 253 / ${e.percentage*10}%)`})},[n(w,{name:"zoomReversed"},{default:x(()=>[o.value?(r(),t("div",{key:0,style:l([{"white-space":"nowrap"},{top:s.value}]),class:g(["floatingLabel z-3 border position-absolute d-block p-1 px-2 bg-body text-body rounded-3 border shadow d-flex",[e.align?"end-0":"start-0"]])},[c("small",k,[n(_,{t:"Core"}),C(" #"+d(e.core_number+1),1)]),c("small",N,d(e.percentage)+"% ",1)],6)):v("",!0)]),_:1})],36))}},h=p(q,[["__scopeId","data-v-f8963858"]]);export{h as C};
|
||||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{_ as h,c as m,a as n,b as t,d as i,h as d,t as p,m as f,y as _,j as r,w as c,z as b,D as v,g}from"./index-BQYwwrw6.js";import{Q as x}from"./browser-BmbEXfbp.js";import{L as y}from"./localeText-C3GiyveB.js";import"./galois-field-I2lBzzs-.js";const T={name:"totp",components:{LocaleText:y},async setup(){const s=v();let e="";return await g("/api/Welcome_GetTotpLink",{},(a=>{a.status&&(e=a.data)})),{l:e,store:s}},mounted(){this.l&&x.toCanvas(document.getElementById("qrcode"),this.l,function(s){})},data(){return{totp:"",totpInvalidMessage:"",verified:!1}},methods:{validateTotp(){}},watch:{totp(s){const e=document.querySelector("#totp");e.classList.remove("is-invalid","is-valid"),s.length===6&&(console.log(s),/[0-9]{6}/.test(s)?b("/api/Welcome_VerifyTotpLink",{totp:s},a=>{a.status?(this.verified=!0,e.classList.add("is-valid"),this.$emit("verified")):(e.classList.add("is-invalid"),this.totpInvalidMessage="TOTP does not match.")}):(e.classList.add("is-invalid"),this.totpInvalidMessage="TOTP can only contain numbers"))}}},k=["data-bs-theme"],L={class:"m-auto text-body",style:{width:"500px"}},w={class:"d-flex flex-column"},C={class:"dashboardLogo display-4"},M={class:"mb-2"},P={class:"text-muted"},I={class:"p-3 bg-body-secondary rounded-3 border mb-3"},O={class:"text-muted mb-0"},B=["href"],$={style:{"line-break":"anywhere"}},D={for:"totp",class:"mb-2"},R={class:"text-muted"},S={class:"form-group mb-2"},q=["disabled"],A={class:"invalid-feedback"},E={class:"valid-feedback"},F={class:"d-flex gap-3 mt-5 flex-column"};function Q(s,e,a,G,N,W){const o=d("LocaleText"),l=d("RouterLink");return n(),m("div",{class:"container-fluid login-container-fluid d-flex main pt-5 overflow-scroll","data-bs-theme":this.store.Configuration.Server.dashboard_theme},[t("div",L,[t("div",w,[t("div",null,[t("h1",C,[i(o,{t:"Multi-Factor Authentication (MFA)"})]),t("p",M,[t("small",P,[i(o,{t:"1. Please scan the following QR Code to generate TOTP with your choice of authenticator"})])]),e[1]||(e[1]=t("canvas",{id:"qrcode",class:"rounded-3 mb-2"},null,-1)),t("div",I,[t("p",O,[t("small",null,[i(o,{t:"Or you can click the link below:"})])]),t("a",{href:this.l},[t("code",$,p(this.l),1)],8,B)]),t("label",D,[t("small",R,[i(o,{t:"2. Enter the TOTP generated by your authenticator to verify"})])]),t("div",S,[f(t("input",{class:"form-control text-center totp",id:"totp",maxlength:"6",type:"text",inputmode:"numeric",autocomplete:"one-time-code","onUpdate:modelValue":e[0]||(e[0]=u=>this.totp=u),disabled:this.verified},null,8,q),[[_,this.totp]]),t("div",A,[i(o,{t:this.totpInvalidMessage},null,8,["t"])]),t("div",E,[i(o,{t:"TOTP verified!"})])])]),e[4]||(e[4]=t("hr",null,null,-1)),t("div",F,[this.verified?(n(),r(l,{key:1,to:"/",class:"btn btn-dark btn-lg d-flex btn-brand shadow align-items-center flex-grow-1 rounded-3"},{default:c(()=>[i(o,{t:"Complete"}),e[3]||(e[3]=t("i",{class:"bi bi-chevron-right ms-auto"},null,-1))]),_:1})):(n(),r(l,{key:0,to:"/",class:"btn bg-secondary-subtle text-secondary-emphasis rounded-3 flex-grow-1 btn-lg border-1 border-secondary-subtle shadow d-flex"},{default:c(()=>[i(o,{t:"I don't need MFA"}),e[2]||(e[2]=t("i",{class:"bi bi-chevron-right ms-auto"},null,-1))]),_:1}))])])])],8,k)}const H=h(T,[["render",Q]]);export{H as default};
|
import{_ as h,c as m,a as n,b as t,d as i,h as d,t as p,m as f,y as _,j as r,w as c,z as b,D as v,g}from"./index-BuOf6BZp.js";import{Q as x}from"./browser-CdT-qU-v.js";import{L as y}from"./localeText-CzYZfO0n.js";import"./galois-field-I2lBzzs-.js";const T={name:"totp",components:{LocaleText:y},async setup(){const s=v();let e="";return await g("/api/Welcome_GetTotpLink",{},(a=>{a.status&&(e=a.data)})),{l:e,store:s}},mounted(){this.l&&x.toCanvas(document.getElementById("qrcode"),this.l,function(s){})},data(){return{totp:"",totpInvalidMessage:"",verified:!1}},methods:{validateTotp(){}},watch:{totp(s){const e=document.querySelector("#totp");e.classList.remove("is-invalid","is-valid"),s.length===6&&(console.log(s),/[0-9]{6}/.test(s)?b("/api/Welcome_VerifyTotpLink",{totp:s},a=>{a.status?(this.verified=!0,e.classList.add("is-valid"),this.$emit("verified")):(e.classList.add("is-invalid"),this.totpInvalidMessage="TOTP does not match.")}):(e.classList.add("is-invalid"),this.totpInvalidMessage="TOTP can only contain numbers"))}}},k=["data-bs-theme"],L={class:"m-auto text-body",style:{width:"500px"}},w={class:"d-flex flex-column"},C={class:"dashboardLogo display-4"},M={class:"mb-2"},P={class:"text-muted"},I={class:"p-3 bg-body-secondary rounded-3 border mb-3"},O={class:"text-muted mb-0"},B=["href"],$={style:{"line-break":"anywhere"}},D={for:"totp",class:"mb-2"},R={class:"text-muted"},S={class:"form-group mb-2"},q=["disabled"],A={class:"invalid-feedback"},E={class:"valid-feedback"},F={class:"d-flex gap-3 mt-5 flex-column"};function Q(s,e,a,G,N,W){const o=d("LocaleText"),l=d("RouterLink");return n(),m("div",{class:"container-fluid login-container-fluid d-flex main pt-5 overflow-scroll","data-bs-theme":this.store.Configuration.Server.dashboard_theme},[t("div",L,[t("div",w,[t("div",null,[t("h1",C,[i(o,{t:"Multi-Factor Authentication (MFA)"})]),t("p",M,[t("small",P,[i(o,{t:"1. Please scan the following QR Code to generate TOTP with your choice of authenticator"})])]),e[1]||(e[1]=t("canvas",{id:"qrcode",class:"rounded-3 mb-2"},null,-1)),t("div",I,[t("p",O,[t("small",null,[i(o,{t:"Or you can click the link below:"})])]),t("a",{href:this.l},[t("code",$,p(this.l),1)],8,B)]),t("label",D,[t("small",R,[i(o,{t:"2. Enter the TOTP generated by your authenticator to verify"})])]),t("div",S,[f(t("input",{class:"form-control text-center totp",id:"totp",maxlength:"6",type:"text",inputmode:"numeric",autocomplete:"one-time-code","onUpdate:modelValue":e[0]||(e[0]=u=>this.totp=u),disabled:this.verified},null,8,q),[[_,this.totp]]),t("div",A,[i(o,{t:this.totpInvalidMessage},null,8,["t"])]),t("div",E,[i(o,{t:"TOTP verified!"})])])]),e[4]||(e[4]=t("hr",null,null,-1)),t("div",F,[this.verified?(n(),r(l,{key:1,to:"/",class:"btn btn-dark btn-lg d-flex btn-brand shadow align-items-center flex-grow-1 rounded-3"},{default:c(()=>[i(o,{t:"Complete"}),e[3]||(e[3]=t("i",{class:"bi bi-chevron-right ms-auto"},null,-1))]),_:1})):(n(),r(l,{key:0,to:"/",class:"btn bg-secondary-subtle text-secondary-emphasis rounded-3 flex-grow-1 btn-lg border-1 border-secondary-subtle shadow d-flex"},{default:c(()=>[i(o,{t:"I don't need MFA"}),e[2]||(e[2]=t("i",{class:"bi bi-chevron-right ms-auto"},null,-1))]),_:1}))])])])],8,k)}const H=h(T,[["render",Q]]);export{H as default};
|
||||||
@@ -1 +1 @@
|
|||||||
import{_ as h,c as o,a as l,b as t,d as n,h as r,m as g,y as b,E as y,w as c,k as u,g as f,W as x,f as v,F as m,i as _,s as k,n as T,t as i}from"./index-BQYwwrw6.js";import{O as A}from"./osmap-CCHzjkwj.js";import{L as w}from"./localeText-C3GiyveB.js";import"./Vector-zgNB5xDX.js";const R={name:"traceroute",components:{LocaleText:w,OSMap:A},data(){return{tracing:!1,ipAddress:void 0,tracerouteResult:void 0}},setup(){return{store:x()}},methods:{execute(){this.ipAddress&&(this.tracing=!0,this.tracerouteResult=void 0,f("/api/traceroute/execute",{ipAddress:this.ipAddress},d=>{d.status?this.tracerouteResult=d.data:this.store.newMessage("Server",d.message,"danger"),this.tracing=!1}))}}},M={class:"mt-md-5 mt-3 text-body"},S={class:"container-md"},$={class:"mb-3 text-body"},L={class:"d-flex gap-2 mb-3 flex-column"},C={class:"flex-grow-1"},P={class:"mb-1 text-muted",for:"ipAddress"},O=["disabled"],V=["disabled"],B={key:0,class:"d-block"},E={key:1,class:"d-block"},I={class:"position-relative"},N={key:"pingPlaceholder"},z={key:1},D={key:"table",class:"w-100 mt-2"},F={class:"table table-sm rounded-3 w-100"},G={scope:"col"},H={scope:"col"},K={scope:"col"},W={scope:"col"},U={scope:"col"},j={scope:"col"},q={key:0},J={key:1};function Q(d,s,X,Y,Z,tt){const a=r("LocaleText"),p=r("OSMap");return l(),o("div",M,[t("div",S,[t("h3",$,[n(a,{t:"Traceroute"})]),t("div",L,[t("div",C,[t("label",P,[t("small",null,[n(a,{t:"Enter IP Address / Hostname"})])]),g(t("input",{disabled:this.tracing,id:"ipAddress",class:"form-control rounded-3","onUpdate:modelValue":s[0]||(s[0]=e=>this.ipAddress=e),onKeyup:s[1]||(s[1]=y(e=>this.execute(),["enter"])),type:"text"},null,40,O),[[b,this.ipAddress]])]),t("button",{class:"btn btn-primary rounded-3 position-relative flex-grow-1",disabled:this.tracing||!this.ipAddress,onClick:s[2]||(s[2]=e=>this.execute())},[n(u,{name:"slide"},{default:c(()=>[this.tracing?(l(),o("span",E,[...s[4]||(s[4]=[t("span",{class:"spinner-border spinner-border-sm","aria-hidden":"true"},null,-1),t("span",{class:"visually-hidden",role:"status"},"Loading...",-1)])])):(l(),o("span",B,[...s[3]||(s[3]=[t("i",{class:"bi bi-person-walking me-2"},null,-1),v("Trace! ",-1)])]))]),_:1})],8,V)]),t("div",I,[n(u,{name:"ping"},{default:c(()=>[this.tracerouteResult?(l(),o("div",z,[n(p,{d:this.tracerouteResult,type:"traceroute"},null,8,["d"]),t("div",D,[t("table",F,[t("thead",null,[t("tr",null,[t("th",G,[n(a,{t:"Hop"})]),t("th",H,[n(a,{t:"IP Address"})]),t("th",K,[n(a,{t:"Average RTT (ms)"})]),t("th",W,[n(a,{t:"Min RTT (ms)"})]),t("th",U,[n(a,{t:"Max RTT (ms)"})]),t("th",j,[n(a,{t:"Geolocation"})])])]),t("tbody",null,[(l(!0),o(m,null,_(this.tracerouteResult,(e,et)=>(l(),o("tr",null,[t("td",null,[t("small",null,i(e.hop),1)]),t("td",null,[t("small",null,[t("samp",null,i(e.ip),1)])]),t("td",null,[t("small",null,[t("samp",null,i(e.avg_rtt),1)])]),t("td",null,[t("small",null,[t("samp",null,i(e.min_rtt),1)])]),t("td",null,[t("small",null,[t("samp",null,i(e.max_rtt),1)])]),t("td",null,[e.geo&&e.geo.city&&e.geo.country?(l(),o("span",q,[t("small",null,i(e.geo.city)+", "+i(e.geo.country),1)])):(l(),o("span",J," - "))])]))),256))])])])])):(l(),o("div",N,[s[5]||(s[5]=t("div",{class:"pingPlaceholder bg-body-secondary rounded-3 mb-3",style:{height:"300px !important"}},null,-1)),(l(),o(m,null,_(5,e=>t("div",{class:T(["pingPlaceholder bg-body-secondary rounded-3 mb-3",{"animate__animated animate__flash animate__slower animate__infinite":this.tracing}]),style:k({"animation-delay":`${e*.05}s`})},null,6)),64))]))]),_:1})])])])}const at=h(R,[["render",Q],["__scopeId","data-v-125b538b"]]);export{at as default};
|
import{_ as h,c as o,a as l,b as t,d as n,h as r,m as g,y as b,H as y,w as c,k as u,g as f,W as x,f as v,F as m,i as _,s as k,n as T,t as i}from"./index-BuOf6BZp.js";import{O as A}from"./osmap-CcOlLXy3.js";import{L as w}from"./localeText-CzYZfO0n.js";import"./Vector-zgNB5xDX.js";const R={name:"traceroute",components:{LocaleText:w,OSMap:A},data(){return{tracing:!1,ipAddress:void 0,tracerouteResult:void 0}},setup(){return{store:x()}},methods:{execute(){this.ipAddress&&(this.tracing=!0,this.tracerouteResult=void 0,f("/api/traceroute/execute",{ipAddress:this.ipAddress},d=>{d.status?this.tracerouteResult=d.data:this.store.newMessage("Server",d.message,"danger"),this.tracing=!1}))}}},M={class:"mt-md-5 mt-3 text-body"},S={class:"container-md"},$={class:"mb-3 text-body"},L={class:"d-flex gap-2 mb-3 flex-column"},C={class:"flex-grow-1"},P={class:"mb-1 text-muted",for:"ipAddress"},O=["disabled"],V=["disabled"],B={key:0,class:"d-block"},H={key:1,class:"d-block"},I={class:"position-relative"},N={key:"pingPlaceholder"},z={key:1},D={key:"table",class:"w-100 mt-2"},E={class:"table table-sm rounded-3 w-100"},F={scope:"col"},G={scope:"col"},K={scope:"col"},W={scope:"col"},U={scope:"col"},j={scope:"col"},q={key:0},J={key:1};function Q(d,s,X,Y,Z,tt){const a=r("LocaleText"),p=r("OSMap");return l(),o("div",M,[t("div",S,[t("h3",$,[n(a,{t:"Traceroute"})]),t("div",L,[t("div",C,[t("label",P,[t("small",null,[n(a,{t:"Enter IP Address / Hostname"})])]),g(t("input",{disabled:this.tracing,id:"ipAddress",class:"form-control rounded-3","onUpdate:modelValue":s[0]||(s[0]=e=>this.ipAddress=e),onKeyup:s[1]||(s[1]=y(e=>this.execute(),["enter"])),type:"text"},null,40,O),[[b,this.ipAddress]])]),t("button",{class:"btn btn-primary rounded-3 position-relative flex-grow-1",disabled:this.tracing||!this.ipAddress,onClick:s[2]||(s[2]=e=>this.execute())},[n(u,{name:"slide"},{default:c(()=>[this.tracing?(l(),o("span",H,[...s[4]||(s[4]=[t("span",{class:"spinner-border spinner-border-sm","aria-hidden":"true"},null,-1),t("span",{class:"visually-hidden",role:"status"},"Loading...",-1)])])):(l(),o("span",B,[...s[3]||(s[3]=[t("i",{class:"bi bi-person-walking me-2"},null,-1),v("Trace! ",-1)])]))]),_:1})],8,V)]),t("div",I,[n(u,{name:"ping"},{default:c(()=>[this.tracerouteResult?(l(),o("div",z,[n(p,{d:this.tracerouteResult,type:"traceroute"},null,8,["d"]),t("div",D,[t("table",E,[t("thead",null,[t("tr",null,[t("th",F,[n(a,{t:"Hop"})]),t("th",G,[n(a,{t:"IP Address"})]),t("th",K,[n(a,{t:"Average RTT (ms)"})]),t("th",W,[n(a,{t:"Min RTT (ms)"})]),t("th",U,[n(a,{t:"Max RTT (ms)"})]),t("th",j,[n(a,{t:"Geolocation"})])])]),t("tbody",null,[(l(!0),o(m,null,_(this.tracerouteResult,(e,et)=>(l(),o("tr",null,[t("td",null,[t("small",null,i(e.hop),1)]),t("td",null,[t("small",null,[t("samp",null,i(e.ip),1)])]),t("td",null,[t("small",null,[t("samp",null,i(e.avg_rtt),1)])]),t("td",null,[t("small",null,[t("samp",null,i(e.min_rtt),1)])]),t("td",null,[t("small",null,[t("samp",null,i(e.max_rtt),1)])]),t("td",null,[e.geo&&e.geo.city&&e.geo.country?(l(),o("span",q,[t("small",null,i(e.geo.city)+", "+i(e.geo.country),1)])):(l(),o("span",J," - "))])]))),256))])])])])):(l(),o("div",N,[s[5]||(s[5]=t("div",{class:"pingPlaceholder bg-body-secondary rounded-3 mb-3",style:{height:"300px !important"}},null,-1)),(l(),o(m,null,_(5,e=>t("div",{class:T(["pingPlaceholder bg-body-secondary rounded-3 mb-3",{"animate__animated animate__flash animate__slower animate__infinite":this.tracing}]),style:k({"animation-delay":`${e*.05}s`})},null,6)),64))]))]),_:1})])])])}const at=h(R,[["render",Q],["__scopeId","data-v-125b538b"]]);export{at as default};
|
||||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
import{B as n,D as r,c as i,a as e,b as s,d as t,j as l,e as c,u}from"./index-BQYwwrw6.js";import{L as o}from"./localeText-C3GiyveB.js";import{D as _,d as m,e as h,A as p,a as b,b as v,_ as g,c as f}from"./dashboardEmailSettings-p_Bw0Z58.js";import"./dayjs.min-CzHDLgWx.js";import"./vue-datepicker-g3vsoQR2.js";const A={class:"d-flex gap-3 flex-column"},D={class:"card rounded-3"},y={class:"card-header"},S={class:"my-2"},x={class:"card-body"},I={class:"row g-2"},P={class:"col-sm"},B={class:"col-sm"},C={class:"card rounded-3"},k={class:"card-header"},w={class:"my-2"},L={class:"card-body"},F={class:"card rounded-3"},M={class:"card-header"},N={class:"my-2"},V={class:"card-body d-flex flex-column gap-3"},z=n({__name:"wgdashboardSettings",setup(T){const d=r();return(U,a)=>(e(),i("div",A,[s("div",D,[s("div",y,[s("h6",S,[a[0]||(a[0]=s("i",{class:"bi bi-magic me-2"},null,-1)),t(o,{t:"Appearance"})])]),s("div",x,[s("div",I,[s("div",P,[t(_)]),s("div",B,[t(m)])])])]),s("div",C,[s("div",k,[s("h6",w,[a[1]||(a[1]=s("i",{class:"bi bi-ethernet me-2"},null,-1)),t(o,{t:"Dashboard IP Address & Listen Port"})])]),s("div",L,[t(h)])]),s("div",F,[s("div",M,[s("h6",N,[a[2]||(a[2]=s("i",{class:"bi bi-people-fill me-2"},null,-1)),t(o,{t:"Account Settings"})])]),s("div",V,[s("div",null,[t(p,{targetData:"username",title:"Username"})]),a[3]||(a[3]=s("hr",null,null,-1)),s("div",null,[t(b,{targetData:"password"})]),a[4]||(a[4]=s("hr",null,null,-1)),s("div",null,[s("h6",null,[t(o,{t:"Multi-Factor Authentication (MFA)"})]),u(d).getActiveCrossServer()?c("",!0):(e(),l(f,{key:0}))])])]),t(v),t(g)]))}});export{z as default};
|
import{B as n,D as r,c as i,a as e,b as s,d as t,j as l,e as c,u}from"./index-BuOf6BZp.js";import{L as o}from"./localeText-CzYZfO0n.js";import{D as _,d as m,e as h,A as p,a as b,b as v,_ as g,c as f}from"./dashboardEmailSettings-CPNkx_Qa.js";import"./dayjs.min-BzBvZaAI.js";import"./vue-datepicker-B81xP9h3.js";const A={class:"d-flex gap-3 flex-column"},D={class:"card rounded-3"},y={class:"card-header"},S={class:"my-2"},x={class:"card-body"},I={class:"row g-2"},P={class:"col-sm"},B={class:"col-sm"},C={class:"card rounded-3"},k={class:"card-header"},w={class:"my-2"},L={class:"card-body"},F={class:"card rounded-3"},M={class:"card-header"},N={class:"my-2"},V={class:"card-body d-flex flex-column gap-3"},z=n({__name:"wgdashboardSettings",setup(T){const d=r();return(U,a)=>(e(),i("div",A,[s("div",D,[s("div",y,[s("h6",S,[a[0]||(a[0]=s("i",{class:"bi bi-magic me-2"},null,-1)),t(o,{t:"Appearance"})])]),s("div",x,[s("div",I,[s("div",P,[t(_)]),s("div",B,[t(m)])])])]),s("div",C,[s("div",k,[s("h6",w,[a[1]||(a[1]=s("i",{class:"bi bi-ethernet me-2"},null,-1)),t(o,{t:"Dashboard IP Address & Listen Port"})])]),s("div",L,[t(h)])]),s("div",F,[s("div",M,[s("h6",N,[a[2]||(a[2]=s("i",{class:"bi bi-people-fill me-2"},null,-1)),t(o,{t:"Account Settings"})])]),s("div",V,[s("div",null,[t(p,{targetData:"username",title:"Username"})]),a[3]||(a[3]=s("hr",null,null,-1)),s("div",null,[t(b,{targetData:"password"})]),a[4]||(a[4]=s("hr",null,null,-1)),s("div",null,[s("h6",null,[t(o,{t:"Multi-Factor Authentication (MFA)"})]),u(d).getActiveCrossServer()?c("",!0):(e(),l(f,{key:0}))])])]),t(v),t(g)]))}});export{z as default};
|
||||||
@@ -1 +0,0 @@
|
|||||||
import{D as e,a}from"./dashboardSettingsWireguardConfigurationAutostart-cyw0vUzN.js";import{B as r,c as o,a as n,d as t}from"./index-BQYwwrw6.js";import"./localeText-C3GiyveB.js";const i={class:"d-flex gap-3 flex-column"},m=r({__name:"wireguardConfigurationSettings",setup(s){return(g,u)=>(n(),o("div",i,[t(e,{targetData:"wg_conf_path",title:"Configurations Directory",warning:!0,"warning-text":"Remember to remove / at the end of your path. e.g /etc/wireguard"}),t(a)]))}});export{m as default};
|
|
||||||
1
src/static/dist/WGDashboardAdmin/assets/wireguardConfigurationSettings-FAn5QwY0.js
vendored
Normal file
1
src/static/dist/WGDashboardAdmin/assets/wireguardConfigurationSettings-FAn5QwY0.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
src/static/dist/WGDashboardAdmin/index.html
vendored
2
src/static/dist/WGDashboardAdmin/index.html
vendored
@@ -10,7 +10,7 @@
|
|||||||
<link rel="icon" href="/static/dist/WGDashboardAdmin/img/Logo-2-512x512.png">
|
<link rel="icon" href="/static/dist/WGDashboardAdmin/img/Logo-2-512x512.png">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>WGDashboard</title>
|
<title>WGDashboard</title>
|
||||||
<script type="module" crossorigin src="/static/dist/WGDashboardAdmin/assets/index-BQYwwrw6.js"></script>
|
<script type="module" crossorigin src="/static/dist/WGDashboardAdmin/assets/index-BuOf6BZp.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/static/dist/WGDashboardAdmin/assets/index-DQmUtZqH.css">
|
<link rel="stylesheet" crossorigin href="/static/dist/WGDashboardAdmin/assets/index-DQmUtZqH.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
41
src/wgd.sh
41
src/wgd.sh
@@ -464,47 +464,6 @@ stop_wgd() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# ============= Docker Functions =============
|
|
||||||
startwgd_docker() {
|
|
||||||
_checkWireguard
|
|
||||||
printf "[WGDashboard][Docker] WireGuard configuration started\n"
|
|
||||||
{ date; start_core ; printf "\n\n"; } >> ./log/install.txt
|
|
||||||
gunicorn_start
|
|
||||||
}
|
|
||||||
|
|
||||||
start_core() {
|
|
||||||
# Re-assign config_files to ensure it includes any newly created configurations
|
|
||||||
local config_files=$(find /etc/wireguard -type f -name "*.conf")
|
|
||||||
|
|
||||||
# Set file permissions
|
|
||||||
find /etc/wireguard -type f -name "*.conf" -exec chmod 600 {} \;
|
|
||||||
find "$iptable_dir" -type f -name "*.sh" -exec chmod +x {} \;
|
|
||||||
|
|
||||||
# Start WireGuard for each config file
|
|
||||||
for file in $config_files; do
|
|
||||||
config_name=$(basename "$file" ".conf")
|
|
||||||
wg-quick up "$config_name"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
newconf_wgd() {
|
|
||||||
local wg_port_listen=$wg_port
|
|
||||||
local wg_addr_range=$wg_net
|
|
||||||
private_key=$(wg genkey)
|
|
||||||
public_key=$(echo "$private_key" | wg pubkey)
|
|
||||||
cat <<EOF >"/etc/wireguard/wg0.conf"
|
|
||||||
[Interface]
|
|
||||||
PrivateKey = $private_key
|
|
||||||
Address = $wg_addr_range
|
|
||||||
ListenPort = $wg_port_listen
|
|
||||||
SaveConfig = true
|
|
||||||
PostUp = /opt/wireguarddashboard/src/iptable-rules/postup.sh
|
|
||||||
PreDown = /opt/wireguarddashboard/src/iptable-rules/postdown.sh
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
# ============= Docker Functions =============
|
|
||||||
|
|
||||||
start_wgd_debug() {
|
start_wgd_debug() {
|
||||||
_checkWireguard
|
_checkWireguard
|
||||||
printf "[WGDashboard] Starting WGDashboard in the foreground.\n"
|
printf "[WGDashboard] Starting WGDashboard in the foreground.\n"
|
||||||
|
|||||||
59
templates/wg-dashboard.ini.template
Normal file
59
templates/wg-dashboard.ini.template
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
[Peers]
|
||||||
|
remote_endpoint = <your-public-ip>
|
||||||
|
peer_global_dns = <your-chosen-dns>
|
||||||
|
peer_endpoint_allowed_ip = 0.0.0.0/0
|
||||||
|
peer_display_mode = grid
|
||||||
|
peer_mtu = 1420
|
||||||
|
peer_keep_alive = 21
|
||||||
|
|
||||||
|
[Server]
|
||||||
|
app_port = 10086
|
||||||
|
wg_conf_path = /etc/wireguard
|
||||||
|
awg_conf_path = /etc/amnezia/amneziawg
|
||||||
|
app_prefix =
|
||||||
|
app_ip = 0.0.0.0
|
||||||
|
auth_req = true
|
||||||
|
version = v4.3.0.1
|
||||||
|
dashboard_refresh_interval = 60000
|
||||||
|
dashboard_peer_list_display = grid
|
||||||
|
dashboard_sort = status
|
||||||
|
dashboard_theme = dark
|
||||||
|
dashboard_api_key = false
|
||||||
|
dashboard_language = en-US
|
||||||
|
|
||||||
|
[Account]
|
||||||
|
username = admin
|
||||||
|
password = $2b$12$nWgPW.4adylN2oMhTyS5AeoiAvDj9SZxnXS.lCMkJYCV6jytmHKzu
|
||||||
|
enable_totp = false
|
||||||
|
totp_verified = false
|
||||||
|
totp_key = UOXAUPDDUNFTTHXZNQI4J4BWCEJZ63HF
|
||||||
|
|
||||||
|
[Other]
|
||||||
|
welcome_session = true
|
||||||
|
|
||||||
|
[Database]
|
||||||
|
type = sqlite
|
||||||
|
host =
|
||||||
|
port =
|
||||||
|
username =
|
||||||
|
password =
|
||||||
|
|
||||||
|
[Email]
|
||||||
|
server =
|
||||||
|
port =
|
||||||
|
encryption =
|
||||||
|
username =
|
||||||
|
email_password =
|
||||||
|
authentication_required = true
|
||||||
|
send_from =
|
||||||
|
email_template =
|
||||||
|
|
||||||
|
[OIDC]
|
||||||
|
admin_enable = false
|
||||||
|
client_enable = false
|
||||||
|
|
||||||
|
[Clients]
|
||||||
|
enable = true
|
||||||
|
|
||||||
|
[WireGuardConfiguration]
|
||||||
|
autostart =
|
||||||
Reference in New Issue
Block a user