mirror of
https://github.com/WGDashboard/WGDashboard.git
synced 2026-08-04 06:53:00 +00:00
Compare commits
163 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ae160aef23 | |||
| 85d1cc8be4 | |||
| 8cff8d85f6 | |||
| d7a1007f41 | |||
| 0cd2c6864e | |||
| 0cb46e1444 | |||
| cb9dfa1321 | |||
| 43fd2fff2b | |||
| b37c64f5a5 | |||
| f1aa064b2d | |||
| 8abadd1070 | |||
| 3f9d9732a0 | |||
| b9dc3c44a8 | |||
| 1483ef83d9 | |||
| dbed799e20 | |||
| 4602b68425 | |||
| 2d3eaedaa7 | |||
| 4d60b21a5f | |||
| 50ee8374ee | |||
| 65eb23e8ce | |||
| 5c76b18ddd | |||
| fc6f5d2535 | |||
| 6a0348e9dc | |||
| 90e6409b1e | |||
| 96b28a8e9b | |||
| a818e87e96 | |||
| dc715758a6 | |||
| 87069329d8 | |||
| 8a380a4545 | |||
| a5e18cb761 | |||
| e9da3e7b6a | |||
| 289fa23728 | |||
| c117ee61d5 | |||
| 7385932e52 | |||
| cb90b69b3f | |||
| 8d0e31872a | |||
| 881925fd43 | |||
| 3a2f744f0a | |||
| 9dc9e668c5 | |||
| 39477c8de8 | |||
| 1b0bb95e81 | |||
| cd5a4bec52 | |||
| 43070ab809 | |||
| 532fedbb62 | |||
| 585bf37783 | |||
| cad364e407 | |||
| 45457c5b38 | |||
| 4e9142b5be | |||
| 207b365d40 | |||
| 1ec95a0d86 | |||
| db4b9ccc7a | |||
| a86d0c74d3 | |||
| 354f4e47df | |||
| 84167650b8 | |||
| 15c12a81f1 | |||
| 249ae584c3 | |||
| b04f7b2d2c | |||
| 630ce459cb | |||
| a7a30fb282 | |||
| ab5abe9bcf | |||
| 7834fff541 | |||
| ef8849e8a9 | |||
| 78bedf9ad6 | |||
| 6ec757ab66 | |||
| 7d71299c51 | |||
| bea37aee7f | |||
| 5323687ea5 | |||
| d1372a4c43 | |||
| c9249a164a | |||
| 6f105f2626 | |||
| e4c08896f4 | |||
| e85a0df9b7 | |||
| a5b7eabd97 | |||
| f3688431a3 | |||
| 44e714352d | |||
| 60da68c994 | |||
| 11288fac20 | |||
| fe9d373444 | |||
| cce31f9b0b | |||
| ca779ed5ad | |||
| eb0eaaae2e | |||
| 9631b97694 | |||
| 6f036876c8 | |||
| bd47179ea4 | |||
| 418c6bd88b | |||
| ada4c4f816 | |||
| 91b499fb14 | |||
| 1f73adffd6 | |||
| 82bd313e7a | |||
| 14cbfe47b9 | |||
| f2d4ff6dc4 | |||
| bf33a70727 | |||
| e1bdcbd581 | |||
| 051c1e7622 | |||
| 3b176474ff | |||
| 15f1b33ea6 | |||
| 0603d4076a | |||
| ac94f10dc3 | |||
| bbb92490e9 | |||
| 2cb63092c0 | |||
| b9bcb59592 | |||
| e083adc022 | |||
| c3cd38fe9f | |||
| a7c2db5e99 | |||
| 4926ee5117 | |||
| e7723ac3db | |||
| 8dbfb93e4e | |||
| 6096366756 | |||
| 8e4cf12512 | |||
| b61fa1f870 | |||
| ac3cf9e4b1 | |||
| e18463f059 | |||
| ee54e08d18 | |||
| 3c07df6496 | |||
| 2117b828c8 | |||
| 28d9694432 | |||
| 7d977700e6 | |||
| 33942945d0 | |||
| 8d7d78db46 | |||
| 3268cc30ea | |||
| 8830ebe34f | |||
| 1d9adba6dd | |||
| 71be73777e | |||
| 7709f70ef1 | |||
| 9b528b84e1 | |||
| c53a4d4861 | |||
| 766173df3d | |||
| 7f65cae891 | |||
| bc56ecb85c | |||
| 50c3151301 | |||
| d49ec0a81e | |||
| 6692028762 | |||
| b71c357958 | |||
| 03b7621f3e | |||
| 2bcf24bd84 | |||
| cc5aa05b12 | |||
| 3232c5c4ce | |||
| 72a52f5cd6 | |||
| bda48a56e0 | |||
| 09cdcf8e53 | |||
| a4d5b41ca7 | |||
| 9fa0d91d06 | |||
| 510f60bdeb | |||
| 30fe827253 | |||
| 8f0f4b168b | |||
| cd11c4beb6 | |||
| 4d49cc413a | |||
| 3d50a58a31 | |||
| d5701230fa | |||
| ab945d6afe | |||
| b4f8a36d43 | |||
| 608c1b4eb6 | |||
| edf3c42157 | |||
| c523cec113 | |||
| 6f8b987d42 | |||
| d0d0642bdf | |||
| 924d760e3b | |||
| f8c207ca2b | |||
| ada1edd0b7 | |||
| c79333db61 | |||
| 13778bed87 | |||
| 83b4d96f42 | |||
| 6cf96de0b4 |
@@ -12,6 +12,7 @@
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
name: Docker Scan and Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
schedule:
|
||||
- cron: "0 0 * * *" # Daily at midnight UTC
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
trigger-build:
|
||||
description: 'Trigger a manual build and push'
|
||||
default: 'true'
|
||||
|
||||
env:
|
||||
DOCKER_IMAGE: donaldzou/wgdashboard
|
||||
|
||||
jobs:
|
||||
docker_build_analyze:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
with:
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v6,linux/arm/v7
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Build and export (multi-arch)
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: ${{ env.DOCKER_IMAGE }}:latest
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v6,linux/arm/v7
|
||||
|
||||
- name: Docker Scout
|
||||
id: docker-scout
|
||||
uses: docker/scout-action@v1
|
||||
with:
|
||||
command: cves
|
||||
image: ${{ env.DOCKER_IMAGE }}:latest
|
||||
only-severities: critical,high,medium,low,unspecified
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -0,0 +1,105 @@
|
||||
name: Docker Build and Push
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
tags:
|
||||
- '*'
|
||||
release:
|
||||
types: [ published ]
|
||||
|
||||
env:
|
||||
DOCKERHUB_PREFIX: docker.io
|
||||
GITHUB_CONTAINER_PREFIX: ghcr.io
|
||||
DOCKER_IMAGE: donaldzou/wgdashboard
|
||||
|
||||
jobs:
|
||||
docker_build:
|
||||
runs-on: ubuntu-latest
|
||||
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
|
||||
- linux/arm64
|
||||
- linux/arm/v7
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Docker meta by docs https://github.com/docker/metadata-action
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
${{ env.DOCKERHUB_PREFIX }}/${{ env.DOCKER_IMAGE }}
|
||||
${{ env.GITHUB_CONTAINER_PREFIX }}/${{ env.DOCKER_IMAGE }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
|
||||
- name: Build and export (multi-arch)
|
||||
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,linux/arm64,linux/arm/v7
|
||||
|
||||
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: Docker Scout CVEs
|
||||
uses: docker/scout-action@v1
|
||||
with:
|
||||
command: cves
|
||||
image: ${{ env.GITHUB_CONTAINER_PREFIX }}/${{ 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 }}/${{ env.DOCKER_IMAGE }}:main
|
||||
to: ${{ env.GITHUB_CONTAINER_PREFIX }}/${{ env.DOCKER_IMAGE }}:latest
|
||||
only-severities: critical,high
|
||||
ignore-unchanged: true
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -1,28 +0,0 @@
|
||||
name: Qodana
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
push:
|
||||
branches: # Specify your branches here
|
||||
- main # The 'main' branch
|
||||
- v4.2-dev
|
||||
|
||||
jobs:
|
||||
qodana:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
checks: write
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit
|
||||
fetch-depth: 0 # a full history is required for pull request analysis
|
||||
- name: 'Qodana Scan'
|
||||
uses: JetBrains/qodana-action@v2024.3
|
||||
with:
|
||||
pr-mode: false
|
||||
env:
|
||||
QODANA_TOKEN: ${{ secrets.QODANA_TOKEN_2090978292 }}
|
||||
QODANA_ENDPOINT: 'https://qodana.cloud'
|
||||
@@ -0,0 +1,26 @@
|
||||
# This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time.
|
||||
#
|
||||
# You can adjust the behavior by modifying this file.
|
||||
# For more information, see:
|
||||
# https://github.com/actions/stale
|
||||
name: Mark stale issues and pull requests
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '00 08 * * *'
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
stale-issue-message: 'This issue has not been updated for 20 days'
|
||||
stale-pr-message: 'This pull request has not been updated for 20 days'
|
||||
stale-issue-label: 'stale'
|
||||
exempt-issue-labels: 'enhancement,ongoing'
|
||||
days-before-stale: 20
|
||||
@@ -18,6 +18,7 @@ src/db/wgdashboard.db
|
||||
node_modules/**
|
||||
*/proxy.js
|
||||
src/static/app/proxy.js
|
||||
.secrets
|
||||
|
||||
# Logs
|
||||
logs
|
||||
|
||||
@@ -4,27 +4,28 @@
|
||||
> [!NOTE]
|
||||
> **Help Wanted 🎉**: Localizing WGDashboard to other languages! If you're willing to help, please visit https://github.com/donaldzou/WGDashboard/issues/397. Many thanks!
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
<p align="center">
|
||||
<img alt="WGDashboard" src="https://wgdashboard-resources.tor1.cdn.digitaloceanspaces.com/Logos/Logo-2-Rounded-512x512.png" width="128">
|
||||
</p>
|
||||
<h1 align="center">WGDashboard</h1>
|
||||
<h1 align="center">
|
||||
<a href="https://wgdashboard.dev">WGDashboard</a>
|
||||
</h1>
|
||||
<p align="center">
|
||||
<img src="https://forthebadge.com/images/badges/made-with-python.svg">
|
||||
<img src="https://forthebadge.com/images/badges/made-with-javascript.svg">
|
||||
<img src="https://forthebadge.com/images/badges/license-mit.svg">
|
||||
</p>
|
||||
<p align="center">
|
||||
<img src="https://forthebadge.com/images/badges/built-with-love.svg">
|
||||
<img src="https://img.shields.io/badge/Made_With-Python-blue?style=for-the-badge&logo=python&logoColor=ffffff">
|
||||
<img src="https://img.shields.io/badge/Made_With-Vue.js-42b883?style=for-the-badge&logo=vuedotjs&logoColor=ffffff">
|
||||
<img src="https://img.shields.io/badge/License-Apache_License_2.0-D22128?style=for-the-badge&logo=apache&logoColor=ffffff">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/donaldzou/wireguard-dashboard/releases/latest"><img src="https://img.shields.io/github/v/release/donaldzou/wireguard-dashboard"></a>
|
||||
<a href="https://wakatime.com/badge/github/donaldzou/WGDashboard"><img src="https://wakatime.com/badge/github/donaldzou/WGDashboard.svg" 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"></a>
|
||||
<img src="https://img.shields.io/docker/pulls/donaldzou/wgdashboard?logo=docker&label=Docker%20Image%20Pulls&labelColor=ffffff">
|
||||
<a href="https://github.com/donaldzou/wireguard-dashboard/releases/latest"><img src="https://img.shields.io/github/v/release/donaldzou/wireguard-dashboard?style=for-the-badge"></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>
|
||||
<img src="https://img.shields.io/docker/pulls/donaldzou/wgdashboard?logo=docker&label=Docker%20Image%20Pulls&labelColor=ffffff&style=for-the-badge">
|
||||
</p>
|
||||
<p align="center"><b>This project is supported by</b></p>
|
||||
<p align="center">
|
||||
@@ -37,31 +38,40 @@
|
||||
|
||||
<p align="center"><b><i>This project is not affiliate to the official WireGuard Project</i></b></p>
|
||||
|
||||
|
||||
<h3 align="center">Looking for help or want to chat about this project?</h4>
|
||||
<p align="center">
|
||||
Join our Discord Server for quick help, or you wanna chat about this project!
|
||||
You can reach out at
|
||||
</p>
|
||||
<p align="center">
|
||||
<a align="center" href="https://discord.gg/72TwzjeuWm"><img src="https://img.shields.io/discord/1276818723637956628?labelColor=ffffff&style=for-the-badge&logo=discord&label=Discord"></a>
|
||||
<a align="center" href="https://discord.gg/72TwzjeuWm" target="_blank"><img src="https://img.shields.io/discord/1276818723637956628?labelColor=ffffff&style=for-the-badge&logo=discord&label=Discord"></a>
|
||||
<a align="center" href="https://www.reddit.com/r/WGDashboard/" target="_blank"><img src="https://img.shields.io/badge/Reddit-r%2FWGDashboard-FF4500?style=for-the-badge&logo=reddit"></a>
|
||||
<a align="center" href="https://app.element.io/#/room/#wgd:matrix.org" target="_blank"><img src="https://img.shields.io/badge/Matrix_Chatroom-%23WGD-000000?style=for-the-badge&logo=matrix"></a>
|
||||
</p>
|
||||
<h3 align="center">Want to support this project?</h4>
|
||||
<p align="center">
|
||||
You can support via <br>
|
||||
</p>
|
||||
<p align="center">
|
||||
Alternatively, you can also reach out at our Matrix.org Chatroom :)
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://app.element.io/#/room/#wgd:matrix.org">Matrix.org Chatroom</a>
|
||||
<a align="center" href="https://github.com/sponsors/donaldzou" target="_blank"><img src="https://img.shields.io/badge/GitHub%20Sponsor-2e9a40?style=for-the-badge&logo=github"></a>
|
||||
<a align="center" href="https://buymeacoffee.com/donaldzou" target="_blank"><img src="https://img.shields.io/badge/Buy%20me%20a%20coffee-ffdd00?style=for-the-badge&logo=buymeacoffee&logoColor=000000"></a>
|
||||
<a align="center" href="https://patreon.com/c/DonaldDonnyZou/membership" target="_blank"><img src="https://img.shields.io/badge/Patreon-000000?style=for-the-badge&logo=patreon&logoColor=ffffff"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<b>or, visit our merch store and support us by purchasing a merch for only $USD 17.00 (Including shipping worldwide & duties)</b>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a align="center" href="https://merch.wgdashboard.dev" target="_blank"><img src="https://img.shields.io/badge/Merch%20from%20WGDashboard-926183?style=for-the-badge"></a>
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<h4 align="center">
|
||||
for more information, visit our
|
||||
</h4>
|
||||
<h1 align="center">
|
||||
<a href="https://wgdashboard.dev">Official Website</a>
|
||||
</h1>
|
||||
|
||||
# [Official Documentation](https://donaldzou.dev/WGDashboard-Documentations)
|
||||
|
||||
- [💡 Features](https://donaldzou.github.io/WGDashboard-Documentation/features.html)
|
||||
- [📝 Requirements](https://donaldzou.github.io/WGDashboard-Documentation/requirements.html)
|
||||
- [🛠 Install](https://donaldzou.github.io/WGDashboard-Documentation/install.html)
|
||||
- [🪜 Usage](https://donaldzou.github.io/WGDashboard-Documentation/usage.html)
|
||||
- [📖 API Documentation](https://donaldzou.github.io/WGDashboard-Documentation/api-documentation.html)
|
||||
- [And much more...](https://donaldzou.github.io/WGDashboard-Documentation/)
|
||||
|
||||
# Screenshots
|
||||
|
||||
@@ -74,4 +84,4 @@
|
||||
<img src="https://wgdashboard-resources.tor1.cdn.digitaloceanspaces.com/Documentation%20Images/configuration.png" alt=""/>
|
||||
<img src="https://wgdashboard-resources.tor1.cdn.digitaloceanspaces.com/Documentation%20Images/add-peers.png" alt="" />
|
||||
<img src="https://wgdashboard-resources.tor1.cdn.digitaloceanspaces.com/Documentation%20Images/ping.png" alt=""/>
|
||||
<img src="https://wgdashboard-resources.tor1.cdn.digitaloceanspaces.com/Documentation%20Images/traceroute.png" alt=""/>
|
||||
<img src="https://wgdashboard-resources.tor1.cdn.digitaloceanspaces.com/Documentation%20Images/traceroute.png" alt=""/>
|
||||
|
||||
@@ -1,58 +1,44 @@
|
||||
FROM golang:1.23 AS compiler
|
||||
WORKDIR /go
|
||||
FROM golang:1.24 AS awg-go
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
git make bash build-essential \
|
||||
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
RUN git clone https://github.com/WGDashboard/amneziawg-go /awg
|
||||
WORKDIR /awg
|
||||
RUN go mod download && \
|
||||
go mod verify && \
|
||||
go build -ldflags '-linkmode external -extldflags "-fno-PIC -static"' -v -o /usr/bin
|
||||
|
||||
RUN git clone --depth=1 https://github.com/amnezia-vpn/amneziawg-tools.git && \
|
||||
git clone --depth=1 https://github.com/amnezia-vpn/amneziawg-go.git
|
||||
RUN cd /go/amneziawg-tools/src && make
|
||||
FROM alpine:latest AS awg-tools
|
||||
|
||||
RUN cd /go/amneziawg-go && \
|
||||
go get -u ./... && \
|
||||
go mod tidy && \
|
||||
make && \
|
||||
chmod +x /go/amneziawg-go/amneziawg-go /go/amneziawg-tools/src/wg /go/amneziawg-tools/src/wg-quick/linux.bash
|
||||
RUN echo "DONE AmneziaWG"
|
||||
RUN apk update && apk add --no-cache \
|
||||
make git build-base linux-headers \
|
||||
&& git clone https://github.com/WGDashboard/amneziawg-tools \
|
||||
&& cd amneziawg-tools/src \
|
||||
&& make \
|
||||
&& chmod +x wg*
|
||||
|
||||
### INTERMEDIATE STAGE
|
||||
FROM scratch AS bins
|
||||
COPY --from=compiler /go/amneziawg-go/amneziawg-go /amneziawg-go
|
||||
COPY --from=compiler /go/amneziawg-tools/src/wg /awg
|
||||
COPY --from=compiler /go/amneziawg-tools/src/wg-quick/linux.bash /awg-quick
|
||||
|
||||
# FINAL STAGE
|
||||
FROM alpine:latest
|
||||
LABEL maintainer="dselen@nerthus.nl"
|
||||
|
||||
COPY --from=bins /amneziawg-go /usr/bin/amneziawg-go
|
||||
COPY --from=bins /awg /usr/bin/awg
|
||||
COPY --from=bins /awg-quick /usr/bin/awg-quick
|
||||
RUN apk update && apk add --no-cache \
|
||||
iproute2 iptables bash curl wget unzip procps sudo \
|
||||
tzdata wireguard-tools python3 py3-psutil py3-bcrypt openresolv
|
||||
|
||||
COPY --from=awg-go /usr/bin/amneziawg-go /usr/bin/amneziawg-go
|
||||
COPY --from=awg-tools /amneziawg-tools/src/wg /usr/bin/awg
|
||||
COPY --from=awg-tools /amneziawg-tools/src/wg-quick/linux.bash /usr/bin/awg-quick
|
||||
|
||||
# Declaring environment variables, change Peernet to an address you like, standard is a 24 bit subnet.
|
||||
ARG wg_net="10.0.0.1"
|
||||
ARG wg_port="51820"
|
||||
ARG wg_net="10.0.0.1" \
|
||||
wg_port="51820"
|
||||
|
||||
# Following ENV variables are changable on container runtime because /entrypoint.sh handles that. See compose.yaml for more info.
|
||||
ENV TZ="Europe/Amsterdam"
|
||||
ENV global_dns="1.1.1.1"
|
||||
ENV isolate="none"
|
||||
ENV public_ip=""
|
||||
ENV wgd_port="10086"
|
||||
|
||||
# Doing package management operations, such as upgrading
|
||||
RUN apk update \
|
||||
&& apk add --no-cache bash git tzdata \
|
||||
iptables ip6tables openrc curl wireguard-tools \
|
||||
sudo py3-psutil py3-bcrypt \
|
||||
&& apk upgrade
|
||||
ENV TZ="Europe/Amsterdam" \
|
||||
global_dns="9.9.9.9" \
|
||||
wgd_port="10086" \
|
||||
public_ip=""
|
||||
|
||||
# Using WGDASH -- like wg_net functionally as a ARG command. But it is needed in entrypoint.sh so it needs to be exported as environment variable.
|
||||
ENV WGDASH=/opt/wgdashboard
|
||||
|
||||
# Removing the Linux Image package to preserve space on the image, for this reason also deleting apt lists, to be able to install packages: run apt update.
|
||||
|
||||
# Doing WireGuard Dashboard installation measures. Modify the git clone command to get the preferred version, with a specific branch for example.
|
||||
RUN mkdir /data \
|
||||
&& mkdir /configs \
|
||||
@@ -81,10 +67,10 @@ HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||
CMD sh -c 'pgrep gunicorn > /dev/null && pgrep tail > /dev/null' || exit 1
|
||||
|
||||
# Copy the basic entrypoint.sh script.
|
||||
COPY entrypoint.sh /entrypoint.sh
|
||||
COPY ./docker/entrypoint.sh /entrypoint.sh
|
||||
|
||||
# Exposing the default WireGuard Dashboard port for web access.
|
||||
EXPOSE 10086
|
||||
WORKDIR $WGDASH
|
||||
|
||||
ENTRYPOINT ["/bin/bash", "/entrypoint.sh"]
|
||||
ENTRYPOINT ["/bin/bash", "/entrypoint.sh"]
|
||||
+137
-49
@@ -1,39 +1,59 @@
|
||||
# WGDashboard Docker Explanation:
|
||||
Author: DaanSelen<br>
|
||||
Author: @DaanSelen<br>
|
||||
|
||||
This document delves into how the WGDashboard Docker container has been built.<br>
|
||||
Of course there are two stages, 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>
|
||||
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 is integrated into the container itself, so it should be a run-and-go(/out-of-the-box).<br>
|
||||
For more details on the source-code specific to this Docker image, refer to the source files, they have lots of comments.
|
||||
|
||||
I have tried to embed some new features such as `isolate` and interface startup on container-start (through `enable`). I hope you enjoy!
|
||||
<br>
|
||||
<img
|
||||
src="https://wgdashboard-resources.tor1.cdn.digitaloceanspaces.com/Logos/Logo-2-Rounded-512x512.png"
|
||||
alt="WG-Dashboard Logo"
|
||||
title="WG-Dashboard Logo"
|
||||
style="display: block; margin: 0 auto;"
|
||||
width="150"
|
||||
height="150"
|
||||
/>
|
||||
<br>
|
||||
|
||||
<img src="https://raw.githubusercontent.com/donaldzou/WGDashboard/main/src/static/img/logo.png" alt="WG-Dashboard Logo" title="WG-Dashboard Logo" width="150" height="150" />
|
||||
|
||||
## Getting the container running:
|
||||
|
||||
To get the container running you either pull the image from the repository, `donaldzou/wgdashboard:latest`.<br>
|
||||
To get the container running you either pull the image from the repository, (docker.io)`donaldzou/wgdashboard:latest`.<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>
|
||||
Otherwise edit the configuration file in `/etc/wireguard/wg0.conf`.
|
||||
|
||||
An example of a simple command to get the container running is show below:<br>
|
||||
# WGDashboard: 🐳 Docker Deployment Guide
|
||||
|
||||
```shell
|
||||
To run the container, you can either pull the image from Docker Hub or build it yourself. The image is available at:
|
||||
|
||||
```
|
||||
docker.io/donaldzou/wgdashboard:latest
|
||||
```
|
||||
|
||||
> `docker.io` is in most cases automatically resolved by the Docker application.
|
||||
|
||||
### 🔧 Quick Docker Run Command
|
||||
|
||||
Here's an example to get it up and running quickly:
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name wgdashboard \
|
||||
--restart unless-stopped \
|
||||
-e enable=wg0 \
|
||||
-e isolate=wg0 \
|
||||
-p 10086:10086/tcp \
|
||||
-p 51820:51820/udp \
|
||||
--cap-add NET_ADMIN \
|
||||
donaldzou/wgdashboard:latest
|
||||
```
|
||||
<br>
|
||||
If you want to use Compose instead of a raw Docker command, refer to the example in the `compose.yaml` or the one pasted below:
|
||||
<br><br>
|
||||
|
||||
> ⚠️ The default WireGuard port is `51820/udp`. If you change this, update the `/etc/wireguard/wg0.conf` accordingly.
|
||||
|
||||
---
|
||||
|
||||
### 📦 Docker Compose Alternative
|
||||
|
||||
You can also use Docker Compose for easier configuration:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
@@ -42,11 +62,9 @@ services:
|
||||
restart: unless-stopped
|
||||
container_name: wgdashboard
|
||||
environment:
|
||||
#- tz=
|
||||
#- global_dns=
|
||||
#- enable=
|
||||
#- isolate=
|
||||
#- public_ip=
|
||||
# - tz=Europe/Amsterdam
|
||||
# - global_dns=1.1.1.1
|
||||
# - public_ip=YOUR_PUBLIC_IP
|
||||
ports:
|
||||
- 10086:10086/tcp
|
||||
- 51820:51820/udp
|
||||
@@ -59,51 +77,121 @@ services:
|
||||
volumes:
|
||||
conf:
|
||||
data:
|
||||
|
||||
```
|
||||
|
||||
If you want to customize the yaml, make sure the core stays the same, but for example volume PATHs (ON THE HOST) can be freely changed.<br>
|
||||
This setup is just generic and will use the Docker volumes.
|
||||
> 📁 You can customize the **volume paths** on the host to fit your needs. The example above uses Docker volumes.
|
||||
|
||||
## Updating the container:
|
||||
---
|
||||
|
||||
Updating is right now in Alpha stage. I have got it to work, testing methods.
|
||||
## 🔄 Updating the Container
|
||||
|
||||
## Working with the container and environment variables:
|
||||
Updating WGDashboard is currently in **alpha** stage. While the update process may work, it's still under testing.
|
||||
|
||||
Once the container is running, the installation process is essentially the same as running it on bare-metal.<br>
|
||||
So go to the assign TCP port in this case HTTP, like the default 10086 one in the example and log into the WEB-GUI.<br>
|
||||
---
|
||||
|
||||
| Environment variable | Accepted arguments | Default value | Example value | Verbose |
|
||||
| -------------- | ------- | ------- | ------- | ------- |
|
||||
| tz | Europe/Amsterdam or any confirming timezone notation. | `Europe/Amsterdam` | `America/New_York` | Sets the timezone of the Docker container. This is to timesync the container to any other processes which would need it. |
|
||||
| global_dns | Any IPv4 address, such as my personal recommendation: 9.9.9.9 (QUAD9). | `1.1.1.1` | `8.8.8.8` or any IP-Address that resolves DNS-names, and of course is reachable | Set the default DNS given to clients once they connect to the WireGuard tunnel, and for new peers, set to Cloudflare DNS for reliability.
|
||||
| enable | Anything, preferably an existing WireGuard interface name. | `none` | `wg0,wg2,wg13` | Enables or disables the starting of the WireGuard interface on container 'boot-up'.
|
||||
| isolate | Anything, preferably an existing WireGuard interface name. | `none` | `wg1,wg0` | The Wireguard interface itself IS able to reach the peers (Done through the `iptables` package).
|
||||
| public_ip | Any IPv4 (public recommended) address, such as the one returned by default | Default uses the return of `curl ifconfig.me` | `89.20.83.118` | To reach your VPN from outside your own network, you need WG-Dashboard to know what your public IP-address is, otherwise it will generate faulty config files for clients. This happends because it is inside a Docker/Kubernetes container. In or outside of NAT is not relevant as long as the given IP-address is reachable from the internet or the target network.
|
||||
## ⚙️ Environment Variables
|
||||
|
||||
## Be careful with:
|
||||
| Variable | Accepted Values | Default | Example | Description |
|
||||
|---------------|------------------------------------------|-------------------------|------------------------|-----------------------------------------------------------------------------|
|
||||
| `tz` | Timezone | `Europe/Amsterdam` | `America/New_York` | Sets the container's timezone. Useful for accurate logs and scheduling. |
|
||||
| `global_dns` | IPv4 and IPv6 addresses | `9.9.9.9` | `8.8.8.8`, `1.1.1.1` | Default DNS for WireGuard clients. |
|
||||
| `public_ip` | Public IP address | Retrieved automatically | `253.162.134.73` | Used to generate accurate client configs. Needed if container is NAT’d. |
|
||||
| `wgd_port` | Any port that is allowed for the process | `10086` | `443` | This port is used to set the WGDashboard web port. |
|
||||
|
||||
When you are going to work with multiple WireGuard interfaces, you need to also open them up to the Docker host. This done by either adding the port mappings like: `51821:51821/udp` in the Docker Compose file, or to open a range like: `51820-51830:51820-51830/udp`<br>
|
||||
The latter opens up UDP ports from 51820 to 51830, so all ports in between as well! Be careful, it is good security practise to open only needed ports!
|
||||
---
|
||||
|
||||
## Building the image yourself:
|
||||
## 🔐 Port Forwarding Note
|
||||
|
||||
To build the image yourself, you need to do a couple things:<br>
|
||||
1. Clone the Github repository containing the source code of WGDashboard including the docker directory. For example do: `git clone https://github.com/donaldzou/WGDashboard.git`
|
||||
1. Navigate into the cloned repository.
|
||||
1. (Make sure you have Docker correctly installed, if not: [Click here](https://docs.docker.com/engine/install/)) and run: `docker build . -t <Image name>:<Image tag>` as an example: `docker build . -t dselen/wgdashboard:latest`.<br>
|
||||
When using multiple WireGuard interfaces, remember to **open their respective ports** on the host.
|
||||
|
||||
This will make Docker compile the image from the resources in the directory you mention, in this case the source/root one. Let it compile, it takes only a couple seconds with a minute at most.
|
||||
Examples:
|
||||
```yaml
|
||||
# Individual mapping
|
||||
- 51821:51821/udp
|
||||
|
||||
1. If all went well, see your image with `docker images`. Example below:
|
||||
# Or port range
|
||||
- 51820-51830:51820-51830/udp
|
||||
```
|
||||
|
||||
> 🚨 **Security Tip:** Only expose ports you actually use.
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Building the Image Yourself
|
||||
|
||||
To build from source:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/donaldzou/WGDashboard.git
|
||||
cd WGDashboard
|
||||
docker build . -f docker/Dockerfile -t yourname/wgdashboard:latest
|
||||
```
|
||||
|
||||
Example output:
|
||||
```shell
|
||||
dselen@dev-mach:~/development/WGDashboard/docker$ docker images
|
||||
docker images
|
||||
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
dselen/wgdashboard latest c96fd96ee3b3 42 minutes ago 314MB
|
||||
yourname/wgdashboard latest c96fd96ee3b3 42 minutes ago 314MB
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧱 Dockerfile Overview
|
||||
|
||||
Here's a brief overview of the Dockerfile stages used in the image build:
|
||||
|
||||
### 1. **Build Tools & Go Compilation**
|
||||
|
||||
```Dockerfile
|
||||
FROM golang:1.24 AS compiler
|
||||
WORKDIR /go
|
||||
|
||||
RUN apt-get update && apt-get install -y ...
|
||||
RUN git clone ... && make
|
||||
...
|
||||
```
|
||||
|
||||
### 2. **Binary Copy to Scratch**
|
||||
|
||||
```Dockerfile
|
||||
FROM scratch AS bins
|
||||
COPY --from=compiler /go/amneziawg-go/amneziawg-go /amneziawg-go
|
||||
...
|
||||
```
|
||||
|
||||
### 3. **Final Alpine Container Setup**
|
||||
|
||||
```Dockerfile
|
||||
FROM alpine:latest
|
||||
COPY --from=bins ...
|
||||
RUN apk update && apk add --no-cache ...
|
||||
COPY ./src ${WGDASH}/src
|
||||
COPY ./docker/entrypoint.sh /entrypoint.sh
|
||||
...
|
||||
EXPOSE 10086
|
||||
ENTRYPOINT ["/bin/bash", "/entrypoint.sh"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Entrypoint Overview
|
||||
|
||||
### Major Functions:
|
||||
|
||||
- **`ensure_installation`**: Sets up the app, database, and Python environment.
|
||||
- **`set_envvars`**: Writes `wg-dashboard.ini` and applies environment variables.
|
||||
- **`start_core`**: Starts the main WGDashboard service.
|
||||
- **`ensure_blocking`**: Tails the error log to keep the container process alive.
|
||||
|
||||
---
|
||||
|
||||
## ✅ Final Notes
|
||||
|
||||
- Use `docker logs wgdashboard` for troubleshooting.
|
||||
- Access the web interface via `http://your-ip:10086` (or whichever port you specified in the compose).
|
||||
- The first time run will auto-generate WireGuard keys and configs (configs are generated from the template).
|
||||
|
||||
## Closing remarks:
|
||||
|
||||
For feedback please submit an issue to the repository. Or message dselen@nerthus.nl.
|
||||
For feedback please submit an issue to the repository. Or message dselen@nerthus.nl.
|
||||
+2
-2
@@ -5,19 +5,19 @@ services:
|
||||
container_name: wgdashboard
|
||||
#environment:
|
||||
#- tz= # <--- Set container timezone, default: Europe/Amsterdam.
|
||||
#- global_dns= # <--- Set global DNS address, default: 1.1.1.1.
|
||||
#- isolate= # <--- Set the interfaces that will disallow peer communication, default: 'none'.
|
||||
#- 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.
|
||||
ports:
|
||||
- 10086:10086/tcp
|
||||
- 51820:51820/udp
|
||||
volumes:
|
||||
- aconf:/etc/amnezia/amneziawg
|
||||
- conf:/etc/wireguard
|
||||
- data:/data
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
|
||||
volumes:
|
||||
aconf:
|
||||
conf:
|
||||
data:
|
||||
|
||||
@@ -7,7 +7,7 @@ trap 'stop_service' SIGTERM
|
||||
|
||||
stop_service() {
|
||||
echo "[WGDashboard] Stopping WGDashboard..."
|
||||
bash ./wgd.sh stop
|
||||
/bin/bash ./wgd.sh stop
|
||||
exit 0
|
||||
}
|
||||
|
||||
@@ -18,51 +18,68 @@ ensure_installation() {
|
||||
# When using a custom directory to store the files, this part moves over and makes sure the installation continues.
|
||||
echo "Quick-installing..."
|
||||
|
||||
# Make the wgd.sh script executable.
|
||||
chmod +x "${WGDASH}"/src/wgd.sh
|
||||
cd "${WGDASH}"/src || exit
|
||||
|
||||
# Github issue: https://github.com/donaldzou/WGDashboard/issues/723
|
||||
echo "Checking for stale pids..."
|
||||
if [[ -f ${WGDASH}/src/gunicorn.pid ]]; then
|
||||
echo "Found stale pid, removing..."
|
||||
rm ${WGDASH}/src/gunicorn.pid
|
||||
fi
|
||||
|
||||
# Removing clear shell command from the wgd.sh script to enhance docker logging.
|
||||
echo "Removing clear command from wgd.sh for better Docker logging."
|
||||
sed -i '/clear/d' ./wgd.sh
|
||||
|
||||
# Create the databases directory if it does not exist yet.
|
||||
if [ ! -d "/data/db" ]; then
|
||||
echo "Creating database dir"
|
||||
mkdir /data/db
|
||||
fi
|
||||
|
||||
# Linking the database on the persistent directory location to where WGDashboard expects.
|
||||
if [ ! -d "${WGDASH}/src/db" ]; then
|
||||
ln -s /data/db "${WGDASH}/src/db"
|
||||
fi
|
||||
|
||||
# Create the wg-dashboard.ini file if it does not exist yet.
|
||||
if [ ! -f "${config_file}" ]; then
|
||||
echo "Creating wg-dashboard.ini file"
|
||||
touch "${config_file}"
|
||||
fi
|
||||
|
||||
# Link the wg-dashboard.ini file from the persistent directory to where WGDashboard expects it.
|
||||
if [ ! -f "${WGDASH}/src/wg-dashboard.ini" ]; then
|
||||
ln -s "${config_file}" "${WGDASH}/src/wg-dashboard.ini"
|
||||
fi
|
||||
|
||||
# Create the Python virtual environment.
|
||||
python3 -m venv "${WGDASH}"/src/venv
|
||||
. "${WGDASH}/src/venv/bin/activate"
|
||||
|
||||
# Due to this pip dependency being available as a system package we can just move it to the venv.
|
||||
echo "Moving PIP dependency from ephemerality to runtime environment: psutil"
|
||||
mv /usr/lib/python3.12/site-packages/psutil* "${WGDASH}"/src/venv/lib/python3.12/site-packages
|
||||
|
||||
# Due to this pip dependency being available as a system package we can just move it to the venv.
|
||||
echo "Moving PIP dependency from ephemerality to runtime environment: bcrypt"
|
||||
mv /usr/lib/python3.12/site-packages/bcrypt* "${WGDASH}"/src/venv/lib/python3.12/site-packages
|
||||
|
||||
./wgd.sh install
|
||||
# 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."
|
||||
|
||||
# This first step is to ensure the wg0.conf file exists, and if not, then its copied over from the ephemeral container storage.
|
||||
# This is done so WGDashboard it works out of the box
|
||||
# This is done so WGDashboard it works out of the box, it also sets a randomly generated private key.
|
||||
|
||||
if [ ! -f "/etc/wireguard/wg0.conf" ]; then
|
||||
echo "Standard wg0 Configuration file not found, grabbing template."
|
||||
cp -a "/configs/wg0.conf.template" "/etc/wireguard/wg0.conf"
|
||||
|
||||
echo "Setting a secure private key." # SORRY 4 BE4 - Daan
|
||||
echo "Setting a secure private key."
|
||||
|
||||
local privateKey
|
||||
privateKey=$(wg genkey)
|
||||
@@ -106,6 +123,7 @@ set_envvars() {
|
||||
sed -i "s/^peer_global_dns = .*/peer_global_dns = ${global_dns}/" "${config_file}"
|
||||
fi
|
||||
|
||||
# Checking the current set public IP and changing it if it has changed.
|
||||
current_public_ip=$(grep "remote_endpoint = " "${config_file}" | awk '{print $NF}')
|
||||
if [ "${public_ip}" == "" ]; then
|
||||
default_ip=$(curl -s ifconfig.me)
|
||||
@@ -118,6 +136,7 @@ set_envvars() {
|
||||
echo "Public-IP is correct, moving on."
|
||||
fi
|
||||
|
||||
# Checking the current WGDashboard web port and changing if needed.
|
||||
current_wgd_port=$(grep "app_port = " "${config_file}" | awk '{print $NF}')
|
||||
if [ "${current_wgd_port}" == "${wgd_port}" ]; then
|
||||
echo "Current WGD port is set correctly, moving on."
|
||||
@@ -131,11 +150,18 @@ set_envvars() {
|
||||
start_core() {
|
||||
printf "\n---------------------- STARTING CORE -----------------------\n"
|
||||
|
||||
# Due to some instances complaining about this, making sure its there every time.
|
||||
mkdir -p /dev/net
|
||||
mknod /dev/net/tun c 10 200
|
||||
chmod 600 /dev/net/tun
|
||||
|
||||
# Actually starting WGDashboard
|
||||
echo "Activating Python venv and executing the WireGuard Dashboard service."
|
||||
bash ./wgd.sh start
|
||||
/bin/bash ./wgd.sh start
|
||||
}
|
||||
|
||||
ensure_blocking() {
|
||||
# Wait a second before continuing, to give the python program some time to get ready.
|
||||
sleep 1s
|
||||
echo -e "\nEnsuring container continuation."
|
||||
|
||||
@@ -147,9 +173,12 @@ ensure_blocking() {
|
||||
# Only tail the logs if they are found
|
||||
if [ -n "$latestErrLog" ]; then
|
||||
tail -f "$latestErrLog" &
|
||||
|
||||
# Wait for the tail process to end.
|
||||
wait $!
|
||||
else
|
||||
echo "No log files found to tail. Something went wrong, exiting..."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
+55
-43
@@ -25,7 +25,7 @@ from modules.PeerJob import PeerJob
|
||||
from modules.SystemStatus import SystemStatus
|
||||
SystemStatus = SystemStatus()
|
||||
|
||||
DASHBOARD_VERSION = 'v4.2.0'
|
||||
DASHBOARD_VERSION = 'v4.2.5'
|
||||
|
||||
CONFIGURATION_PATH = os.getenv('CONFIGURATION_PATH', '.')
|
||||
DB_PATH = os.path.join(CONFIGURATION_PATH, 'db')
|
||||
@@ -180,6 +180,7 @@ class PeerJobs:
|
||||
|
||||
def runJob(self):
|
||||
needToDelete = []
|
||||
self.__getJobs()
|
||||
for job in self.Jobs:
|
||||
c = WireguardConfigurations.get(job.Configuration)
|
||||
if c is not None:
|
||||
@@ -432,7 +433,6 @@ class WireguardConfiguration:
|
||||
original = [l.rstrip("\n") for l in f.readlines()]
|
||||
try:
|
||||
start = original.index("[Interface]")
|
||||
|
||||
# Clean
|
||||
for i in range(start, len(original)):
|
||||
if original[i] == "[Peer]":
|
||||
@@ -445,7 +445,7 @@ class WireguardConfiguration:
|
||||
setattr(self, key, False)
|
||||
else:
|
||||
setattr(self, key, "")
|
||||
|
||||
|
||||
# Set
|
||||
for i in range(start, len(original)):
|
||||
if original[i] == "[Peer]":
|
||||
@@ -459,7 +459,10 @@ class WireguardConfiguration:
|
||||
setattr(self, key, StringToBoolean(value))
|
||||
else:
|
||||
if len(getattr(self, key)) > 0:
|
||||
setattr(self, key, f"{getattr(self, key)}, {value}")
|
||||
if key not in ["PostUp", "PostDown", "PreUp", "PreDown"]:
|
||||
setattr(self, key, f"{getattr(self, key)}, {value}")
|
||||
else:
|
||||
setattr(self, key, f"{getattr(self, key)}; {value}")
|
||||
else:
|
||||
setattr(self, key, value)
|
||||
except ValueError as e:
|
||||
@@ -470,11 +473,12 @@ class WireguardConfiguration:
|
||||
self.Status = self.getStatus()
|
||||
|
||||
def __dropDatabase(self):
|
||||
existingTables = sqlSelect(f"SELECT name FROM sqlite_master WHERE type='table' AND name LIKE '{self.Name}%'").fetchall()
|
||||
existingTables = [self.Name, f'{self.Name}_restrict_access', f'{self.Name}_transfer', f'{self.Name}_deleted']
|
||||
# existingTables = sqlSelect(f"SELECT name FROM sqlite_master WHERE type='table' AND name LIKE '{self.Name}%'").fetchall()
|
||||
for t in existingTables:
|
||||
sqlUpdate("DROP TABLE '%s'" % t['name'])
|
||||
sqlUpdate("DROP TABLE '%s'" % t)
|
||||
|
||||
existingTables = sqlSelect(f"SELECT name FROM sqlite_master WHERE type='table' AND name LIKE '{self.Name}%'").fetchall()
|
||||
# existingTables = sqlSelect(f"SELECT name FROM sqlite_master WHERE type='table' AND name LIKE '{self.Name}%'").fetchall()
|
||||
|
||||
def createDatabase(self, dbName = None):
|
||||
if dbName is None:
|
||||
@@ -804,6 +808,9 @@ class WireguardConfiguration:
|
||||
return ResponseObject(False, "Failed to save configuration through WireGuard")
|
||||
|
||||
self.getPeers()
|
||||
|
||||
if numOfDeletedPeers == 0 and numOfFailedToDeletePeers == 0:
|
||||
return ResponseObject(False, "No peer(s) to delete found", responseCode=404)
|
||||
|
||||
if numOfDeletedPeers == len(listOfPublicKeys):
|
||||
return ResponseObject(True, f"Deleted {numOfDeletedPeers} peer(s)")
|
||||
@@ -945,7 +952,8 @@ class WireguardConfiguration:
|
||||
},
|
||||
"ConnectedPeers": len(list(filter(lambda x: x.status == "running", self.Peers))),
|
||||
"TotalPeers": len(self.Peers),
|
||||
"Protocol": self.Protocol
|
||||
"Protocol": self.Protocol,
|
||||
"Table": self.Table,
|
||||
}
|
||||
|
||||
def backupConfigurationFile(self) -> tuple[bool, dict[str, str]]:
|
||||
@@ -1047,7 +1055,7 @@ class WireguardConfiguration:
|
||||
dataChanged = False
|
||||
with open(self.configPath, 'r') as f:
|
||||
original = [l.rstrip("\n") for l in f.readlines()]
|
||||
allowEdit = ["Address", "PreUp", "PostUp", "PreDown", "PostDown", "ListenPort"]
|
||||
allowEdit = ["Address", "PreUp", "PostUp", "PreDown", "PostDown", "ListenPort", "Table"]
|
||||
if self.Protocol == 'awg':
|
||||
allowEdit += ["Jc", "Jmin", "Jmax", "S1", "S2", "H1", "H2", "H3", "H4"]
|
||||
start = original.index("[Interface]")
|
||||
@@ -1204,15 +1212,15 @@ AmneziaWG Configuration
|
||||
"""
|
||||
class AmneziaWireguardConfiguration(WireguardConfiguration):
|
||||
def __init__(self, name: str = None, data: dict = None, backup: dict = None, startup: bool = False):
|
||||
self.Jc = 0
|
||||
self.Jmin = 0
|
||||
self.Jmax = 0
|
||||
self.S1 = 0
|
||||
self.S2 = 0
|
||||
self.H1 = 1
|
||||
self.H2 = 2
|
||||
self.H3 = 3
|
||||
self.H4 = 4
|
||||
self.Jc = ""
|
||||
self.Jmin = ""
|
||||
self.Jmax = ""
|
||||
self.S1 = ""
|
||||
self.S2 = ""
|
||||
self.H1 = ""
|
||||
self.H2 = ""
|
||||
self.H3 = ""
|
||||
self.H4 = ""
|
||||
|
||||
super().__init__(name, data, backup, startup, wg=False)
|
||||
|
||||
@@ -1237,6 +1245,7 @@ class AmneziaWireguardConfiguration(WireguardConfiguration):
|
||||
},
|
||||
"ConnectedPeers": len(list(filter(lambda x: x.status == "running", self.Peers))),
|
||||
"TotalPeers": len(self.Peers),
|
||||
"Table": self.Table,
|
||||
"Protocol": self.Protocol,
|
||||
"Jc": self.Jc,
|
||||
"Jmin": self.Jmin,
|
||||
@@ -1434,7 +1443,7 @@ class AmneziaWireguardConfiguration(WireguardConfiguration):
|
||||
f.write(p['preshared_key'])
|
||||
|
||||
subprocess.check_output(
|
||||
f"{self.Protocol} set {self.Name} peer {p['id']} allowed-ips {p['allowed_ip'].replace(' ', '')}{f' preshared-key {uid}' if presharedKeyExist else ''} advanced-security {p['advanced_security']}",
|
||||
f"{self.Protocol} set {self.Name} peer {p['id']} allowed-ips {p['allowed_ip'].replace(' ', '')}{f' preshared-key {uid}' if presharedKeyExist else ''}",
|
||||
shell=True, stderr=subprocess.STDOUT)
|
||||
if presharedKeyExist:
|
||||
os.remove(uid)
|
||||
@@ -1713,7 +1722,7 @@ PersistentKeepalive = {str(self.keepalive)}
|
||||
f.write(preshared_key)
|
||||
newAllowedIPs = allowed_ip.replace(" ", "")
|
||||
updateAllowedIp = subprocess.check_output(
|
||||
f"{self.configuration.Protocol} set {self.configuration.Name} peer {self.id} allowed-ips {newAllowedIPs} {f'preshared-key {uid}' if pskExist else 'preshared-key /dev/null'} advanced-security {advanced_security}",
|
||||
f"{self.configuration.Protocol} set {self.configuration.Name} peer {self.id} allowed-ips {newAllowedIPs} {f'preshared-key {uid}' if pskExist else 'preshared-key /dev/null'}",
|
||||
shell=True, stderr=subprocess.STDOUT)
|
||||
|
||||
if pskExist: os.remove(uid)
|
||||
@@ -1756,7 +1765,7 @@ class DashboardConfig:
|
||||
def __init__(self):
|
||||
if not os.path.exists(DASHBOARD_CONF):
|
||||
open(DASHBOARD_CONF, "x")
|
||||
self.__config = configparser.ConfigParser(strict=False)
|
||||
self.__config = configparser.RawConfigParser(strict=False)
|
||||
self.__config.read_file(open(DASHBOARD_CONF, "r+"))
|
||||
self.hiddenAttribute = ["totp_key", "auth_req"]
|
||||
self.__default = {
|
||||
@@ -1903,9 +1912,9 @@ class DashboardConfig:
|
||||
self.__config[section] = {}
|
||||
else:
|
||||
return False, "Section does not exist"
|
||||
|
||||
|
||||
if ((key not in self.__config[section].keys() and init) or
|
||||
(key in self.__config[section].keys() and value != self.__config[section][key] and not init)):
|
||||
(key in self.__config[section].keys())):
|
||||
if type(value) is bool:
|
||||
if value:
|
||||
self.__config[section][key] = "true"
|
||||
@@ -2042,7 +2051,7 @@ def auth_req():
|
||||
else:
|
||||
DashboardConfig.APIAccessed = False
|
||||
whiteList = [
|
||||
'/static/', 'validateAuthentication', 'authenticate', 'getDashboardConfiguration',
|
||||
'/static/', 'validateAuthentication', 'authenticate',
|
||||
'getDashboardTheme', 'getDashboardVersion', 'sharePeer/get', 'isTotpEnabled', 'locale',
|
||||
'/fileDownload'
|
||||
]
|
||||
@@ -2180,7 +2189,7 @@ def API_addWireguardConfiguration():
|
||||
WireguardConfigurations[data['ConfigurationName']] = WireguardConfiguration(data=data) if data.get('Protocol') == 'wg' else AmneziaWireguardConfiguration(data=data)
|
||||
return ResponseObject()
|
||||
|
||||
@app.get(f'{APP_PREFIX}/api/toggleWireguardConfiguration/')
|
||||
@app.get(f'{APP_PREFIX}/api/toggleWireguardConfiguration')
|
||||
def API_toggleWireguardConfiguration():
|
||||
configurationName = request.args.get('configurationName')
|
||||
if configurationName is None or len(
|
||||
@@ -2373,7 +2382,7 @@ def API_updateDashboardConfigurationItem():
|
||||
valid, msg = DashboardConfig.SetConfig(
|
||||
data["section"], data["key"], data['value'])
|
||||
if not valid:
|
||||
return ResponseObject(False, msg, status_code=404)
|
||||
return ResponseObject(False, msg)
|
||||
if data['section'] == "Server":
|
||||
if data['key'] == 'wg_conf_path':
|
||||
WireguardConfigurations.clear()
|
||||
@@ -2434,7 +2443,7 @@ def API_updatePeerSettings(configName):
|
||||
allowed_ip, endpoint_allowed_ip, mtu, keepalive)
|
||||
|
||||
return peer.updatePeer(name, private_key, preshared_key, dns_addresses,
|
||||
allowed_ip, endpoint_allowed_ip, mtu, keepalive, data.get('advanced_security', 'off'))
|
||||
allowed_ip, endpoint_allowed_ip, mtu, keepalive, "off")
|
||||
|
||||
return ResponseObject(False, "Peer does not exist")
|
||||
|
||||
@@ -2463,11 +2472,11 @@ def API_deletePeers(configName: str) -> ResponseObject:
|
||||
peers = data['peers']
|
||||
if configName in WireguardConfigurations.keys():
|
||||
if len(peers) == 0:
|
||||
return ResponseObject(False, "Please specify one or more peers")
|
||||
return ResponseObject(False, "Please specify one or more peers", status_code=400)
|
||||
configuration = WireguardConfigurations.get(configName)
|
||||
return configuration.deletePeers(peers)
|
||||
|
||||
return ResponseObject(False, "Configuration does not exist")
|
||||
return ResponseObject(False, "Configuration does not exist", status_code=404)
|
||||
|
||||
@app.post(f'{APP_PREFIX}/api/restrictPeers/<configName>')
|
||||
def API_restrictPeers(configName: str) -> ResponseObject:
|
||||
@@ -2604,7 +2613,7 @@ def API_addPeers(configName):
|
||||
"endpoint_allowed_ip": endpoint_allowed_ip,
|
||||
"mtu": mtu,
|
||||
"keepalive": keep_alive,
|
||||
"advanced_security": data.get("advanced_security", "off")
|
||||
"advanced_security": "off"
|
||||
})
|
||||
if addedCount == bulkAddAmount:
|
||||
break
|
||||
@@ -2674,7 +2683,7 @@ def API_addPeers(configName):
|
||||
"DNS": dns_addresses,
|
||||
"mtu": mtu,
|
||||
"keepalive": keep_alive,
|
||||
"advanced_security": data.get("advanced_security", "off")
|
||||
"advanced_security": "off"
|
||||
}]
|
||||
)
|
||||
return ResponseObject(status=status, message=result['message'], data=result['peers'])
|
||||
@@ -2952,7 +2961,7 @@ def API_isTotpEnabled():
|
||||
@app.get(f'{APP_PREFIX}/api/Welcome_GetTotpLink')
|
||||
def API_Welcome_GetTotpLink():
|
||||
if not DashboardConfig.GetConfig("Account", "totp_verified")[1]:
|
||||
DashboardConfig.SetConfig("Account", "totp_key", pyotp.random_base32())
|
||||
DashboardConfig.SetConfig("Account", "totp_key", pyotp.random_base32(), True)
|
||||
return ResponseObject(
|
||||
data=pyotp.totp.TOTP(DashboardConfig.GetConfig("Account", "totp_key")[1]).provisioning_uri(
|
||||
issuer_name="WGDashboard"))
|
||||
@@ -3106,16 +3115,19 @@ def peerInformationBackgroundThread():
|
||||
time.sleep(10)
|
||||
while True:
|
||||
with app.app_context():
|
||||
for c in WireguardConfigurations.values():
|
||||
if c.getStatus():
|
||||
try:
|
||||
c.getPeersTransfer()
|
||||
c.getPeersLatestHandshake()
|
||||
c.getPeersEndpoint()
|
||||
c.getPeersList()
|
||||
c.getRestrictedPeersList()
|
||||
except Exception as e:
|
||||
print(f"[WGDashboard] Background Thread #1 Error: {str(e)}", flush=True)
|
||||
try:
|
||||
curKeys = list(WireguardConfigurations.keys())
|
||||
for name in curKeys:
|
||||
if name in WireguardConfigurations.keys() and WireguardConfigurations.get(name) is not None:
|
||||
c = WireguardConfigurations.get(name)
|
||||
if c.getStatus():
|
||||
c.getPeersTransfer()
|
||||
c.getPeersLatestHandshake()
|
||||
c.getPeersEndpoint()
|
||||
c.getPeersList()
|
||||
c.getRestrictedPeersList()
|
||||
except Exception as e:
|
||||
print(f"[WGDashboard] Background Thread #1 Error: {str(e)}", flush=True)
|
||||
time.sleep(10)
|
||||
|
||||
def peerJobScheduleBackgroundThread():
|
||||
@@ -3191,4 +3203,4 @@ def startThreads():
|
||||
|
||||
if __name__ == "__main__":
|
||||
startThreads()
|
||||
app.run(host=app_ip, debug=False, port=app_port)
|
||||
app.run(host=app_ip, debug=False, port=app_port)
|
||||
|
||||
@@ -11,8 +11,8 @@ class EmailSender:
|
||||
def __init__(self, DashboardConfig):
|
||||
self.smtp = None
|
||||
self.DashboardConfig = DashboardConfig
|
||||
if not os.path.exists('../attachments'):
|
||||
os.mkdir('../attachments')
|
||||
if not os.path.exists('./attachments'):
|
||||
os.mkdir('./attachments')
|
||||
|
||||
def Server(self):
|
||||
return self.DashboardConfig.GetConfig("Email", "server")[1]
|
||||
@@ -33,8 +33,7 @@ class EmailSender:
|
||||
return self.DashboardConfig.GetConfig("Email", "send_from")[1]
|
||||
|
||||
def ready(self):
|
||||
print(self.Server())
|
||||
return len(self.Server()) > 0 and len(self.Port()) > 0 and len(self.Encryption()) > 0 and len(self.Username()) > 0 and len(self.Password()) > 0
|
||||
return len(self.Server()) > 0 and len(self.Port()) > 0 and len(self.Encryption()) > 0 and len(self.Username()) > 0 and len(self.Password()) > 0 and len(self.SendFrom())
|
||||
|
||||
def send(self, receiver, subject, body, includeAttachment = False, attachmentName = ""):
|
||||
if self.ready():
|
||||
@@ -46,7 +45,7 @@ class EmailSender:
|
||||
self.smtp.login(self.Username(), self.Password())
|
||||
message = MIMEMultipart()
|
||||
message['Subject'] = subject
|
||||
message['From'] = formataddr((Header(self.SendFrom()).encode(), self.Username()))
|
||||
message['From'] = self.SendFrom()
|
||||
message["To"] = receiver
|
||||
message.attach(MIMEText(body, "plain"))
|
||||
|
||||
@@ -62,7 +61,7 @@ class EmailSender:
|
||||
else:
|
||||
self.smtp.close()
|
||||
return False, "Attachment does not exist"
|
||||
self.smtp.sendmail(self.Username(), receiver, message.as_string())
|
||||
self.smtp.sendmail(self.SendFrom(), receiver, message.as_string())
|
||||
self.smtp.close()
|
||||
return True, None
|
||||
except Exception as e:
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
import{_ as r,c as i,d as o,w as e,k as l,a as t,j as _,i as a,l as d,S as u}from"./index-CUmHRwBw.js";const m={name:"configuration"},p={class:"mt-md-5 mt-3 text-body"};function f(k,x,h,w,$,v){const n=l("RouterView");return t(),i("div",p,[o(n,null,{default:e(({Component:s,route:c})=>[o(_,{name:"fade2",mode:"out-in"},{default:e(()=>[(t(),a(u,null,{default:e(()=>[(t(),a(d(s),{key:c.path}))]),_:2},1024))]),_:2},1024)]),_:1})])}const B=r(m,[["render",f]]);export{B as default};
|
||||
import{_ as r,c as i,d as o,w as e,k as l,a as t,j as _,i as a,l as d,S as u}from"./index-oBQzjt8-.js";const m={name:"configuration"},p={class:"mt-md-5 mt-3 text-body"};function f(k,x,h,w,$,v){const n=l("RouterView");return t(),i("div",p,[o(n,null,{default:e(({Component:s,route:c})=>[o(_,{name:"fade2",mode:"out-in"},{default:e(()=>[(t(),a(u,null,{default:e(()=>[(t(),a(d(s),{key:c.path}))]),_:2},1024))]),_:2},1024)]),_:1})])}const B=r(m,[["render",f]]);export{B as default};
|
||||
@@ -1 +0,0 @@
|
||||
.fade-enter-active[data-v-6451623a]{transition-delay:var(--d75b06ae)!important}.progress-bar[data-v-c7f6d1a1]{width:0;transition:all 1s cubic-bezier(.42,0,.22,1)}.filter a[data-v-ea61b607]{text-decoration:none}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
.fade-enter-active[data-v-dafd6275]{transition-delay:var(--7d032b58)!important}.progress-bar[data-v-851170e4]{width:0;transition:all 1s cubic-bezier(.42,0,.22,1)}.filter a[data-v-ea61b607]{text-decoration:none}
|
||||
File diff suppressed because one or more lines are too long
Vendored
+1
-1
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 +0,0 @@
|
||||
.agentMessage[data-v-8635cf47]{white-space:break-spaces;max-width:80%;display:flex;flex-direction:column;word-wrap:break-word}.text-bg-secondary[data-v-8635cf47]{background-color:RGBA(var(--bs-secondary-rgb),.7)!important}.text-bg-primary[data-v-8635cf47]{background-color:RGBA(var(--bs-primary-rgb),.7)!important}.agentContainer[data-v-694cfad1]{--agentHeight: 100vh;position:absolute;z-index:9999;top:0;left:100%;width:450px;box-shadow:0 10px 30px #0000004d;backdrop-filter:blur(8px);background:linear-gradient(var(--degree),#009dff52 var(--distance2),#ff4a0052 100%)}.agentContainer.enabled[data-v-694cfad1]{height:calc(var(--agentHeight) - 1rem)}@media screen and (max-width: 768px){.agentContainer[data-v-694cfad1]{--agentHeight: 100vh !important;top:0;left:0;max-height:calc(var(--agentHeight) - 58px - 1rem);width:calc(100% - 1rem)}}.agentChatroomBody[data-v-694cfad1]{flex:1 1 auto;overflow-y:auto;max-height:calc(var(--agentHeight) - 70px - 244px)}@media screen and (max-width: 768px){.navbar-container[data-v-58e71749]{position:absolute!important;z-index:1000;animation-duration:.4s;animation-fill-mode:both;display:none;animation-timing-function:cubic-bezier(.82,.58,.17,.9)}.navbar-container.active[data-v-58e71749]{animation-direction:normal;display:block!important;animation-name:zoomInFade-58e71749}}.navbar-container[data-v-58e71749]{height:100vh;position:relative}@supports (height: 100dvh){@media screen and (max-width: 768px){.navbar-container[data-v-58e71749]{height:calc(100dvh - 58px)}}}@keyframes zoomInFade-58e71749{0%{opacity:0;transform:translateY(60px);filter:blur(3px)}to{opacity:1;transform:translateY(0);filter:blur(0px)}}.slideIn-enter-active[data-v-58e71749],.slideIn-leave-active[data-v-58e71749]{transition:all .3s cubic-bezier(.82,.58,.17,1)}.slideIn-enter-from[data-v-58e71749],.slideIn-leave-to[data-v-58e71749]{transform:translateY(30px);filter:blur(3px);opacity:0}main[data-v-0c6a5068]{height:100vh}@supports (height: 100dvh){@media screen and (max-width: 768px){main[data-v-0c6a5068]{height:calc(100dvh - 58px)}}}
|
||||
-56
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
.agentContainer[data-v-44ff028e]{--agentHeight: 100vh;position:absolute;z-index:9999;top:0;left:100%;width:450px;box-shadow:0 10px 30px #0000004d;backdrop-filter:blur(8px);background:linear-gradient(var(--degree),#009dff52 var(--distance2),#F9464752 100%)}.agentContainer.enabled[data-v-44ff028e]{height:calc(var(--agentHeight) - 1rem)}@media screen and (max-width: 768px){.agentContainer[data-v-44ff028e]{--agentHeight: 100vh !important;top:0;left:0;max-height:calc(var(--agentHeight) - 58px - 1rem);width:calc(100% - 1rem)}}.agentChatroomBody[data-v-44ff028e]{flex:1 1 auto;overflow-y:auto;max-height:calc(var(--agentHeight) - 70px - 244px)}@media screen and (max-width: 768px){.navbar-container[data-v-58e71749]{position:absolute!important;z-index:1000;animation-duration:.4s;animation-fill-mode:both;display:none;animation-timing-function:cubic-bezier(.82,.58,.17,.9)}.navbar-container.active[data-v-58e71749]{animation-direction:normal;display:block!important;animation-name:zoomInFade-58e71749}}.navbar-container[data-v-58e71749]{height:100vh;position:relative}@supports (height: 100dvh){@media screen and (max-width: 768px){.navbar-container[data-v-58e71749]{height:calc(100dvh - 58px)}}}@keyframes zoomInFade-58e71749{0%{opacity:0;transform:translateY(60px);filter:blur(3px)}to{opacity:1;transform:translateY(0);filter:blur(0px)}}.slideIn-enter-active[data-v-58e71749],.slideIn-leave-active[data-v-58e71749]{transition:all .3s cubic-bezier(.82,.58,.17,1)}.slideIn-enter-from[data-v-58e71749],.slideIn-leave-to[data-v-58e71749]{transform:translateY(30px);filter:blur(3px);opacity:0}main[data-v-0c6a5068]{height:100vh}@supports (height: 100dvh){@media screen and (max-width: 768px){main[data-v-0c6a5068]{height:calc(100dvh - 58px)}}}
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{P as Ws,Q as Vs,R as Ue,U as Hn,r as Wn,o as Vn,V as Nn,H as jn,X as Xe,Y as $n,Z as Ns}from"./index-CUmHRwBw.js";/*!
|
||||
import{P as Ws,Q as Vs,R as Ue,U as Hn,r as Wn,o as Vn,V as Nn,H as jn,X as Xe,Y as $n,Z as Ns}from"./index-oBQzjt8-.js";/*!
|
||||
* @kurkle/color v0.3.2
|
||||
* https://github.com/kurkle/color#readme
|
||||
* (c) 2023 Jukka Kurkela
|
||||
File diff suppressed because one or more lines are too long
Vendored
+11
-11
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
||||
import{_ as e,G as t,a as o,c as a,t as c}from"./index-CUmHRwBw.js";const s={name:"localeText",props:{t:""},computed:{getLocaleText(){return t(this.t)}}};function n(r,p,l,_,i,x){return o(),a("span",null,c(this.getLocaleText),1)}const u=e(s,[["render",n]]);export{u as L};
|
||||
import{_ as e,G as t,a as o,c as a,t as c}from"./index-oBQzjt8-.js";const s={name:"localeText",props:{t:""},computed:{getLocaleText(){return t(this.t)}}};function n(r,p,l,_,i,x){return o(),a("span",null,c(this.getLocaleText),1)}const u=e(s,[["render",n]]);export{u as L};
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
import{L as l}from"./localeText-DvaqSAco.js";import{d as c}from"./dayjs.min-C3XPfvH9.js";import{_ as h,a as o,c as a,b as e,d as i,w as u,f as p,t as n,j as g,n as f,k as _}from"./index-CUmHRwBw.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(j,s,C,L,t,m){const d=_("LocaleText");return o(),a("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:f([{"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(g,{name:"zoom",mode:"out-in"},{default:u(()=>[t.dismiss?(o(),a("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"})])])):(o(),a("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-CuybU_0U.js";import{d as c}from"./dayjs.min-BHDUvWAB.js";import{_ as h,a as o,c as a,b as e,d as i,w as u,f as p,t as n,j as g,n as f,k as _}from"./index-oBQzjt8-.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(j,s,C,L,t,m){const d=_("LocaleText");return o(),a("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:f([{"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(g,{name:"zoom",mode:"out-in"},{default:u(()=>[t.dismiss?(o(),a("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"})])])):(o(),a("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
@@ -0,0 +1 @@
|
||||
.protocolBtnGroup a[data-v-b97242f3]{transition:all .2s ease-in-out}
|
||||
@@ -1 +0,0 @@
|
||||
.protocolBtnGroup a[data-v-b4bbbc2b]{transition:all .2s ease-in-out}
|
||||
File diff suppressed because one or more lines are too long
Vendored
+1
-1
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
@@ -1 +1 @@
|
||||
import{_ as v,D as g,r as o,o as h,J as x,g as y,a as i,c as n,b as s,d as c,n as w,e as C,w as k,j as F}from"./index-CUmHRwBw.js";import{L as T}from"./localeText-DvaqSAco.js";import"./browser-CjSdxGTc.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"},P={class:"card rounded-3 shadow w-100"},j={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"},L={style:{height:"300px"},class:"d-flex"},N=["value"],V={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)=>(i(),n("div",M,[s("div",S,[s("div",D,[s("div",P,[s("div",j,[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",L,[s("textarea",{style:{height:"300px"},class:w(["form-control w-100 rounded-3 animate__fadeIn animate__faster animate__animated",{"d-none":a.value}]),id:"peerConfigurationFile",value:l.value},null,10,N),a.value?(i(),n("div",V,e[2]||(e[2]=[s("span",{class:"visually-hidden"},"Loading...",-1)]))):C("",!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?(i(),n("span",q,e[4]||(e[4]=[s("i",{class:"bi bi-check-circle-fill"},null,-1)]))):(i(),n("span",$,e[3]||(e[3]=[s("i",{class:"bi bi-clipboard-fill"},null,-1)])))]),_:1})],8,W)])])])])])]))}},R=v(z,[["__scopeId","data-v-b0ea2d46"]]);export{R as default};
|
||||
import{_ as v,D as g,r as o,o as h,J as x,g as y,a as i,c as n,b as s,d as c,n as w,e as C,w as k,j as F}from"./index-oBQzjt8-.js";import{L as T}from"./localeText-CuybU_0U.js";import"./browser-CjSdxGTc.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"},P={class:"card rounded-3 shadow w-100"},j={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"},L={style:{height:"300px"},class:"d-flex"},N=["value"],V={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)=>(i(),n("div",M,[s("div",S,[s("div",D,[s("div",P,[s("div",j,[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",L,[s("textarea",{style:{height:"300px"},class:w(["form-control w-100 rounded-3 animate__fadeIn animate__faster animate__animated",{"d-none":a.value}]),id:"peerConfigurationFile",value:l.value},null,10,N),a.value?(i(),n("div",V,e[2]||(e[2]=[s("span",{class:"visually-hidden"},"Loading...",-1)]))):C("",!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?(i(),n("span",q,e[4]||(e[4]=[s("i",{class:"bi bi-check-circle-fill"},null,-1)]))):(i(),n("span",$,e[3]||(e[3]=[s("i",{class:"bi bi-clipboard-fill"},null,-1)])))]),_:1})],8,W)])])])])])]))}},R=v(z,[["__scopeId","data-v-b0ea2d46"]]);export{R as default};
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
import{S as p,a as b}from"./schedulePeerJob-Rx5QXWIx.js";import{_ as h,W as u,z as m,k as i,a as o,c as a,b as e,d as r,w as _,F as v,h as f,i as J,e as x,T as g}from"./index-CUmHRwBw.js";import{L as w}from"./localeText-DvaqSAco.js";import"./vue-datepicker-CUbRHf9G.js";import"./dayjs.min-C3XPfvH9.js";const P={name:"peerJobs",setup(){return{store:u()}},props:{selectedPeer:Object},components:{LocaleText:w,SchedulePeerJob:p,ScheduleDropdown:b},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:m().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"},k={class:"mb-0 fw-normal"},j={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",k,[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",j,[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(g,{name:"schedulePeerJobTransition",tag:"div",class:"position-relative"},{default:_(()=>[(o(!0),a(v,null,f(this.selectedPeer.jobs,(s,E)=>(o(),J(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."})])])])):x("",!0)]),_:1})])])])])])}const q=h(P,[["render",O],["__scopeId","data-v-5bbdd42b"]]);export{q as default};
|
||||
import{S as p,a as b}from"./schedulePeerJob-D7M0MV7j.js";import{_ as h,W as u,z as m,k as i,a as o,c as a,b as e,d as r,w as _,F as v,h as f,i as J,e as x,T as g}from"./index-oBQzjt8-.js";import{L as w}from"./localeText-CuybU_0U.js";import"./vue-datepicker-DZRPqFzF.js";import"./dayjs.min-BHDUvWAB.js";const P={name:"peerJobs",setup(){return{store:u()}},props:{selectedPeer:Object},components:{LocaleText:w,SchedulePeerJob:p,ScheduleDropdown:b},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:m().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"},k={class:"mb-0 fw-normal"},j={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",k,[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",j,[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(g,{name:"schedulePeerJobTransition",tag:"div",class:"position-relative"},{default:_(()=>[(o(!0),a(v,null,f(this.selectedPeer.jobs,(s,E)=>(o(),J(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."})])])])):x("",!0)]),_:1})])])])])])}const q=h(P,[["render",O],["__scopeId","data-v-5bbdd42b"]]);export{q as default};
|
||||
+1
-1
@@ -1 +1 @@
|
||||
import{S as _}from"./schedulePeerJob-Rx5QXWIx.js";import{_ as g,W as v,k as c,a as t,c as r,b as e,d as l,F as p,h as b,t as m,e as f,i as y}from"./index-CUmHRwBw.js";import{L as x}from"./localeText-DvaqSAco.js";import"./vue-datepicker-CUbRHf9G.js";import"./dayjs.min-C3XPfvH9.js";const J={name:"peerJobsAllModal",setup(){return{store:v()}},components:{LocaleText:x,SchedulePeerJob:_},props:{configurationPeers:Array[Object]},computed:{getAllJobs(){return this.configurationPeers.filter(a=>a.jobs.length>0)}}},k={class:"peerSettingContainer w-100 h-100 position-absolute top-0 start-0 overflow-y-scroll"},w={class:"container d-flex h-100 w-100"},$={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"},C={class:"card-body px-4 pb-4 pt-2"},P={key:0,class:"accordion",id:"peerJobsLogsModalAccordion"},j={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",k,[e("div",w,[e("div",$,[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",C,[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",P,[(t(!0),r(p,null,b(this.getAllJobs,(s,d)=>(t(),r("div",{class:"accordion-item",key:s.id},[e("h2",j,[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)):f("",!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(),y(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-D7M0MV7j.js";import{_ as g,W as v,k as c,a as t,c as r,b as e,d as l,F as p,h as b,t as m,e as f,i as y}from"./index-oBQzjt8-.js";import{L as x}from"./localeText-CuybU_0U.js";import"./vue-datepicker-DZRPqFzF.js";import"./dayjs.min-BHDUvWAB.js";const J={name:"peerJobsAllModal",setup(){return{store:v()}},components:{LocaleText:x,SchedulePeerJob:_},props:{configurationPeers:Array[Object]},computed:{getAllJobs(){return this.configurationPeers.filter(a=>a.jobs.length>0)}}},k={class:"peerSettingContainer w-100 h-100 position-absolute top-0 start-0 overflow-y-scroll"},w={class:"container d-flex h-100 w-100"},$={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"},C={class:"card-body px-4 pb-4 pt-2"},P={key:0,class:"accordion",id:"peerJobsLogsModalAccordion"},j={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",k,[e("div",w,[e("div",$,[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",C,[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",P,[(t(!0),r(p,null,b(this.getAllJobs,(s,d)=>(t(),r("div",{class:"accordion-item",key:s.id},[e("h2",j,[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)):f("",!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(),y(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};
|
||||
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
@media screen and (max-width: 768px){#qrcode[data-v-7c287bf3]{width:100%!important;height:auto!important;aspect-ratio:1/1}}
|
||||
@@ -0,0 +1 @@
|
||||
import{b as i}from"./browser-CjSdxGTc.js";import{L as c}from"./localeText-CuybU_0U.js";import{_ as l,D as p,g as _,k as m,a as n,c as r,b as e,d as u,n as h,e as f}from"./index-oBQzjt8-.js";const g={name:"peerQRCode",components:{LocaleText:c},props:{selectedPeer:Object},setup(){return{dashboardStore:p()}},data(){return{loading:!0}},mounted(){_("/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};t=btoa(JSON.stringify(a))}else t=o.data.file;i.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"},v={class:"container d-flex h-100 w-100"},C={class:"m-auto modal-dialog-centered dashboardModal justify-content-center"},w={class:"card rounded-3 shadow"},P={class:"card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-0"},x={class:"mb-0"},S={class:"card-body p-4"},y={class:"d-flex"},L={key:0,class:"spinner-border m-auto",role:"status"};function k(o,t,a,N,s,$){const d=m("LocaleText");return n(),r("div",b,[e("div",v,[e("div",C,[e("div",w,[e("div",P,[e("h4",x,[u(d,{t:"QR Code"})]),e("button",{type:"button",class:"btn-close ms-auto",onClick:t[0]||(t[0]=Q=>this.$emit("close"))})]),e("div",S,[e("div",y,[e("canvas",{id:"qrcode",class:h(["rounded-3 shadow animate__animated animate__fadeIn animate__faster",{"d-none":s.loading}])},null,2),s.loading?(n(),r("div",L,t[1]||(t[1]=[e("span",{class:"visually-hidden"},"Loading...",-1)]))):f("",!0)])])])])])])}const q=l(g,[["render",k],["__scopeId","data-v-7c287bf3"]]);export{q as default};
|
||||
@@ -1 +0,0 @@
|
||||
import{b as r}from"./browser-CjSdxGTc.js";import{L as i}from"./localeText-DvaqSAco.js";import{_ as c,D as l,g as p,k as _,a,c as n,b as e,d as m,n as h,e as u}from"./index-CUmHRwBw.js";const f={name:"peerQRCode",components:{LocaleText:i},props:{selectedPeer:Object},setup(){return{dashboardStore:l()}},data(){return{loading:!0}},mounted(){p("/api/downloadPeer/"+this.$route.params.id,{id:this.selectedPeer.id},t=>{this.loading=!1,t.status?r.toCanvas(document.querySelector("#qrcode"),t.data.file,s=>{s&&console.error(s)}):this.dashboardStore.newMessage("Server",t.message,"danger")})}},b={class:"peerSettingContainer w-100 h-100 position-absolute top-0 start-0"},g={class:"container d-flex h-100 w-100"},v={class:"m-auto modal-dialog-centered dashboardModal justify-content-center"},x={class:"card rounded-3 shadow"},C={class:"card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-0"},w={class:"mb-0"},y={class:"card-body p-4"},S={style:{width:"292px",height:"292px"},class:"d-flex"},k={key:0,class:"spinner-border m-auto",role:"status"};function L(t,s,$,q,o,B){const d=_("LocaleText");return a(),n("div",b,[e("div",g,[e("div",v,[e("div",x,[e("div",C,[e("h4",w,[m(d,{t:"QR Code"})]),e("button",{type:"button",class:"btn-close ms-auto",onClick:s[0]||(s[0]=N=>this.$emit("close"))})]),e("div",y,[e("div",S,[e("canvas",{id:"qrcode",class:h(["rounded-3 shadow animate__animated animate__fadeIn animate__faster",{"d-none":o.loading}])},null,2),o.loading?(a(),n("div",k,s[1]||(s[1]=[e("span",{class:"visually-hidden"},"Loading...",-1)]))):u("",!0)])])])])])])}const T=c(f,[["render",L]]);export{T as default};
|
||||
+1
-1
@@ -1 +1 @@
|
||||
import{_ as u,q as m,G as p,r as b,W as f,a2 as h,o as g,a as v,i as y,w as _,b as e,m as x,y as w,d as S,j as B}from"./index-CUmHRwBw.js";import{L as T}from"./localeText-DvaqSAco.js";const C={class:"fixed-bottom w-100 bottom-0 z-2",style:{"z-index":"1"}},P={class:"container-fluid"},k={class:"row g-0"},L={class:"col-md-9 col-lg-10 d-flex justify-content-center py-2"},V={class:"rounded-3 p-2 border shadow searchPeersContainer bg-body-tertiary"},j={class:"d-flex gap-1 align-items-center px-2"},z=["placeholder"],D={__name:"peerSearchBar",emits:["close"],setup(G,{emit:n}){const l=m(()=>p("Search Peers..."));let t;const o=b(""),r=f(),i=()=>{t?(clearTimeout(t),t=setTimeout(()=>{r.searchString=o.value},300)):t=setTimeout(()=>{r.searchString=o.value},300)},d=n,c=h("searchBar");return g(()=>{c.value.focus()}),(M,s)=>(v(),y(B,{name:"slideUp",appear:"",type:"animation",style:{"animation-delay":"1s"}},{default:_(()=>[e("div",C,[e("div",P,[e("div",k,[s[5]||(s[5]=e("div",{class:"col-md-3 col-lg-2"},null,-1)),e("div",L,[e("div",V,[e("div",j,[s[4]||(s[4]=e("h6",{class:"mb-0 me-2"},[e("label",{for:"searchPeers"},[e("i",{class:"bi bi-search"})])],-1)),x(e("input",{ref:"searchBar",class:"flex-grow-1 form-control rounded-3 bg-secondary-subtle border-1 border-secondary-subtle",placeholder:l.value,id:"searchPeers",onKeyup:s[0]||(s[0]=a=>i()),"onUpdate:modelValue":s[1]||(s[1]=a=>o.value=a)},null,40,z),[[w,o.value]]),e("button",{onClick:s[2]||(s[2]=a=>d("close")),style:{"white-space":"nowrap"},class:"btn bg-secondary-subtle text-secondary-emphasis border-secondary-subtle rounded-3 d-flex align-items-center"},[e("span",null,[s[3]||(s[3]=e("i",{class:"bi bi-x-circle-fill me-2"},null,-1)),S(T,{t:"Done"})])])])])])])])])]),_:1}))}},W=u(D,[["__scopeId","data-v-b741afe7"]]);export{W as default};
|
||||
import{_ as u,q as m,G as p,r as b,W as f,a2 as h,o as g,a as v,i as y,w as _,b as e,m as x,y as w,d as S,j as B}from"./index-oBQzjt8-.js";import{L as T}from"./localeText-CuybU_0U.js";const C={class:"fixed-bottom w-100 bottom-0 z-2",style:{"z-index":"1"}},P={class:"container-fluid"},k={class:"row g-0"},L={class:"col-md-9 col-lg-10 d-flex justify-content-center py-2"},V={class:"rounded-3 p-2 border shadow searchPeersContainer bg-body-tertiary"},j={class:"d-flex gap-1 align-items-center px-2"},z=["placeholder"],D={__name:"peerSearchBar",emits:["close"],setup(G,{emit:n}){const l=m(()=>p("Search Peers..."));let t;const o=b(""),r=f(),i=()=>{t?(clearTimeout(t),t=setTimeout(()=>{r.searchString=o.value},300)):t=setTimeout(()=>{r.searchString=o.value},300)},d=n,c=h("searchBar");return g(()=>{c.value.focus()}),(M,s)=>(v(),y(B,{name:"slideUp",appear:"",type:"animation",style:{"animation-delay":"1s"}},{default:_(()=>[e("div",C,[e("div",P,[e("div",k,[s[5]||(s[5]=e("div",{class:"col-md-3 col-lg-2"},null,-1)),e("div",L,[e("div",V,[e("div",j,[s[4]||(s[4]=e("h6",{class:"mb-0 me-2"},[e("label",{for:"searchPeers"},[e("i",{class:"bi bi-search"})])],-1)),x(e("input",{ref:"searchBar",class:"flex-grow-1 form-control rounded-3 bg-secondary-subtle border-1 border-secondary-subtle",placeholder:l.value,id:"searchPeers",onKeyup:s[0]||(s[0]=a=>i()),"onUpdate:modelValue":s[1]||(s[1]=a=>o.value=a)},null,40,z),[[w,o.value]]),e("button",{onClick:s[2]||(s[2]=a=>d("close")),style:{"white-space":"nowrap"},class:"btn bg-secondary-subtle text-secondary-emphasis border-secondary-subtle rounded-3 d-flex align-items-center"},[e("span",null,[s[3]||(s[3]=e("i",{class:"bi bi-x-circle-fill me-2"},null,-1)),S(T,{t:"Done"})])])])])])])])])]),_:1}))}},W=u(D,[["__scopeId","data-v-b741afe7"]]);export{W as default};
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
.toggleShowKey[data-v-12b3ae8e]{position:absolute;top:35px;right:12px}
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
.toggleShowKey[data-v-2166fcf9]{position:absolute;top:35px;right:12px}
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
||||
import{L as r}from"./localeText-DvaqSAco.js";import{a as t,c as n,f as i,i as s,e as a}from"./index-CUmHRwBw.js";const d={key:0,class:"badge wireguardBg rounded-3 shadow"},c={key:1,class:"badge amneziawgBg rounded-3 shadow"},u={__name:"protocolBadge",props:{protocol:String,mini:!1},setup(e){return(m,o)=>e.protocol==="wg"?(t(),n("span",d,[o[0]||(o[0]=i(" WireGuard ")),e.mini?a("",!0):(t(),s(r,{key:0,t:"Configuration"}))])):e.protocol==="awg"?(t(),n("span",c,[o[1]||(o[1]=i(" AmneziaWG ")),e.mini?a("",!0):(t(),s(r,{key:0,t:"Configuration"}))])):a("",!0)}};export{u as _};
|
||||
import{L as r}from"./localeText-CuybU_0U.js";import{a as t,c as n,f as i,i as s,e as a}from"./index-oBQzjt8-.js";const d={key:0,class:"badge wireguardBg rounded-3 shadow"},c={key:1,class:"badge amneziawgBg rounded-3 shadow"},u={__name:"protocolBadge",props:{protocol:String,mini:!1},setup(e){return(m,o)=>e.protocol==="wg"?(t(),n("span",d,[o[0]||(o[0]=i(" WireGuard ")),e.mini?a("",!0):(t(),s(r,{key:0,t:"Configuration"}))])):e.protocol==="awg"?(t(),n("span",c,[o[1]||(o[1]=i(" AmneziaWG ")),e.mini?a("",!0):(t(),s(r,{key:0,t:"Configuration"}))])):a("",!0)}};export{u as _};
|
||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
.btn.disabled[data-v-6a5aba2a]{opacity:1;background-color:#0d6efd17;border-color:transparent}[data-v-8f3f1b93]{font-size:.875rem}input[data-v-8f3f1b93]{padding:.1rem .4rem}input[data-v-8f3f1b93]:disabled{border-color:transparent;background-color:#0d6efd17;color:#0d6efd}.dp__main[data-v-8f3f1b93]{width:auto;flex-grow:1;--dp-input-padding: 2.5px 30px 2.5px 12px;--dp-border-radius: .5rem}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
.btn.disabled[data-v-6a5aba2a]{opacity:1;background-color:#0d6efd17;border-color:transparent}[data-v-4aa63a3e]{font-size:.875rem}input[data-v-4aa63a3e]{padding:.1rem .4rem}input[data-v-4aa63a3e]:disabled{border-color:transparent;background-color:#0d6efd17;color:#0d6efd}.dp__main[data-v-4aa63a3e]{width:auto;flex-grow:1;--dp-input-padding: 2.5px 30px 2.5px 12px;--dp-border-radius: .5rem}
|
||||
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -1 +1 @@
|
||||
import{_ as u,D as m,A as p,c as r,b as e,d as o,f as c,t as h,e as f,m as l,y as d,a as i,k as w}from"./index-CUmHRwBw.js";import{L as g}from"./localeText-DvaqSAco.js";const b={name:"setup",components:{LocaleText:g},setup(){return{store:m()}},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,p("/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"},A={for:"confirmPassword",class:"mb-1 text-muted"},$=["disabled"],q={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=w("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]=c(" 😊"))]),e("div",null,[e("h3",null,[o(t,{t:"Create an account"})]),this.errorMessage?(i(),r("div",P,h(this.errorMessage),1)):f("",!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",A,[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",q,[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,$)])])])],8,_)}const j=u(b,[["render",B]]);export{j as default};
|
||||
import{_ as u,D as m,A as p,c as r,b as e,d as o,f as c,t as h,e as f,m as l,y as d,a as i,k as w}from"./index-oBQzjt8-.js";import{L as g}from"./localeText-CuybU_0U.js";const b={name:"setup",components:{LocaleText:g},setup(){return{store:m()}},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,p("/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"},A={for:"confirmPassword",class:"mb-1 text-muted"},$=["disabled"],q={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=w("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]=c(" 😊"))]),e("div",null,[e("h3",null,[o(t,{t:"Create an account"})]),this.errorMessage?(i(),r("div",P,h(this.errorMessage),1)):f("",!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",A,[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",q,[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,$)])])])],8,_)}const j=u(b,[["render",B]]);export{j as default};
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
import{_,r,D as p,g as u,c as m,b as t,d as c,J as h,a as f,k as b}from"./index-CUmHRwBw.js";import{b as v}from"./browser-CjSdxGTc.js";import{L as y}from"./localeText-DvaqSAco.js";const g={name:"share",components:{LocaleText:y},async setup(){const o=h(),e=r(!1),i=p(),n=r(""),s=r(void 0),l=r(new Blob);await u("/api/getDashboardTheme",{},d=>{n.value=d.data});const a=o.query.ShareID;return a===void 0||a.length===0?(s.value=void 0,e.value=!0):await u("/api/sharePeer/get",{ShareID:a},d=>{d.status?(s.value=d.data,l.value=new Blob([s.value.file],{type:"text/plain"})):s.value=void 0,e.value=!0}),{store:i,theme:n,peerConfiguration:s,blob:l}},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),i=`${this.peerConfiguration.fileName}.conf`,n=document.createElement("a");n.href=e,n.download=i,n.click()}},computed:{getBlob(){return URL.createObjectURL(this.blob)}}},w=["data-bs-theme"],x={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"}},I={class:"m-auto"},L={key:1,class:"d-flex align-items-center flex-column gap-3"},k={class:"h1 dashboardLogo text-center animate__animated animate__fadeInUp"},B={id:"qrcode",class:"rounded-3 shadow animate__animated animate__fadeInUp mb-3",ref:"qrcode"},D={class:"text-muted animate__animated animate__fadeInUp mb-1",style:{"animation-delay":"0.2s"}},R=["download","href"];function q(o,e,i,n,s,l){const a=b("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",x,[this.peerConfiguration?(f(),m("div",L,[t("div",k,[e[1]||(e[1]=t("h6",null,"WGDashboard",-1)),c(a,{t:"Scan QR Code with the WireGuard App to add peer"})]),t("canvas",B,null,512),t("p",D,[c(a,{t:"or click the button below to download the "}),e[2]||(e[2]=t("samp",null,".conf",-1)),c(a,{t:" file"})]),t("a",{download:this.peerConfiguration.fileName+".conf",href:l.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,R)])):(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",I,[c(a,{t:"Oh no... This link is either expired or invalid."})])])]))])],8,w)}const N=_(g,[["render",q],["__scopeId","data-v-1b44aacd"]]);export{N as default};
|
||||
import{_,r,D as p,g as u,c as m,b as t,d as c,J as h,a as f,k as b}from"./index-oBQzjt8-.js";import{b as v}from"./browser-CjSdxGTc.js";import{L as y}from"./localeText-CuybU_0U.js";const g={name:"share",components:{LocaleText:y},async setup(){const o=h(),e=r(!1),i=p(),n=r(""),s=r(void 0),l=r(new Blob);await u("/api/getDashboardTheme",{},d=>{n.value=d.data});const a=o.query.ShareID;return a===void 0||a.length===0?(s.value=void 0,e.value=!0):await u("/api/sharePeer/get",{ShareID:a},d=>{d.status?(s.value=d.data,l.value=new Blob([s.value.file],{type:"text/plain"})):s.value=void 0,e.value=!0}),{store:i,theme:n,peerConfiguration:s,blob:l}},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),i=`${this.peerConfiguration.fileName}.conf`,n=document.createElement("a");n.href=e,n.download=i,n.click()}},computed:{getBlob(){return URL.createObjectURL(this.blob)}}},w=["data-bs-theme"],x={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"}},I={class:"m-auto"},L={key:1,class:"d-flex align-items-center flex-column gap-3"},k={class:"h1 dashboardLogo text-center animate__animated animate__fadeInUp"},B={id:"qrcode",class:"rounded-3 shadow animate__animated animate__fadeInUp mb-3",ref:"qrcode"},D={class:"text-muted animate__animated animate__fadeInUp mb-1",style:{"animation-delay":"0.2s"}},R=["download","href"];function q(o,e,i,n,s,l){const a=b("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",x,[this.peerConfiguration?(f(),m("div",L,[t("div",k,[e[1]||(e[1]=t("h6",null,"WGDashboard",-1)),c(a,{t:"Scan QR Code with the WireGuard App to add peer"})]),t("canvas",B,null,512),t("p",D,[c(a,{t:"or click the button below to download the "}),e[2]||(e[2]=t("samp",null,".conf",-1)),c(a,{t:" file"})]),t("a",{download:this.peerConfiguration.fileName+".conf",href:l.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,R)])):(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",I,[c(a,{t:"Oh no... This link is either expired or invalid."})])])]))])],8,w)}const N=_(g,[["render",q],["__scopeId","data-v-1b44aacd"]]);export{N as default};
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
.square[data-v-2ad535bb]{height:var(--2ec4d3bc);transition:background-color .5s cubic-bezier(.42,0,.22,1)}.square[data-v-9509d7a0]{height:var(--2dc8ab7e);transition:background-color .5s cubic-bezier(.42,0,.22,1)}
|
||||
@@ -1 +0,0 @@
|
||||
.square[data-v-70102637]{height:var(--e901480c);transition:background-color .5s cubic-bezier(.42,0,.22,1)}.floatingLabel[data-v-70102637]{top:40px}.square[data-v-a382214a]{height:var(--38705f32);transition:background-color .5s cubic-bezier(.42,0,.22,1)}.floatingLabel[data-v-a382214a]{top:var(--38705f32)}
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
import{_ as b,p as m,r as p,q as v,a as t,c as r,d as g,w as x,s as n,n as f,b as l,t as d,e as C,j as w}from"./index-oBQzjt8-.js";const y={class:"text-muted me-2"},_={class:"fw-bold"},k={__name:"cpuCore",props:{core_number:Number,percentage:Number,align:Boolean,square:Boolean},setup(e){m(c=>({"2ec4d3bc":o.value}));const u=e,s=p(!1),o=v(()=>u.square?"40px":"25px");return(c,a)=>(t(),r("div",{class:"flex-grow-1 square rounded-3 border position-relative p-2",onMouseenter:a[0]||(a[0]=i=>s.value=!0),onMouseleave:a[1]||(a[1]=i=>s.value=!1),style:n({"background-color":`rgb(13 110 253 / ${e.percentage*10}%)`})},[g(w,{name:"zoomReversed"},{default:x(()=>[s.value?(t(),r("div",{key:0,style:n([{"white-space":"nowrap"},{top:o.value}]),class:f(["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"]])},[l("small",y," Core #"+d(e.core_number+1),1),l("small",_,d(e.percentage)+"% ",1)],6)):C("",!0)]),_:1})],36))}},B=b(k,[["__scopeId","data-v-2ad535bb"]]);export{B as C};
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
import{_ as i,p as m,r as p,q as b,a as o,c as t,d as g,w as v,n as x,b as r,t as n,e as f,j as C,s as w}from"./index-CUmHRwBw.js";const y={class:"text-muted me-2"},_={class:"fw-bold"},k={__name:"cpuCore",props:{core_number:Number,percentage:Number,align:Boolean,square:Boolean},setup(e){m(c=>({e901480c:u.value}));const l=e,a=p(!1),u=b(()=>l.square?"40px":"25px");return(c,s)=>(o(),t("div",{class:"flex-grow-1 square rounded-3 border position-relative p-2",onMouseenter:s[0]||(s[0]=d=>a.value=!0),onMouseleave:s[1]||(s[1]=d=>a.value=!1),style:w({"background-color":`rgb(13 110 253 / ${e.percentage*10}%)`})},[g(C,{name:"zoomReversed"},{default:v(()=>[a.value?(o(),t("div",{key:0,style:{"white-space":"nowrap"},class:x(["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"]])},[r("small",y," Core #"+n(e.core_number+1),1),r("small",_,n(e.percentage)+"% ",1)],2)):f("",!0)]),_:1})],36))}},B=i(k,[["__scopeId","data-v-70102637"]]);export{B as C};
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
||||
import{_ as h,D as m,g as p,A as f,c as b,b as t,d as i,t as _,m as v,y as g,i as d,w as r,k as c,a as n}from"./index-CUmHRwBw.js";import{b as x}from"./browser-CjSdxGTc.js";import{L as y}from"./localeText-DvaqSAco.js";const T={name:"totp",components:{LocaleText:y},async setup(){const s=m();let e="";return await p("/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)?f("/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"],w={class:"m-auto text-body",style:{width:"500px"}},L={class:"d-flex flex-column"},M={class:"dashboardLogo display-4"},C={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"}},A={for:"totp",class:"mb-2"},D={class:"text-muted"},S={class:"form-group mb-2"},q=["disabled"],E={class:"invalid-feedback"},F={class:"valid-feedback"},R={class:"d-flex gap-3 mt-5 flex-column"};function G(s,e,a,N,W,Q){const o=c("LocaleText"),l=c("RouterLink");return n(),b("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",w,[t("div",L,[t("div",null,[t("h1",M,[i(o,{t:"Multi-Factor Authentication (MFA)"})]),t("p",C,[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",$,_(this.l),1)],8,B)]),t("label",A,[t("small",D,[i(o,{t:"2. Enter the TOTP generated by your authenticator to verify"})])]),t("div",S,[v(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),[[g,this.totp]]),t("div",E,[i(o,{t:this.totpInvalidMessage},null,8,["t"])]),t("div",F,[i(o,{t:"TOTP verified!"})])])]),e[4]||(e[4]=t("hr",null,null,-1)),t("div",R,[this.verified?(n(),d(l,{key:1,to:"/",class:"btn btn-dark btn-lg d-flex btn-brand shadow align-items-center flex-grow-1 rounded-3"},{default:r(()=>[i(o,{t:"Complete"}),e[3]||(e[3]=t("i",{class:"bi bi-chevron-right ms-auto"},null,-1))]),_:1})):(n(),d(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:r(()=>[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 z=h(T,[["render",G]]);export{z as default};
|
||||
import{_ as h,D as m,g as p,A as f,c as b,b as t,d as i,t as _,m as v,y as g,i as d,w as r,k as c,a as n}from"./index-oBQzjt8-.js";import{b as x}from"./browser-CjSdxGTc.js";import{L as y}from"./localeText-CuybU_0U.js";const T={name:"totp",components:{LocaleText:y},async setup(){const s=m();let e="";return await p("/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)?f("/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"],w={class:"m-auto text-body",style:{width:"500px"}},L={class:"d-flex flex-column"},M={class:"dashboardLogo display-4"},C={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"}},A={for:"totp",class:"mb-2"},D={class:"text-muted"},S={class:"form-group mb-2"},q=["disabled"],E={class:"invalid-feedback"},F={class:"valid-feedback"},R={class:"d-flex gap-3 mt-5 flex-column"};function G(s,e,a,N,W,Q){const o=c("LocaleText"),l=c("RouterLink");return n(),b("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",w,[t("div",L,[t("div",null,[t("h1",M,[i(o,{t:"Multi-Factor Authentication (MFA)"})]),t("p",C,[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",$,_(this.l),1)],8,B)]),t("label",A,[t("small",D,[i(o,{t:"2. Enter the TOTP generated by your authenticator to verify"})])]),t("div",S,[v(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),[[g,this.totp]]),t("div",E,[i(o,{t:this.totpInvalidMessage},null,8,["t"])]),t("div",F,[i(o,{t:"TOTP verified!"})])])]),e[4]||(e[4]=t("hr",null,null,-1)),t("div",R,[this.verified?(n(),d(l,{key:1,to:"/",class:"btn btn-dark btn-lg d-flex btn-brand shadow align-items-center flex-grow-1 rounded-3"},{default:r(()=>[i(o,{t:"Complete"}),e[3]||(e[3]=t("i",{class:"bi bi-chevron-right ms-auto"},null,-1))]),_:1})):(n(),d(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:r(()=>[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 z=h(T,[["render",G]]);export{z as default};
|
||||
+1
-1
@@ -1 +1 @@
|
||||
import{_ as h,W as g,g as b,c as o,b as t,d as n,m as y,y as f,C as x,w as r,j as c,a as l,f as v,F as u,h as m,n as k,s as T,t as i,k as _}from"./index-CUmHRwBw.js";import{O as A}from"./osmap-C861OkPV.js";import{L as w}from"./localeText-DvaqSAco.js";const R={name:"traceroute",components:{LocaleText:w,OSMap:A},data(){return{tracing:!1,ipAddress:void 0,tracerouteResult:void 0}},setup(){return{store:g()}},methods:{execute(){this.ipAddress&&(this.tracing=!0,this.tracerouteResult=void 0,b("/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"},C={class:"d-flex gap-2 mb-3 flex-column"},L={class:"flex-grow-1"},P={class:"mb-1 text-muted",for:"ipAddress"},O=["disabled"],V=["disabled"],B={key:0,class:"d-block"},I={key:1,class:"d-block"},N={class:"position-relative"},z={key:"pingPlaceholder"},D={key:1},E={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"},j={scope:"col"},U={scope:"col"},q={key:0},J={key:1};function Q(d,s,X,Y,Z,tt){const a=_("LocaleText"),p=_("OSMap");return l(),o("div",M,[t("div",S,[t("h3",$,[n(a,{t:"Traceroute"})]),t("div",C,[t("div",L,[t("label",P,[t("small",null,[n(a,{t:"Enter IP Address / Hostname"})])]),y(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]=x(e=>this.execute(),["enter"])),type:"text"},null,40,O),[[f,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(c,{name:"slide"},{default:r(()=>[this.tracing?(l(),o("span",I,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})],8,V)]),t("div",N,[n(c,{name:"ping"},{default:r(()=>[this.tracerouteResult?(l(),o("div",D,[n(p,{d:this.tracerouteResult,type:"traceroute"},null,8,["d"]),t("div",E,[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",j,[n(a,{t:"Max RTT (ms)"})]),t("th",U,[n(a,{t:"Geolocation"})])])]),t("tbody",null,[(l(!0),o(u,null,m(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.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",z,[s[5]||(s[5]=t("div",{class:"pingPlaceholder bg-body-secondary rounded-3 mb-3",style:{height:"300px !important"}},null,-1)),(l(),o(u,null,m(5,e=>t("div",{class:k(["pingPlaceholder bg-body-secondary rounded-3 mb-3",{"animate__animated animate__flash animate__slower animate__infinite":this.tracing}]),style:T({"animation-delay":`${e*.05}s`})},null,6)),64))]))]),_:1})])])])}const lt=h(R,[["render",Q],["__scopeId","data-v-3e75b4d4"]]);export{lt as default};
|
||||
import{_ as h,W as g,g as b,c as o,b as t,d as n,m as y,y as f,C as x,w as r,j as c,a as l,f as v,F as u,h as m,n as k,s as T,t as i,k as _}from"./index-oBQzjt8-.js";import{O as A}from"./osmap-DL0KYfmh.js";import{L as w}from"./localeText-CuybU_0U.js";const R={name:"traceroute",components:{LocaleText:w,OSMap:A},data(){return{tracing:!1,ipAddress:void 0,tracerouteResult:void 0}},setup(){return{store:g()}},methods:{execute(){this.ipAddress&&(this.tracing=!0,this.tracerouteResult=void 0,b("/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"},C={class:"d-flex gap-2 mb-3 flex-column"},L={class:"flex-grow-1"},P={class:"mb-1 text-muted",for:"ipAddress"},O=["disabled"],V=["disabled"],B={key:0,class:"d-block"},I={key:1,class:"d-block"},N={class:"position-relative"},z={key:"pingPlaceholder"},D={key:1},E={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"},j={scope:"col"},U={scope:"col"},q={key:0},J={key:1};function Q(d,s,X,Y,Z,tt){const a=_("LocaleText"),p=_("OSMap");return l(),o("div",M,[t("div",S,[t("h3",$,[n(a,{t:"Traceroute"})]),t("div",C,[t("div",L,[t("label",P,[t("small",null,[n(a,{t:"Enter IP Address / Hostname"})])]),y(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]=x(e=>this.execute(),["enter"])),type:"text"},null,40,O),[[f,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(c,{name:"slide"},{default:r(()=>[this.tracing?(l(),o("span",I,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})],8,V)]),t("div",N,[n(c,{name:"ping"},{default:r(()=>[this.tracerouteResult?(l(),o("div",D,[n(p,{d:this.tracerouteResult,type:"traceroute"},null,8,["d"]),t("div",E,[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",j,[n(a,{t:"Max RTT (ms)"})]),t("th",U,[n(a,{t:"Geolocation"})])])]),t("tbody",null,[(l(!0),o(u,null,m(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.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",z,[s[5]||(s[5]=t("div",{class:"pingPlaceholder bg-body-secondary rounded-3 mb-3",style:{height:"300px !important"}},null,-1)),(l(),o(u,null,m(5,e=>t("div",{class:k(["pingPlaceholder bg-body-secondary rounded-3 mb-3",{"animate__animated animate__flash animate__slower animate__infinite":this.tracing}]),style:T({"animation-delay":`${e*.05}s`})},null,6)),64))]))]),_:1})])])])}const lt=h(R,[["render",Q],["__scopeId","data-v-3e75b4d4"]]);export{lt as default};
|
||||
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -10,7 +10,7 @@
|
||||
<link rel="icon" href="/static/app/dist/img/Logo-2-512x512.png">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>WGDashboard</title>
|
||||
<script type="module" crossorigin src="/static/app/dist/assets/index-CUmHRwBw.js"></script>
|
||||
<script type="module" crossorigin src="/static/app/dist/assets/index-oBQzjt8-.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/static/app/dist/assets/index-DFl-XeJT.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "app",
|
||||
"version": "4.2.0",
|
||||
"version": "4.2.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "app",
|
||||
"version": "4.2.0",
|
||||
"version": "4.2.3",
|
||||
"dependencies": {
|
||||
"@vue/language-server": "^2.1.10",
|
||||
"@vuepic/vue-datepicker": "^9.0.1",
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"name": "app",
|
||||
"version": "4.2.0",
|
||||
"version": "4.2.5",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"buildcommitpush": "./build.sh",
|
||||
"build electron": "vite build && vite build --mode electron && cd ../../../../WGDashboard-Desktop && electron-builder --mac --win",
|
||||
"build electron": "vite build && vite build --mode electron && cd ../../../../WGDashboard-Desktop && /opt/homebrew/bin/npm run \"electron dist\"",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -36,7 +36,7 @@ const resetForm = () => {
|
||||
dataChanged.value = false;
|
||||
Object.assign(data, JSON.parse(JSON.stringify(props.configurationInfo)))
|
||||
}
|
||||
const emit = defineEmits(["changed", "close", "refresh"])
|
||||
const emit = defineEmits(["changed", "close", "refresh", "dataChanged"])
|
||||
const saveForm = () => {
|
||||
saving.value = true
|
||||
fetchPost("/api/updateWireguardConfiguration", data, (res) => {
|
||||
@@ -63,179 +63,201 @@ const editRawConfigurationFileModal = ref(false)
|
||||
const backupRestoreModal = ref(false)
|
||||
const deleteConfigurationModal = ref(false)
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="peerSettingContainer w-100 h-100 position-absolute top-0 start-0 overflow-y-scroll" ref="editConfigurationContainer">
|
||||
<TransitionGroup name="zoom">
|
||||
<EditRawConfigurationFile
|
||||
name="EditRawConfigurationFile"
|
||||
v-if="editRawConfigurationFileModal"
|
||||
@close="editRawConfigurationFileModal = false">
|
||||
</EditRawConfigurationFile>
|
||||
<DeleteConfiguration
|
||||
key="DeleteConfiguration"
|
||||
@backup="backupRestoreModal = true"
|
||||
@close="deleteConfigurationModal = false"
|
||||
v-if="deleteConfigurationModal">
|
||||
</DeleteConfiguration>
|
||||
<ConfigurationBackupRestore
|
||||
@close="backupRestoreModal = false"
|
||||
@refreshPeersList="emit('refresh')"
|
||||
v-if="backupRestoreModal">
|
||||
</ConfigurationBackupRestore>
|
||||
</TransitionGroup>
|
||||
|
||||
<div class="container d-flex h-100 w-100">
|
||||
<div class="m-auto modal-dialog-centered dashboardModal" style="width: 700px">
|
||||
<div class="card rounded-3 shadow flex-grow-1">
|
||||
<div class="card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4">
|
||||
<h4 class="mb-0">
|
||||
<LocaleText t="Configuration Settings"></LocaleText>
|
||||
</h4>
|
||||
<button type="button" class="btn-close ms-auto" @click="$emit('close')"></button>
|
||||
</div>
|
||||
<div class="card-body px-4 pb-4">
|
||||
<div class="d-flex gap-2 flex-column">
|
||||
<div class="d-flex align-items-center gap-3" v-if="!updateConfigurationName">
|
||||
<small class="text-muted">
|
||||
<LocaleText t="Name"></LocaleText>
|
||||
</small>
|
||||
<small>{{data.Name}}</small>
|
||||
<button
|
||||
@click="updateConfigurationName = true"
|
||||
class="btn btn-sm bg-danger-subtle border-danger-subtle text-danger-emphasis rounded-3 ms-auto">
|
||||
<LocaleText t="Update Name"></LocaleText>
|
||||
</button>
|
||||
</div>
|
||||
<UpdateConfigurationName
|
||||
@close="updateConfigurationName = false"
|
||||
:configuration-name="data.Name"
|
||||
v-if="updateConfigurationName"></UpdateConfigurationName>
|
||||
|
||||
<template v-else>
|
||||
<hr>
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<small class="text-muted" style="word-break: keep-all">
|
||||
<LocaleText t="Public Key"></LocaleText>
|
||||
</small>
|
||||
<small class="ms-auto" style="word-break: break-all">
|
||||
{{data.PublicKey}}
|
||||
<div class="peerSettingContainer w-100 h-100 position-absolute top-0 start-0" ref="editConfigurationContainer">
|
||||
<div class="w-100 h-100 overflow-y-scroll">
|
||||
<TransitionGroup name="zoom">
|
||||
<EditRawConfigurationFile
|
||||
name="EditRawConfigurationFile"
|
||||
v-if="editRawConfigurationFileModal"
|
||||
@close="editRawConfigurationFileModal = false">
|
||||
</EditRawConfigurationFile>
|
||||
<DeleteConfiguration
|
||||
key="DeleteConfiguration"
|
||||
@backup="backupRestoreModal = true"
|
||||
@close="deleteConfigurationModal = false"
|
||||
v-if="deleteConfigurationModal">
|
||||
</DeleteConfiguration>
|
||||
<ConfigurationBackupRestore
|
||||
@close="backupRestoreModal = false"
|
||||
@refreshPeersList="emit('refresh')"
|
||||
v-if="backupRestoreModal">
|
||||
</ConfigurationBackupRestore>
|
||||
</TransitionGroup>
|
||||
|
||||
<div class="container d-flex h-100 w-100">
|
||||
<div class="m-auto modal-dialog-centered dashboardModal" style="width: 700px">
|
||||
<div class="card rounded-3 shadow flex-grow-1">
|
||||
<div class="card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4">
|
||||
<h4 class="mb-0">
|
||||
<LocaleText t="Configuration Settings"></LocaleText>
|
||||
</h4>
|
||||
<button type="button" class="btn-close ms-auto" @click="$emit('close')"></button>
|
||||
</div>
|
||||
<div class="card-body px-4 pb-4">
|
||||
<div class="d-flex gap-2 flex-column">
|
||||
<div class="d-flex align-items-center gap-3" v-if="!updateConfigurationName">
|
||||
<small class="text-muted">
|
||||
<LocaleText t="Name"></LocaleText>
|
||||
</small>
|
||||
<small>{{data.Name}}</small>
|
||||
<button
|
||||
@click="updateConfigurationName = true"
|
||||
class="btn btn-sm bg-danger-subtle border-danger-subtle text-danger-emphasis rounded-3 ms-auto">
|
||||
<LocaleText t="Update Name"></LocaleText>
|
||||
</button>
|
||||
</div>
|
||||
<hr>
|
||||
<div>
|
||||
<div class="d-flex">
|
||||
<label for="configuration_private_key" class="form-label">
|
||||
<small class="text-muted d-block">
|
||||
<LocaleText t="Private Key"></LocaleText>
|
||||
<UpdateConfigurationName
|
||||
@close="updateConfigurationName = false"
|
||||
:configuration-name="data.Name"
|
||||
v-if="updateConfigurationName"></UpdateConfigurationName>
|
||||
|
||||
<template v-else>
|
||||
<hr>
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<small class="text-muted" style="word-break: keep-all">
|
||||
<LocaleText t="Public Key"></LocaleText>
|
||||
</small>
|
||||
<small class="ms-auto" style="word-break: break-all">
|
||||
{{data.PublicKey}}
|
||||
</small>
|
||||
</div>
|
||||
<hr>
|
||||
<div>
|
||||
<div class="d-flex">
|
||||
<label for="configuration_private_key" class="form-label">
|
||||
<small class="text-muted d-block">
|
||||
<LocaleText t="Private Key"></LocaleText>
|
||||
</small>
|
||||
</label>
|
||||
<div class="form-check form-switch ms-auto">
|
||||
<input class="form-check-input"
|
||||
type="checkbox" role="switch" id="editPrivateKeySwitch"
|
||||
v-model="editPrivateKey"
|
||||
>
|
||||
<label class="form-check-label" for="editPrivateKeySwitch">
|
||||
<small>Edit</small>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<input type="text" class="form-control form-control-sm rounded-3"
|
||||
:disabled="saving || !editPrivateKey"
|
||||
:class="{'is-invalid': !reqField.PrivateKey}"
|
||||
@keyup="genKey()"
|
||||
v-model="data.PrivateKey"
|
||||
id="configuration_private_key">
|
||||
</div>
|
||||
<div>
|
||||
<label for="configuration_ipaddress_cidr" class="form-label">
|
||||
<small class="text-muted">
|
||||
<LocaleText t="IP Address/CIDR"></LocaleText>
|
||||
</small>
|
||||
</label>
|
||||
<div class="form-check form-switch ms-auto">
|
||||
<input class="form-check-input"
|
||||
type="checkbox" role="switch" id="editPrivateKeySwitch"
|
||||
v-model="editPrivateKey"
|
||||
>
|
||||
<label class="form-check-label" for="editPrivateKeySwitch">
|
||||
<small>Edit</small>
|
||||
</label>
|
||||
</div>
|
||||
<input type="text" class="form-control form-control-sm rounded-3"
|
||||
:disabled="saving"
|
||||
v-model="data.Address"
|
||||
id="configuration_ipaddress_cidr">
|
||||
</div>
|
||||
<input type="text" class="form-control form-control-sm rounded-3"
|
||||
:disabled="saving || !editPrivateKey"
|
||||
:class="{'is-invalid': !reqField.PrivateKey}"
|
||||
@keyup="genKey()"
|
||||
v-model="data.PrivateKey"
|
||||
id="configuration_private_key">
|
||||
</div>
|
||||
<div>
|
||||
<label for="configuration_ipaddress_cidr" class="form-label">
|
||||
<small class="text-muted">
|
||||
<LocaleText t="IP Address/CIDR"></LocaleText>
|
||||
</small>
|
||||
</label>
|
||||
<input type="text" class="form-control form-control-sm rounded-3"
|
||||
:disabled="saving"
|
||||
v-model="data.Address"
|
||||
id="configuration_ipaddress_cidr">
|
||||
</div>
|
||||
<div>
|
||||
<label for="configuration_listen_port" class="form-label">
|
||||
<small class="text-muted">
|
||||
<LocaleText t="Listen Port"></LocaleText>
|
||||
</small>
|
||||
</label>
|
||||
<input type="number" class="form-control form-control-sm rounded-3"
|
||||
:disabled="saving"
|
||||
v-model="data.ListenPort"
|
||||
id="configuration_listen_port">
|
||||
<div>
|
||||
<label for="configuration_listen_port" class="form-label">
|
||||
<small class="text-muted">
|
||||
<LocaleText t="Listen Port"></LocaleText>
|
||||
</small>
|
||||
</label>
|
||||
<input type="number" class="form-control form-control-sm rounded-3"
|
||||
:disabled="saving"
|
||||
v-model="data.ListenPort"
|
||||
id="configuration_listen_port">
|
||||
|
||||
</div>
|
||||
<div v-for="key in ['PreUp', 'PreDown', 'PostUp', 'PostDown']">
|
||||
<label :for="'configuration_' + key" class="form-label">
|
||||
<small class="text-muted">
|
||||
<LocaleText :t="key"></LocaleText>
|
||||
</small>
|
||||
</label>
|
||||
<input type="text" class="form-control form-control-sm rounded-3"
|
||||
:disabled="saving"
|
||||
v-model="data[key]"
|
||||
:id="'configuration_' + key">
|
||||
</div>
|
||||
<div v-for="key in ['Jc', 'Jmin', 'Jmax', 'S1', 'S2', 'H1', 'H2', 'H3', 'H4']"
|
||||
v-if="configurationInfo.Protocol === 'awg'">
|
||||
<label :for="'configuration_' + key" class="form-label">
|
||||
<small class="text-muted">
|
||||
<LocaleText :t="key"></LocaleText>
|
||||
</small>
|
||||
</label>
|
||||
<input type="number" class="form-control form-control-sm rounded-3"
|
||||
:disabled="saving"
|
||||
v-model="data[key]"
|
||||
:id="'configuration_' + key">
|
||||
</div>
|
||||
<div class="d-flex align-items-center gap-2 mt-4">
|
||||
<button class="btn bg-secondary-subtle border-secondary-subtle text-secondary-emphasis rounded-3 shadow ms-auto"
|
||||
@click="resetForm()"
|
||||
:disabled="!dataChanged || saving">
|
||||
<i class="bi bi-arrow-clockwise me-2"></i>
|
||||
<LocaleText t="Reset"></LocaleText>
|
||||
</button>
|
||||
<button class="btn bg-primary-subtle border-primary-subtle text-primary-emphasis rounded-3 shadow"
|
||||
:disabled="!dataChanged || saving"
|
||||
@click="saveForm()"
|
||||
>
|
||||
<i class="bi bi-save-fill me-2"></i>
|
||||
<LocaleText t="Save"></LocaleText>
|
||||
</button>
|
||||
</div>
|
||||
<hr>
|
||||
<h5 class="mb-3">
|
||||
<LocaleText t="Danger Zone"></LocaleText>
|
||||
</h5>
|
||||
<div class="d-flex gap-2 flex-column">
|
||||
<button
|
||||
@click="backupRestoreModal = true"
|
||||
class="btn bg-warning-subtle border-warning-subtle text-warning-emphasis rounded-3 text-start d-flex">
|
||||
<i class="bi bi-copy me-auto"></i>
|
||||
<LocaleText t="Backup & Restore"></LocaleText>
|
||||
</button>
|
||||
<button
|
||||
@click="editRawConfigurationFileModal = true"
|
||||
class="btn bg-warning-subtle border-warning-subtle text-warning-emphasis rounded-3 d-flex">
|
||||
<i class="bi bi-pen me-auto"></i>
|
||||
<LocaleText t="Edit Raw Configuration File"></LocaleText>
|
||||
</button>
|
||||
</div>
|
||||
<div class="accordion mt-2" id="editConfigurationOptionalAccordion">
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button collapsed px-3 py-2" type="button" data-bs-toggle="collapse" data-bs-target="#editOptionalAccordionCollapse">
|
||||
<small class="text-muted">
|
||||
<LocaleText t="Optional Settings"></LocaleText>
|
||||
</small>
|
||||
</button>
|
||||
</h2>
|
||||
<div id="editOptionalAccordionCollapse"
|
||||
class="accordion-collapse collapse" data-bs-parent="#editConfigurationOptionalAccordion">
|
||||
<div class="accordion-body d-flex flex-column gap-3">
|
||||
<div v-for="key in ['Table', 'PreUp', 'PreDown', 'PostUp', 'PostDown']">
|
||||
<label :for="'configuration_' + key" class="form-label">
|
||||
<small class="text-muted">
|
||||
<LocaleText :t="key"></LocaleText>
|
||||
</small>
|
||||
</label>
|
||||
<input type="text" class="form-control form-control-sm rounded-3"
|
||||
:disabled="saving"
|
||||
v-model="data[key]"
|
||||
:id="'configuration_' + key">
|
||||
</div>
|
||||
<div v-for="key in ['Jc', 'Jmin', 'Jmax', 'S1', 'S2', 'H1', 'H2', 'H3', 'H4']"
|
||||
v-if="configurationInfo.Protocol === 'awg'">
|
||||
<label :for="'configuration_' + key" class="form-label">
|
||||
<small class="text-muted">
|
||||
<LocaleText :t="key"></LocaleText>
|
||||
</small>
|
||||
</label>
|
||||
<input type="number" class="form-control form-control-sm rounded-3"
|
||||
:disabled="saving"
|
||||
v-model="data[key]"
|
||||
:id="'configuration_' + key">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<button
|
||||
@click="deleteConfigurationModal = true"
|
||||
class="btn bg-danger-subtle border-danger-subtle text-danger-emphasis rounded-3 d-flex mt-4">
|
||||
<i class="bi bi-trash-fill me-auto"></i>
|
||||
<LocaleText t="Delete Configuration"></LocaleText>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<div class="d-flex align-items-center gap-2 mt-4">
|
||||
<button class="btn bg-secondary-subtle border-secondary-subtle text-secondary-emphasis rounded-3 shadow ms-auto"
|
||||
@click="resetForm()"
|
||||
:disabled="!dataChanged || saving">
|
||||
<i class="bi bi-arrow-clockwise me-2"></i>
|
||||
<LocaleText t="Reset"></LocaleText>
|
||||
</button>
|
||||
<button class="btn bg-primary-subtle border-primary-subtle text-primary-emphasis rounded-3 shadow"
|
||||
:disabled="!dataChanged || saving"
|
||||
@click="saveForm()"
|
||||
>
|
||||
<i class="bi bi-save-fill me-2"></i>
|
||||
<LocaleText t="Save"></LocaleText>
|
||||
</button>
|
||||
</div>
|
||||
<hr>
|
||||
<h5 class="mb-3">
|
||||
<LocaleText t="Danger Zone"></LocaleText>
|
||||
</h5>
|
||||
<div class="d-flex gap-2 flex-column">
|
||||
<button
|
||||
@click="backupRestoreModal = true"
|
||||
class="btn bg-warning-subtle border-warning-subtle text-warning-emphasis rounded-3 text-start d-flex">
|
||||
<i class="bi bi-copy me-auto"></i>
|
||||
<LocaleText t="Backup & Restore"></LocaleText>
|
||||
</button>
|
||||
<button
|
||||
@click="editRawConfigurationFileModal = true"
|
||||
class="btn bg-warning-subtle border-warning-subtle text-warning-emphasis rounded-3 d-flex">
|
||||
<i class="bi bi-pen me-auto"></i>
|
||||
<LocaleText t="Edit Raw Configuration File"></LocaleText>
|
||||
</button>
|
||||
|
||||
<button
|
||||
@click="deleteConfigurationModal = true"
|
||||
class="btn bg-danger-subtle border-danger-subtle text-danger-emphasis rounded-3 d-flex mt-4">
|
||||
<i class="bi bi-trash-fill me-auto"></i>
|
||||
<LocaleText t="Delete Configuration"></LocaleText>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -98,15 +98,6 @@ export default {
|
||||
<samp>{{Peer.allowed_ip}}</samp>
|
||||
</small>
|
||||
</div>
|
||||
<div v-if="Peer.advanced_security"
|
||||
:class="{'d-flex gap-2 align-items-center' : dashboardStore.Configuration.Server.dashboard_peer_list_display === 'list'}">
|
||||
<small class="text-muted">
|
||||
<LocaleText t="Advanced Security"></LocaleText>
|
||||
</small>
|
||||
<small class="d-block">
|
||||
<samp>{{Peer.advanced_security}}</samp>
|
||||
</small>
|
||||
</div>
|
||||
<div class="d-flex align-items-end ms-auto">
|
||||
<div class="ms-auto px-2 rounded-3 subMenuBtn"
|
||||
:class="{active: this.subMenuOpened}"
|
||||
|
||||
@@ -102,11 +102,12 @@ watch(() => {
|
||||
<div class="card-body px-4 pb-4">
|
||||
<div class="d-flex flex-column gap-2">
|
||||
<BulkAdd :saving="saving" :data="peerData" :availableIp="availableIp"></BulkAdd>
|
||||
<hr class="mb-0 mt-2">
|
||||
<NameInput :saving="saving" :data="peerData" v-if="!peerData.bulkAdd"></NameInput>
|
||||
<PrivatePublicKeyInput :saving="saving" :data="peerData" v-if="!peerData.bulkAdd"></PrivatePublicKeyInput>
|
||||
<AllowedIPsInput :availableIp="availableIp" :saving="saving" :data="peerData" v-if="!peerData.bulkAdd"></AllowedIPsInput>
|
||||
|
||||
<template v-if="!peerData.bulkAdd">
|
||||
<hr class="mb-0 mt-2">
|
||||
<NameInput :saving="saving" :data="peerData"></NameInput>
|
||||
<PrivatePublicKeyInput :saving="saving" :data="peerData"></PrivatePublicKeyInput>
|
||||
<AllowedIPsInput :availableIp="availableIp" :saving="saving" :data="peerData"></AllowedIPsInput>
|
||||
</template>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="accordion mb-3" id="peerAddModalAccordion">
|
||||
@@ -155,36 +156,6 @@ watch(() => {
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div v-if="getProtocol === 'awg'">
|
||||
<h5>
|
||||
<LocaleText t="AmneziaWG Peer Setting"></LocaleText>
|
||||
</h5>
|
||||
<div >
|
||||
<label class="form-label d-block"><small class="text-muted">
|
||||
<LocaleText t="Advanced Security"></LocaleText>
|
||||
</small></label>
|
||||
|
||||
<div class="btn-group" role="group">
|
||||
<input type="radio" class="btn-check"
|
||||
v-model="peerData.advanced_security"
|
||||
value="on"
|
||||
name="advanced_security_radio" id="advanced_security_on" autocomplete="off">
|
||||
<label class="btn btn-outline-primary btn-sm" for="advanced_security_on">
|
||||
<LocaleText t="On"></LocaleText>
|
||||
</label>
|
||||
|
||||
<input type="radio"
|
||||
v-model="peerData.advanced_security"
|
||||
value="off"
|
||||
class="btn-check" name="advanced_security_radio" id="advanced_security_off" autocomplete="off">
|
||||
<label class="btn btn-outline-primary btn-sm" for="advanced_security_off">
|
||||
<LocaleText t="Off"></LocaleText>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex mt-2">
|
||||
<button class="ms-auto btn btn-dark btn-brand rounded-3 px-3 py-2 shadow"
|
||||
:disabled="!allRequireFieldsFilled || saving"
|
||||
|
||||
@@ -157,35 +157,6 @@ export default {
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div v-if="this.getProtocol === 'awg'">
|
||||
<h5>
|
||||
<LocaleText t="AmneziaWG Peer Setting"></LocaleText>
|
||||
</h5>
|
||||
<div >
|
||||
<label class="form-label d-block"><small class="text-muted">
|
||||
<LocaleText t="Advanced Security"></LocaleText>
|
||||
</small></label>
|
||||
|
||||
<div class="btn-group" role="group">
|
||||
<input type="radio" class="btn-check"
|
||||
v-model="this.data.advanced_security"
|
||||
value="on"
|
||||
name="advanced_security_radio" id="advanced_security_on" autocomplete="off">
|
||||
<label class="btn btn-outline-primary btn-sm" for="advanced_security_on">
|
||||
<LocaleText t="On"></LocaleText>
|
||||
</label>
|
||||
|
||||
<input type="radio"
|
||||
v-model="this.data.advanced_security"
|
||||
value="off"
|
||||
class="btn-check" name="advanced_security_radio" id="advanced_security_off" autocomplete="off">
|
||||
<label class="btn btn-outline-primary btn-sm" for="advanced_security_off">
|
||||
<LocaleText t="Off"></LocaleText>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="d-flex mt-2">
|
||||
<button class="ms-auto btn btn-dark btn-brand rounded-3 px-3 py-2 shadow"
|
||||
:disabled="!this.allRequireFieldsFilled || this.saving"
|
||||
|
||||
@@ -197,7 +197,7 @@ export default {
|
||||
methods:{
|
||||
toggle(){
|
||||
this.configurationToggling = true;
|
||||
fetchGet("/api/toggleWireguardConfiguration/", {
|
||||
fetchGet("/api/toggleWireguardConfiguration", {
|
||||
configurationName: this.configurationInfo.Name
|
||||
}, (res) => {
|
||||
if (res.status){
|
||||
|
||||
@@ -118,7 +118,7 @@ watch(() => {
|
||||
// Toggle Configuration Method =====================================
|
||||
const toggleConfiguration = async () => {
|
||||
configurationToggling.value = true;
|
||||
await fetchGet("/api/toggleWireguardConfiguration/", {
|
||||
await fetchGet("/api/toggleWireguardConfiguration", {
|
||||
configurationName: configurationInfo.value.Name
|
||||
}, (res) => {
|
||||
if (res.status){
|
||||
|
||||
@@ -24,7 +24,29 @@ export default {
|
||||
}, (res) => {
|
||||
this.loading = false;
|
||||
if (res.status){
|
||||
QRCode.toCanvas(document.querySelector("#qrcode"), res.data.file, (error) => {
|
||||
let data = ""
|
||||
if (this.selectedPeer.configuration.Protocol === "awg"){
|
||||
let awgQRCodeObject = {
|
||||
containers: [
|
||||
{
|
||||
awg: {
|
||||
isThirdPartyConfig: true,
|
||||
last_config: res.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
|
||||
}
|
||||
data = btoa(JSON.stringify(awgQRCodeObject))
|
||||
}else{
|
||||
data = res.data.file
|
||||
}
|
||||
QRCode.toCanvas(document.querySelector("#qrcode"), data, (error) => {
|
||||
if (error) console.error(error)
|
||||
})
|
||||
}else{
|
||||
@@ -47,8 +69,10 @@ export default {
|
||||
<button type="button" class="btn-close ms-auto" @click="this.$emit('close')"></button>
|
||||
</div>
|
||||
<div class="card-body p-4">
|
||||
<div style="width: 292px; height: 292px;" class="d-flex">
|
||||
<canvas id="qrcode" class="rounded-3 shadow animate__animated animate__fadeIn animate__faster" :class="{'d-none': loading}"></canvas>
|
||||
<div class="d-flex">
|
||||
<canvas id="qrcode" class="rounded-3 shadow animate__animated animate__fadeIn animate__faster"
|
||||
|
||||
:class="{'d-none': loading}"></canvas>
|
||||
<div class="spinner-border m-auto" role="status" v-if="loading">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
@@ -61,4 +85,11 @@ export default {
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
@media screen and (max-width: 768px) {
|
||||
#qrcode{
|
||||
width: 100% !important;
|
||||
height: auto !important;
|
||||
aspect-ratio: 1/1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+2
-2
@@ -46,7 +46,7 @@ export default {
|
||||
methods: {
|
||||
save(){
|
||||
if (this.job.Field && this.job.Operator && this.job.Action && this.job.Value){
|
||||
fetchPost(`/api/savePeerScheduleJob/`, {
|
||||
fetchPost(`/api/savePeerScheduleJob`, {
|
||||
Job: this.job
|
||||
}, (res) => {
|
||||
if (res.status){
|
||||
@@ -84,7 +84,7 @@ export default {
|
||||
},
|
||||
delete(){
|
||||
if(this.job.CreationDate){
|
||||
fetchPost(`/api/deletePeerScheduleJob/`, {
|
||||
fetchPost(`/api/deletePeerScheduleJob`, {
|
||||
Job: this.job
|
||||
}, (res) => {
|
||||
if (!res.status){
|
||||
|
||||
@@ -198,30 +198,6 @@ export default {
|
||||
v-model="this.data.keepalive"
|
||||
id="peer_keep_alive">
|
||||
</div>
|
||||
<div v-if="this.data.advanced_security">
|
||||
<label for="peer_advance_security" class="form-label d-block">
|
||||
<small class="text-muted">
|
||||
<LocaleText t="Advanced Security"></LocaleText>
|
||||
</small>
|
||||
</label>
|
||||
<div class="btn-group" role="group">
|
||||
<input type="radio" class="btn-check"
|
||||
v-model="this.data.advanced_security"
|
||||
value="on"
|
||||
name="advanced_security_radio" id="advanced_security_on" autocomplete="off">
|
||||
<label class="btn btn-outline-primary btn-sm" for="advanced_security_on">
|
||||
<LocaleText t="On"></LocaleText>
|
||||
</label>
|
||||
|
||||
<input type="radio"
|
||||
v-model="this.data.advanced_security"
|
||||
value="off"
|
||||
class="btn-check" name="advanced_security_radio" id="advanced_security_off" autocomplete="off">
|
||||
<label class="btn btn-outline-primary btn-sm" for="advanced_security_off">
|
||||
<LocaleText t="Off"></LocaleText>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -29,7 +29,7 @@ export default {
|
||||
methods: {
|
||||
toggle(){
|
||||
this.configurationToggling = true;
|
||||
fetchGet("/api/toggleWireguardConfiguration/", {
|
||||
fetchGet("/api/toggleWireguardConfiguration", {
|
||||
configurationName: this.c.Name
|
||||
}, (res) => {
|
||||
if (res.status){
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<script setup>
|
||||
import LocaleText from "@/components/text/localeText.vue";
|
||||
import AgentContainer from "@/components/navbarComponents/agentContainer.vue";
|
||||
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||
|
||||
const emits = defineEmits(['close'])
|
||||
@@ -29,7 +28,7 @@ const store = DashboardConfigurationStore()
|
||||
<LocaleText t="You can visit our: "></LocaleText>
|
||||
</p>
|
||||
<div class="list-group">
|
||||
<a href="https://donaldzou.github.io/WGDashboard-Documentation/"
|
||||
<a href="https://docs.wgdashboard.dev/"
|
||||
target="_blank" class="list-group-item list-group-item-action d-flex align-items-center">
|
||||
<i class="bi bi-book-fill"></i>
|
||||
<LocaleText class="ms-auto" t="Official Documentation"></LocaleText>
|
||||
@@ -75,7 +74,7 @@ const store = DashboardConfigurationStore()
|
||||
width: 450px;
|
||||
box-shadow: 0px 10px 30px rgba(0, 0, 0, 0.3);
|
||||
backdrop-filter: blur(8px);
|
||||
background: linear-gradient(var(--degree), #009dff52 var(--distance2), #ff4a0052 100%);
|
||||
background: linear-gradient(var(--degree), #009dff52 var(--distance2), #F9464752 100%);
|
||||
}
|
||||
|
||||
.agentContainer.enabled{
|
||||
|
||||
@@ -52,7 +52,7 @@ onMounted(() => {
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<a class="card text-decoration-none" href="https://donaldzou.github.io/WGDashboard-Documentation/" target="_blank">
|
||||
<a class="card text-decoration-none" href="https://docs.wgdashboard.dev/" target="_blank">
|
||||
<div class="card-body d-flex gap-4 align-items-center">
|
||||
<h1 class="mb-0">
|
||||
<i class="bi bi-hash"></i>
|
||||
|
||||
@@ -27,6 +27,7 @@ const squareHeight = computed(() => {
|
||||
<div
|
||||
v-if="show"
|
||||
style="white-space: nowrap;"
|
||||
:style="{'top': squareHeight}"
|
||||
class="floatingLabel z-3 border position-absolute d-block p-1 px-2
|
||||
bg-body text-body rounded-3 border shadow d-flex"
|
||||
:class="[align ? 'end-0':'start-0']"
|
||||
@@ -48,7 +49,4 @@ const squareHeight = computed(() => {
|
||||
transition: background-color 0.5s cubic-bezier(0.42, 0, 0.22, 1.0);
|
||||
}
|
||||
|
||||
.floatingLabel{
|
||||
top: 40px;
|
||||
}
|
||||
</style>
|
||||
@@ -23,6 +23,7 @@ const squareHeight = computed(() => {
|
||||
<div
|
||||
v-if="show"
|
||||
style="white-space: nowrap;"
|
||||
:style="{'top': squareHeight}"
|
||||
class="floatingLabel z-3 border position-absolute d-block p-1 px-2
|
||||
bg-body text-body rounded-3 border shadow d-flex"
|
||||
:class="[align ? 'end-0':'start-0']"
|
||||
@@ -43,8 +44,4 @@ const squareHeight = computed(() => {
|
||||
height: v-bind(squareHeight);
|
||||
transition: background-color 0.5s cubic-bezier(0.42, 0, 0.22, 1.0);
|
||||
}
|
||||
|
||||
.floatingLabel{
|
||||
top: v-bind(squareHeight);
|
||||
}
|
||||
</style>
|
||||
@@ -66,13 +66,13 @@ const data = computed(() => {
|
||||
</h6>
|
||||
<h6 class="ms-auto">
|
||||
<span v-if="data">
|
||||
{{ data?.Disks.find(x => x.mountPoint === '/').percent }}%
|
||||
{{ data.Disks.find(x => x.mountPoint === '/') ? data?.Disks.find(x => x.mountPoint === '/').percent : data?.Disks[0].percent }}%
|
||||
</span>
|
||||
<span v-else class="spinner-border spinner-border-sm"></span>
|
||||
</h6>
|
||||
</div>
|
||||
<div class="progress" role="progressbar" style="height: 6px">
|
||||
<div class="progress-bar bg-success" :style="{width: `${data?.Disks.find(x => x.mountPoint === '/').percent}%` }"></div>
|
||||
<div class="progress-bar bg-success" :style="{width: `${data?.Disks.find(x => x.mountPoint === '/') ? data?.Disks.find(x => x.mountPoint === '/').percent : data?.Disks[0].percent}%` }"></div>
|
||||
</div>
|
||||
<div class="d-flex mt-2 gap-1">
|
||||
<StorageMount v-for="(disk, count) in data?.Disks"
|
||||
|
||||
@@ -35,39 +35,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sidebar
|
||||
*/
|
||||
|
||||
/*.sidebar {*/
|
||||
/* position: fixed;*/
|
||||
/* top: 0;*/
|
||||
/* bottom: 0;*/
|
||||
/* left: 0;*/
|
||||
/* z-index: 100;*/
|
||||
/* !* Behind the navbar *!*/
|
||||
/* padding: 48px 0 0;*/
|
||||
/* !* Height of navbar *!*/
|
||||
/* box-shadow: inset -1px 0 0 rgba(0, 0, 0, .1);*/
|
||||
/*}*/
|
||||
|
||||
/*.sidebar-sticky {*/
|
||||
/* position: relative;*/
|
||||
/* top: 0;*/
|
||||
/* height: calc(100vh - 48px);*/
|
||||
/* padding-top: .5rem;*/
|
||||
/* overflow-x: hidden;*/
|
||||
/* overflow-y: auto;*/
|
||||
/* !* Scrollable contents if viewport is shorter than content. *!*/
|
||||
/*}*/
|
||||
|
||||
/*@supports ((position: -webkit-sticky) or (position: sticky)) {*/
|
||||
/* .sidebar-sticky {*/
|
||||
/* position: -webkit-sticky;*/
|
||||
/* position: sticky;*/
|
||||
/* }*/
|
||||
/*}*/
|
||||
|
||||
@property --brandColor1 {
|
||||
syntax: '<color>';
|
||||
initial-value: #009dff;
|
||||
@@ -1273,7 +1240,6 @@ samp{
|
||||
}
|
||||
|
||||
.wireguardBg{
|
||||
|
||||
background: rgb(125,32,32);
|
||||
background: linear-gradient(90deg, rgba(125,32,32,1) 0%, rgba(255,56,56,1) 100%);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import { createPinia } from 'pinia'
|
||||
import App from './App.vue'
|
||||
import router from './router/router.js'
|
||||
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
|
||||
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
|
||||
let Locale;
|
||||
await fetch("/api/locale")
|
||||
.then(res => res.json())
|
||||
@@ -24,7 +23,6 @@ const pinia = createPinia();
|
||||
pinia.use(({ store }) => {
|
||||
store.$router = markRaw(router)
|
||||
})
|
||||
pinia.use(piniaPluginPersistedstate)
|
||||
|
||||
app.use(pinia)
|
||||
const store = DashboardConfigurationStore()
|
||||
|
||||
@@ -34,6 +34,7 @@ export default {
|
||||
PreDown: "",
|
||||
PostUp: "",
|
||||
PostDown: "",
|
||||
Table: "",
|
||||
Protocol: "wg",
|
||||
Jc: 5,
|
||||
Jmin: 49,
|
||||
@@ -342,6 +343,7 @@ export default {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<div class="accordion" id="newConfigurationOptionalAccordion">
|
||||
<div class="accordion-item">
|
||||
@@ -353,7 +355,7 @@ export default {
|
||||
<div id="newConfigurationOptionalAccordionCollapse"
|
||||
class="accordion-collapse collapse" data-bs-parent="#newConfigurationOptionalAccordion">
|
||||
<div class="accordion-body d-flex flex-column gap-3">
|
||||
<div class="card rounded-3" v-for="key in ['PreUp', 'PreDown', 'PostUp', 'PostDown']">
|
||||
<div class="card rounded-3" v-for="key in ['Table', 'PreUp', 'PreDown', 'PostUp', 'PostDown']">
|
||||
<div class="card-header">{{ key }}</div>
|
||||
<div class="card-body">
|
||||
<input type="text"
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
[
|
||||
{
|
||||
"lang_id": "id",
|
||||
"lang_name": "Bahasa Indonesia",
|
||||
"lang_name_localized": "Bahasa Indonesia"
|
||||
},
|
||||
{
|
||||
"lang_id": "zh-cn",
|
||||
"lang_name": "Chinese (Simplified)",
|
||||
@@ -9,6 +14,11 @@
|
||||
"lang_name": "Belarusian",
|
||||
"lang_name_localized": "Беларуская"
|
||||
},
|
||||
{
|
||||
"lang_id": "ca",
|
||||
"lang_name": "Catalan",
|
||||
"lang_name_localized": "Català"
|
||||
},
|
||||
{
|
||||
"lang_id": "zh-hk",
|
||||
"lang_name": "Chinese (Traditional)",
|
||||
@@ -44,11 +54,21 @@
|
||||
"lang_name": "French (Quebec)",
|
||||
"lang_name_localized": "Français (Québec)"
|
||||
},
|
||||
{
|
||||
"lang_id": "fr-fr",
|
||||
"lang_name": "French (France)",
|
||||
"lang_name_localized": "Français (France)"
|
||||
},
|
||||
{
|
||||
"lang_id": "de-de",
|
||||
"lang_name": "German",
|
||||
"lang_name_localized": "Deutsch"
|
||||
},
|
||||
{
|
||||
"lang_id": "hu-hu",
|
||||
"lang_name": "Hungarian",
|
||||
"lang_name_localized": "Magyar"
|
||||
},
|
||||
{
|
||||
"lang_id": "it-it",
|
||||
"lang_name": "Italian",
|
||||
@@ -69,6 +89,11 @@
|
||||
"lang_name": "Polish",
|
||||
"lang_name_localized": "Polski"
|
||||
},
|
||||
{
|
||||
"lang_id": "pt-br",
|
||||
"lang_name": "Portuguese (Brazil)",
|
||||
"lang_name_localized": "Português (Brasil)"
|
||||
},
|
||||
{
|
||||
"lang_id": "ru",
|
||||
"lang_name": "Russian",
|
||||
@@ -99,4 +124,4 @@
|
||||
"lang_name": "Ukrainian",
|
||||
"lang_name_localized": "Українська"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -278,7 +278,6 @@
|
||||
"Create Backup": "إنشاء نسخة احتياطية",
|
||||
"No backup yet, click the button above to create backup\\.": "لا توجد نسخة احتياطية حتى الآن، انقر على الزر أعلاه لإنشاء نسخة احتياطية",
|
||||
"Are you sure to delete this backup\\?": "هل أنت متأكد من حذف هذه النسخة الاحتياطية؟",
|
||||
"Are you sure to restore this backup?\\": "هل أنت متأكد من استعادة هذه النسخة الاحتياطية؟",
|
||||
"Backup Date": "تاريخ النسخة الاحتياطية",
|
||||
"File": "الملف",
|
||||
"Are you sure to delete this configuration\\?": "هل أنت متأكد من حذف هذا الإعداد؟",
|
||||
@@ -308,5 +307,63 @@
|
||||
"Deleted ([0-9]{1,}) peer\\(s\\)": "تم حذف $1 قرين(قرين)",
|
||||
"Deleted ([0-9]{1,}) peer\\(s\\) successfully. Failed to delete ([0-9]{1,}) peer\\(s\\)": "تم حذف $1 قرين(قرين) بنجاح. فشل في حذف $2 قرين(قرين)",
|
||||
"Restricted ([0-9]{1,}) peer\\(s\\)": "تم تقييد $1 قرين(قرين).",
|
||||
"Restricted ([0-9]{1,}) peer\\(s\\) successfully. Failed to restrict ([0-9]{1,}) peer\\(s\\)": "تم تقييد $1 قرين(قرين) بنجاح. فشل في تقييد $2 قرين(قرين)."
|
||||
"Restricted ([0-9]{1,}) peer\\(s\\) successfully. Failed to restrict ([0-9]{1,}) peer\\(s\\)": "تم تقييد $1 قرين(قرين) بنجاح. فشل في تقييد $2 قرين(قرين).",
|
||||
"Table": "",
|
||||
"Search": "",
|
||||
"Hop": "",
|
||||
"Average RTT \\(ms\\)": "",
|
||||
"Min RTT \\(ms\\)": "",
|
||||
"Max RTT \\(ms\\)": "",
|
||||
"You can visit our: ": "",
|
||||
"Official Documentation": "",
|
||||
"Discord Server": "",
|
||||
"Are you sure to restore this backup\\?": "",
|
||||
"Download": "",
|
||||
"Display As": "",
|
||||
"List": "",
|
||||
"Grid": "",
|
||||
"Protocol": "",
|
||||
"Open File": "",
|
||||
"Advanced Options": "",
|
||||
"Allowed IPs Validation": "",
|
||||
"Update Name": "",
|
||||
"To update this configuration's name, WGDashboard will execute the following operations:": "",
|
||||
"Duplicate current configuration's database table and \\.conf file with the new name": "",
|
||||
"Delete current configuration's database table and \\.conf file": "",
|
||||
"Danger Zone": "",
|
||||
"Configuration File": "",
|
||||
"Edit Raw Configuration File": "",
|
||||
"Peer Configuration File": "",
|
||||
"Share with Email": "",
|
||||
"Email Account": "",
|
||||
"Ready": "",
|
||||
"Port": "",
|
||||
"Encryption": "",
|
||||
"No Encryption": "",
|
||||
"Send From": "",
|
||||
"Send Test Email": "",
|
||||
"Email Body Template": "",
|
||||
"Live Preview": "",
|
||||
"Include configuration file as an attachment": "",
|
||||
"Send": "",
|
||||
"Sending\\.\\.\\.": "",
|
||||
"Email sent successfully!": "",
|
||||
"AmneziaWG Peer Setting": "",
|
||||
"System Status": "",
|
||||
"CPU": "",
|
||||
"Memory": "",
|
||||
"Swap Memory": "",
|
||||
"Processes": "",
|
||||
"CPU Usage": "",
|
||||
"Memory Usage": "",
|
||||
"Swap Memory Usage": "",
|
||||
"Network": "",
|
||||
"([0-9]{1,}) Interfaces": "",
|
||||
"Storage": "",
|
||||
"([0-9]{1,}) Partitions": "",
|
||||
"(.*) Used": "",
|
||||
"Untitled Peer": "",
|
||||
"Who are you sending to\\?": "",
|
||||
"What\\'s the subject\\?": "",
|
||||
"What\\'s the body\\?": ""
|
||||
}
|
||||
@@ -278,7 +278,6 @@
|
||||
"Create Backup": "Стварыць рэзервовую копію",
|
||||
"No backup yet, click the button above to create backup\\.": "Рэзервовых копій яшчэ няма, націсніце кнопку вышэй, каб стварыць рэзервовую копію.",
|
||||
"Are you sure to delete this backup\\?": "Вы ўпэўнены, што хочаце выдаліць гэтую рэзервовую копію?",
|
||||
"Are you sure to restore this backup?\\": "Вы ўпэўнены, што хочаце аднавіць гэтую рэзервовую копію?",
|
||||
"Backup Date": "Дата рэзервовай копіі",
|
||||
"File": "Файл",
|
||||
"Are you sure to delete this configuration\\?": "Вы ўпэўнены, што хочаце выдаліць гэтую канфігурацыю?",
|
||||
@@ -308,5 +307,63 @@
|
||||
"Deleted ([0-9]{1,}) peer\\(s\\)": "Выдалена $1 кліент(аў)",
|
||||
"Deleted ([0-9]{1,}) peer\\(s\\) successfully. Failed to delete ([0-9]{1,}) peer\\(s\\)": "Выдалена $1 кліент(аў) паспяхова. Не ўдалося выдаліць $2 кліент(аў)",
|
||||
"Restricted ([0-9]{1,}) peer\\(s\\)": "Абмежавана $1 кліент(аў)",
|
||||
"Restricted ([0-9]{1,}) peer\\(s\\) successfully. Failed to restrict ([0-9]{1,}) peer\\(s\\)": "Абмежавана $1 кліент(аў) паспяхова. Не ўдалося абмежаваць $2 кліент(аў)"
|
||||
"Restricted ([0-9]{1,}) peer\\(s\\) successfully. Failed to restrict ([0-9]{1,}) peer\\(s\\)": "Абмежавана $1 кліент(аў) паспяхова. Не ўдалося абмежаваць $2 кліент(аў)",
|
||||
"Table": "",
|
||||
"Search": "",
|
||||
"Hop": "",
|
||||
"Average RTT \\(ms\\)": "",
|
||||
"Min RTT \\(ms\\)": "",
|
||||
"Max RTT \\(ms\\)": "",
|
||||
"You can visit our: ": "",
|
||||
"Official Documentation": "",
|
||||
"Discord Server": "",
|
||||
"Are you sure to restore this backup\\?": "",
|
||||
"Download": "",
|
||||
"Display As": "",
|
||||
"List": "",
|
||||
"Grid": "",
|
||||
"Protocol": "",
|
||||
"Open File": "",
|
||||
"Advanced Options": "",
|
||||
"Allowed IPs Validation": "",
|
||||
"Update Name": "",
|
||||
"To update this configuration's name, WGDashboard will execute the following operations:": "",
|
||||
"Duplicate current configuration's database table and \\.conf file with the new name": "",
|
||||
"Delete current configuration's database table and \\.conf file": "",
|
||||
"Danger Zone": "",
|
||||
"Configuration File": "",
|
||||
"Edit Raw Configuration File": "",
|
||||
"Peer Configuration File": "",
|
||||
"Share with Email": "",
|
||||
"Email Account": "",
|
||||
"Ready": "",
|
||||
"Port": "",
|
||||
"Encryption": "",
|
||||
"No Encryption": "",
|
||||
"Send From": "",
|
||||
"Send Test Email": "",
|
||||
"Email Body Template": "",
|
||||
"Live Preview": "",
|
||||
"Include configuration file as an attachment": "",
|
||||
"Send": "",
|
||||
"Sending\\.\\.\\.": "",
|
||||
"Email sent successfully!": "",
|
||||
"AmneziaWG Peer Setting": "",
|
||||
"System Status": "",
|
||||
"CPU": "",
|
||||
"Memory": "",
|
||||
"Swap Memory": "",
|
||||
"Processes": "",
|
||||
"CPU Usage": "",
|
||||
"Memory Usage": "",
|
||||
"Swap Memory Usage": "",
|
||||
"Network": "",
|
||||
"([0-9]{1,}) Interfaces": "",
|
||||
"Storage": "",
|
||||
"([0-9]{1,}) Partitions": "",
|
||||
"(.*) Used": "",
|
||||
"Untitled Peer": "",
|
||||
"Who are you sending to\\?": "",
|
||||
"What\\'s the subject\\?": "",
|
||||
"What\\'s the body\\?": ""
|
||||
}
|
||||
@@ -0,0 +1,369 @@
|
||||
{
|
||||
"Welcome to": "Benvingut",
|
||||
"Username": "Usuari",
|
||||
"Password": "Contrasenya",
|
||||
"OTP from your authenticator": "OTP del seu autenticador",
|
||||
"Sign In": "Iniciar sessió",
|
||||
"Signing In\\.\\.\\.": "Iniciant sessió\\.\\.\\.",
|
||||
"Access Remote Server": "Accedir al servidor remot",
|
||||
"Server": "Servidor",
|
||||
"Click": "Clic",
|
||||
"Pinging...": "S'està fent ping...",
|
||||
"to add your server": "per afegir el vostre servidor",
|
||||
"Server List": "Llista de servidors:",
|
||||
"Sorry, your username or password is incorrect.": "Ho sentim, el seu nom d'usuari o contrasenya són incorrectes",
|
||||
"Home": "Inici",
|
||||
"Settings": "Paràmetres",
|
||||
"Tools": "Eines",
|
||||
"Sign Out": "Tancar sessió",
|
||||
"Checking for update...": "Comprovant actualitzacions...",
|
||||
"You're on the latest version": "Està a l'última versió",
|
||||
"WireGuard Configurations": "Configuració de WireGuard",
|
||||
"You don't have any WireGuard configurations yet. Please check the configuration folder or change it in Settings. By default the folder is /etc/wireguard.": "Encara no teniu cap configuració de WireGuard. Si us plau, comproveu la carpeta de configuració o canvieu-la a Configuració. Per defecte, la carpeta és /etc/wireguard.",
|
||||
"Configuration": "Configuració",
|
||||
"Configurations": "Configuracions",
|
||||
"Peers Default Settings": "Paràmetres per defecte de Peers",
|
||||
"Dashboard Theme": "Tema del tauler",
|
||||
"Light": "Clar",
|
||||
"Dark": "Fosc",
|
||||
"This will be changed globally, and will be apply to all peer's QR code and configuration file.": "Això es canviarà globalment i s'aplicarà a tots els codis QR i fitxers de configuració dels peer.",
|
||||
"WireGuard Configurations Settings": "Paràmetres de Configuració del WireGuard",
|
||||
"Configurations Directory": "Carpeta de configuracions",
|
||||
"Remember to remove / at the end of your path. e.g /etc/wireguard": "Recordi eliminar / al final de la vostra ruta. p. ex. /etc/wireguard",
|
||||
"WGDashboard Account Settings": "Paràmetres el Compte WGDashboard",
|
||||
"Current Password": "Contrasenya Actual",
|
||||
"New Password": "Nova Contrasenya",
|
||||
"Repeat New Password": "Repeteixi la Nova Contrasenya",
|
||||
"Update Password": "Actualitzar Contrasenya",
|
||||
"Multi-Factor Authentication \\(MFA\\)": "Autenticació Multifactor \\(MFA\\)",
|
||||
"Reset": "Restablir",
|
||||
"Setup": "Configuració",
|
||||
"API Keys": "Claus API",
|
||||
"API Key": "Clau API",
|
||||
"Key": "Clau",
|
||||
"Enabled": "Habilitat",
|
||||
"Disabled": "Deshabilitat",
|
||||
"No WGDashboard API Key": "No hi ha clau API de WGDashboard",
|
||||
"Expire At": "Caduca al",
|
||||
"Are you sure to delete this API key\\?": "Està segur que vol eliminar aquesta clau API\\?",
|
||||
"Create API Key": "Crear clau d'API",
|
||||
"When should this API Key expire\\?": "Quan hauria de caducar aquesta clau API\\?",
|
||||
"Never Expire": "Mai Expira",
|
||||
"Don't think that's a good idea": "No crec que sigui una bona idea",
|
||||
"Creating\\.\\.\\.": "Creant\\.\\.\\.",
|
||||
"Create": "Crear",
|
||||
"Status": "Estatus",
|
||||
"On": "Iniciar",
|
||||
"Off": "Parar",
|
||||
"Turning On\\.\\.\\.": "S'està encenent\\.\\.\\.",
|
||||
"Turning Off\\.\\.\\.": "S'estat apagant\\.\\.\\.",
|
||||
"Address": "Adreça",
|
||||
"Listen Port": "Port d'escolta",
|
||||
"Public Key": "Clau Pública",
|
||||
"Connected Peers": "Peers Connectats",
|
||||
"Total Usage": "Total usat",
|
||||
"Total Received": "Total Rebut",
|
||||
"Total Sent": "Total Enviat",
|
||||
"Peers Data Usage": "Ús de dades dels Peers",
|
||||
"Real Time Received Data Usage": "Ús de Dades Rebudes en Temps Real",
|
||||
"Real Time Sent Data Usage": "Úsde Dades Eviades en Temps Real",
|
||||
"Peer": "Peer",
|
||||
"Peers": "Peers",
|
||||
"Peer Settings": "Paràmetres del Peer",
|
||||
"Download All": "Descarregar Tot",
|
||||
"Search": "Cercar",
|
||||
"Search Peers\\.\\.\\.": "Cercar Peers\\.\\.\\.",
|
||||
"Display": "Mostrar",
|
||||
"Sort By": "Ordenar Per",
|
||||
"Refresh Interval": "Interval de Refresc",
|
||||
"Name": "Nom",
|
||||
"Allowed IPs": "IPs Permeses",
|
||||
"Restricted": "Restringit",
|
||||
"(.*) Seconds": "(.*) Segons",
|
||||
"(.*) Minutes": "(.*) Minuts",
|
||||
"Configuration Settings": "Paràmetres de Configuracio",
|
||||
"Peer Jobs": "Feines Peer",
|
||||
"Active Jobs": "Feines Actives",
|
||||
"All Active Jobs": "Totes les Feines Actives",
|
||||
"Logs": "Registres",
|
||||
"Private Key": "Clau Privada",
|
||||
"\\(Required for QR Code and Download\\)": "\\(Obligatori pel Codi QR i la Descàrrega\\)",
|
||||
"\\(Required\\)": "\\(Obligatori\\)",
|
||||
"Endpoint Allowed IPs": "IPs Permeses del Punt Final",
|
||||
"DNS": "DNS",
|
||||
"Optional Settings": "Paràmetres Opcionals",
|
||||
"Pre-Shared Key": "Clau Precompartida",
|
||||
"MTU": "MTU",
|
||||
"Persistent Keepalive": "Keepalive Persistent",
|
||||
"Reset Data Usage": "Restablir l'Ús de Dades",
|
||||
"Total": "Total",
|
||||
"Sent": "Enviat",
|
||||
"Received": "Rebut",
|
||||
"Revert": "Desfer",
|
||||
"Save Peer": "Desar Peer",
|
||||
"QR Code": "Codi QR",
|
||||
"Schedule Jobs": "Feines Programades",
|
||||
"Job": "Feina",
|
||||
"Job ID": "Feina ID",
|
||||
"Unsaved Job": "Feina no desada",
|
||||
"This peer does not have any job yet\\.": "Aquest peer encara no te cap feina\\.",
|
||||
"if": "si",
|
||||
"is": "és",
|
||||
"then": "aleshores",
|
||||
"larger than": "més llarg que",
|
||||
"Date": "Data",
|
||||
"Restrict Peer": "Restringir Peer",
|
||||
"Delete Peer": "Eliminar Peer",
|
||||
"Edit": "Editar",
|
||||
"Delete": "Eliminar",
|
||||
"Deleting...": "Eliminant...",
|
||||
"Cancel": "Cancel·lar",
|
||||
"Save": "Desar",
|
||||
"No active job at the moment\\.": "No hi ha cap feina activa ara mateix\\.",
|
||||
"Jobs Logs": "Registres de Feines",
|
||||
"Updated at": "Actualitzat a",
|
||||
"Refresh": "Refrescar",
|
||||
"Filter": "Filtrar",
|
||||
"Success": "Èxit",
|
||||
"Failed": "Fallat",
|
||||
"Log ID": "ID Registre",
|
||||
"Message": "Missatge",
|
||||
"Share Peer": "Compartir Peer",
|
||||
"Currently the peer is not sharing": "Actualment el peer no s'està compartint",
|
||||
"Sharing\\.\\.\\.": "Compartint\\.\\.\\.",
|
||||
"Start Sharing": "Començar a Compartir",
|
||||
"Stop Sharing\\.\\.\\.": "Parar de Compartir\\.\\.\\.",
|
||||
"Stop Sharing": "Para de Compartir",
|
||||
"Access Restricted": "Accés Restringit",
|
||||
"Restrict Access": "Àrea Restringida",
|
||||
"Restricting\\.\\.\\.": "Restringint\\.\\.\\.",
|
||||
"Allow Access": "Permetre Accés",
|
||||
"Allowing Access\\.\\.\\.": "Permetent Accés\\.\\.\\.",
|
||||
"Download \\& QR Code is not available due to no private key set for this peer": "La descàrrega del codi QR \\& no està disponible perquè no s'ha establert cap clau privada per a aquest peer",
|
||||
"Add Peers": "Afegir Peers",
|
||||
"Bulk Add": "Afegir en Massa",
|
||||
"By adding peers by bulk, each peer's name will be auto generated, and Allowed IP will be assign to the next available IP\\.": "En afegir peers en massa, el nom de cada peer es generarà automàticament i la IP permesa s'assignarà a la següent IP disponible\\.",
|
||||
"How many peers you want to add\\?": "Quants peers voleu afegir\\?",
|
||||
"You can add up to (.*) peers": "Pot afegir fins a (.*) peers",
|
||||
"Use your own Private and Public Key": "Utilitzi la seva pròpia Clau Privada i Pública",
|
||||
"Enter IP Address/CIDR": "Introdueixi l'adreça IP/CIDR",
|
||||
"IP Address/CIDR": "Adreça IP/CDIR",
|
||||
"or": "o",
|
||||
"Pick Available IP": "Seleccioni una IP disponible",
|
||||
"No available IP containing": "No conté cap IP disponible",
|
||||
"Add": "Afegir",
|
||||
"Adding\\.\\.\\.": "Afegint\\.\\.\\.",
|
||||
"Failed to check available update": "No s'ha pogut comprovar l'actualització disponible",
|
||||
"Nice to meet you!": "Encantat de conèixer-lo",
|
||||
"Please fill in the following fields to finish setup": "Si us plau, ompli els següets camps per finalitzar la configuració",
|
||||
"Create an account": "Crear un compte",
|
||||
"Enter an username you like": "Introdueixi un nom d'usuari que li agradi",
|
||||
"Enter a password": "Introduir una contrasenya",
|
||||
"\\(At least 8 characters and make sure is strong enough!\\)": "\\(Com a mínim 8 caràcters i asseguri's que és suficietment forta!\\)",
|
||||
"Confirm password": "Confirmar contrasenya",
|
||||
"Next": "Seguent",
|
||||
"Saving\\.\\.\\.": "Desant\\.\\.\\.",
|
||||
"1\\. Please scan the following QR Code to generate TOTP with your choice of authenticator": "1\\. Si us plau, escanegi el següent codi QR per generar TOTP amb l'autenticador que triï",
|
||||
"Or you can click the link below:": "O bé pot clicar l'enllaç següent:",
|
||||
"2\\. Enter the TOTP generated by your authenticator to verify": "2\\. Introdueixi el TOTP generat pel seu autentitador per feriricar",
|
||||
"TOTP verified!": "TOTP verificat!",
|
||||
"I don't need MFA": "No necessito MFA",
|
||||
"Complete": "Completat",
|
||||
"(v[0-9.]{1,}) is now available for update!": "(v[0-9.]{1,}) ara està disponible per actualitzar!",
|
||||
"Current Version:": "Versió Actual",
|
||||
"Oh no\\.\\.\\. This link is either expired or invalid\\.": "Oh no\\.\\.\\. Aquest enllaç ha caducat o no és vàlid",
|
||||
"Scan QR Code with the WireGuard App to add peer": "Escanegi el codi QR amb l'aplicació WireGuard per afegir el peer",
|
||||
"or click the button below to download the ": "o faci clic al botó següent per descarrer el ",
|
||||
" file": " fitxer",
|
||||
"FROM ": "DE",
|
||||
"(.*) is on": "(.*) està encès",
|
||||
"(.*) is off": "(.*) està parat",
|
||||
"Allowed IPs is invalid": "Les IPs Permeses no són vàlides",
|
||||
"Peer created successfully": "Pere creat satisfactoriament",
|
||||
"Please fill in all required box": "Si us plau, empleni tots els espais necessaris",
|
||||
"Please specify amount of peers you want to add": "Si us plau, especifiqueu la quantitat de persones del mateix nivell que vol afegir",
|
||||
"No more available IP can assign": "No hi ha cap més IP disponible per assignar",
|
||||
"The maximum number of peers can add is (.*)": "El màxim nombre de peers que es poden afegir és (.*)",
|
||||
"Generating key pairs by bulk failed": "No s'ha pogut generar parells de claus de manera massiva",
|
||||
"Failed to add peers in bulk": "No s'ha pogut afegir peers de manera massiva",
|
||||
"This peer already exist": "Aquest peer ja existeix",
|
||||
"This IP is not available: (.*)": "Aquesta IP no està disponible: (.*)",
|
||||
"Configuration does not exist": "La configuració no existeix",
|
||||
"Peer does not exist": "El Pere no existeix",
|
||||
"Please provide a valid configuration name": "Si us plau, proporcioneu un nom de configuració vàlid",
|
||||
"Peer saved": "Peter desat",
|
||||
"Allowed IPs already taken by another peer": "Les IPs permeses ja estan ocupades per un altre peer",
|
||||
"Endpoint Allowed IPs format is incorrect": "El format de les IPs permeses del punt final és incorrecte",
|
||||
"DNS format is incorrect": "El DNS és incorrecte",
|
||||
"MTU format is not correct": "El format MTU no és correcte",
|
||||
"Persistent Keepalive format is not correct": "El format de Keepalive persistent no és correcte",
|
||||
"Private key does not match with the public key": "La clau privada no coincideix amb la clau pública",
|
||||
"Update peer failed when updating Pre-Shared Key": "L'actualització del peer ha fallat en actualitzar la clau precompartida",
|
||||
"Update peer failed when updating Allowed IPs": "L'actualització del peer ha fallat en actualitzar les IP permeses",
|
||||
"Update peer failed when saving the configuration": "L'actualització del peer ha fallat en desar la configuració",
|
||||
"Peer data usage reset successfully": "L'ús de dades del peer s'ha reiniciat correctament",
|
||||
"Peer download started": "La descàrrega del peer s'ha iniciat",
|
||||
"Please specify one or more peers": "Si us plau, especifiqueu un o més peers",
|
||||
"Share link failed to create. Reason: (.*)": "No s'ha pogut crear l'enllaç de compartició. Motiu: (.*)",
|
||||
"Link expire date updated": "La data de caducitat de l'enllaç s'ha actualitzat",
|
||||
"Link expire date failed to update. Reason: (.*)": "No s'ha pogut actualitzar la data de caducitat de l'enllaç. Mtoiu: (.*)",
|
||||
"Peer job saved": "Feina del peer desat",
|
||||
"Please specify job": "Si us plau, especifiqui la tasca",
|
||||
"Please specify peer and configuration": "Si us plau, esficiqui el peer i la configuració",
|
||||
"Peer job deleted": "Feina del peer suprimida",
|
||||
"API Keys function is successfully enabled": "La funció de claus API s'ha activat correctament",
|
||||
"API Keys function is successfully disabled": "La funció de claus API s'ha descativat correctament",
|
||||
"API Keys function is failed to enable": "No s'ha pogut habilitar la funció de claus API",
|
||||
"API Keys function is failed to disable": "No s'ha pogut desactivar la funció de claus API",
|
||||
"WGDashboard API Keys function is disabled": "La funció de claus API de WGDashboard està desactivada",
|
||||
"WireGuard configuration path saved": "Ruta de configuracio del WireGuard desada",
|
||||
"API Key deleted": "Clau API eliminada",
|
||||
"API Key created": "Clau API creada",
|
||||
"Sign in session ended, please sign in again": "La sessió d'inici ha finalitzat. Si us plau, torni a iniciar",
|
||||
"Please specify an IP Address (v4/v6)": "Si us plau, espqcifiqui una adreça IP (v4/v6)",
|
||||
"Please provide ipAddress and count": "Si us plau, proporcioni l'adreça IP i el recompte",
|
||||
"Please provide ipAddress": "Si us plau, proporcioni l'adreça IP",
|
||||
"Dashboard Language": "Idioma del tauler de control",
|
||||
"Dashboard language update failed": "Error d'actualització de l'idioma del tauler de control",
|
||||
"Peer Remote Endpoint": "Punt Final Remot del Peer",
|
||||
"New Configuration": "Nova Configuració",
|
||||
"Configuration Name": "Nom de Configuració",
|
||||
"Configuration name is invalid. Possible reasons:": "Nom de configuració no vàlid. Possibles raons:",
|
||||
"Configuration name already exist\\.": "El nom de configuració ja existeix\\.",
|
||||
"Configuration name can only contain 15 lower/uppercase alphabet, numbers, underscore, equal sign, plus sign, period and hyphen\\.": "El nom de configuració només pot contenir 15 caràcters en majúsucules/minúscules, números, subratllat, signe igual, signe més, punt i guionet\\.",
|
||||
"Invalid Port": "Port Invàlid",
|
||||
"Save Configuration": "Desar Configuració",
|
||||
"IP Address/CIDR is invalid": "L'adreça IP/CIDR no és vàlida",
|
||||
"IP Address": "Adreça IP",
|
||||
"Enter IP Address / Hostname": "Introdueixi l'adreça IP / nom de l'amfitrió",
|
||||
"IP Address / Hostname": "Adreça IP / Hostname",
|
||||
"Dashboard IP Address \\& Listen Port": "L'adreça IP del tauler de control\\& Port d'Escolta",
|
||||
"Count": "Comptar",
|
||||
"Geolocation": "Geolocalització",
|
||||
"Is Alive": "Estpa Viu",
|
||||
"Average / Min / Max Round Trip Time": "Temps mitjà / Min / Max d'anada i tornada",
|
||||
"Sent / Received / Lost Package": "Enviat / Rebut / Paquets Perduts",
|
||||
"Manual restart of WGDashboard is needed to apply changes on IP Address and Listen Port": "Cal reiniciar manualment WGDashboard per aplicar els canvis a l'adreça IP i al Port d'Escolta",
|
||||
"Restore Configuration": "Restaurar Configuració",
|
||||
"Step (.*)": "Pas (.*)",
|
||||
"Select a backup you want to restore": "Seleccioni una còpia de seguretat que vulgui restaurar",
|
||||
"Click to change a backup": "Faci clic per canviar una còpia de seguretat",
|
||||
"Selected Backup": "Còpia de seguretat seleccionada",
|
||||
"You don't have any configuration to restore": "No té cap configuració per restaurar",
|
||||
"Help": "Ajuda",
|
||||
"Backup": "Còpia de Seguretat",
|
||||
"([0-9].*) Backups?": "([0-9].*) Còpia de Seguretat?",
|
||||
"Yes": "Sí",
|
||||
"No": "No",
|
||||
"Backup not selected": "Còpia de seguretat no seleccionada",
|
||||
"Confirm \\& edit restore information": "Confirmar \\& editar restaurar informació?",
|
||||
"(.*) Available IP Address": "(.*) Adreces IP Disponibles",
|
||||
"Database File": "Fitxer de Base de Dades",
|
||||
"Contain": "Conté",
|
||||
"Restricted Peers?": "Peers restringuits?",
|
||||
"Restore": "Restaurar",
|
||||
"Restoring": "Restaurant",
|
||||
"WGDashboard Settings": "Paràmetres del WGDashboard",
|
||||
"Peers Settings": "Paràmetres de Peers",
|
||||
"WireGuard Configuration Settings": "Paràmetres de Configuració de WireGuard",
|
||||
"Appearance": "Aparença",
|
||||
"Theme": "Tema",
|
||||
"Language": "Idioma",
|
||||
"Account Settings": "Paràmetres del Compte",
|
||||
"Peer Default Settings": "Paràmetres per Defecte del Peer",
|
||||
"Toggle When Start Up": "Canviar Quan s'Iniciï",
|
||||
"Other Settings": "Altres Paràmetres",
|
||||
"Select Peers": "Seleccioni Peers",
|
||||
"Backup & Restore": "Còpia de seguretat & Restaurar",
|
||||
"Delete Configuration": "Eliminar Configuració",
|
||||
"Create Backup": "Crear Còpia de Seguretat",
|
||||
"No backup yet, click the button above to create backup\\.": "Encara no hi ha cap còpia de seguretat, faci clic al botó de dalt per crear una còpia de seguretat\\.",
|
||||
"Are you sure to delete this backup\\?": "Està segur que vol suprimir aquesta còpia de seguretat\\?",
|
||||
"Backup Date": "Data de la Còpia de Seguretat",
|
||||
"File": "Fitxer",
|
||||
"Are you sure to delete this configuration\\?": "Segur que vol suprimir aquesta configuració?",
|
||||
"Once you deleted this configuration\\:": "Un cop hagi suprimit aquesta configuració\\:",
|
||||
"All connected peers will get disconnected": "Tots els Peers connectats es desconnectaran",
|
||||
"Both configuration file \\(\\.conf\\) and database table related to this configuration will get deleted": "Tant el fitxer de configuració \\(\\.conf\\) com la taula de la base de dades relacionada amb aquesta configuració s'eliminarà",
|
||||
"Checking backups...": "Comprovant còpies de seguretat",
|
||||
"This configuration have ([0-9].*) backups": "Aquesta configuració té ([0-9].*) còpies de seguretat",
|
||||
"This configuration have no backup": "Aquesta configuració no té cap còpia de seguretat",
|
||||
"If you're sure, please type in the configuration name below and click Delete": "Si està segur, escrigui el nom de la configuració qa continuació i faci clic a Eliminar",
|
||||
"Select All": "Seleccionar Tot",
|
||||
"Clear Selection": "Netejar Selecció",
|
||||
"([0-9].*) Peers?": "([0-9].*) Peers?",
|
||||
"Download": "Descarregar",
|
||||
"Downloading": "Descarregant",
|
||||
"Download Finished": "Descàrrega Finalitzada",
|
||||
"Done": "Fet",
|
||||
"Are you sure to delete": "Està segur que vol eliminar",
|
||||
"Are you sure to delete this peer\\?": "Està segur que vol eliminar aquest peer\\?",
|
||||
"Configuration deleted": "Configuració eliminada",
|
||||
"Configuration saved": "Configuració desada",
|
||||
"WGDashboard language update failed": "L'actualització de l'idioma de WGDashboard ha fallat",
|
||||
"Configuration restored": "Configuració restaurada",
|
||||
"Allowed IP already taken by another peer": "IP permesa ja ocupada per un altre peer",
|
||||
"Failed to allow access of peer (.*)": "No s'ha pogut permetre l'accés al peer (.*)",
|
||||
"Failed to save configuration through WireGuard": "No s'ha pogut desar la configuració mitjançant WireGuard",
|
||||
"Allow access successfully": "Accés permès correctament",
|
||||
"Deleted ([0-9]{1,}) peer\\(s\\)": "Els ([0-9]{1,}) peer\\(s\\) s'han suprimit",
|
||||
"Deleted ([0-9]{1,}) peer\\(s\\) successfully. Failed to delete ([0-9]{1,}) peer\\(s\\)": "Els ([0-9]{1,}) peer\\(s\\) s'han suprimit correctament. No s'ha pgout suprimir els ([0-9]{1,}) peer\\(s\\)",
|
||||
"Restricted ([0-9]{1,}) peer\\(s\\)": "Els ([0-9]{1,}) peer\\(s\\) s'han restringit",
|
||||
"Restricted ([0-9]{1,}) peer\\(s\\) successfully. Failed to restrict ([0-9]{1,}) peer\\(s\\)": "Els ([0-9]{1,}) peer\\(s\\) s'han restringit correctament. No s'ha pogut restringuir els ([0-9]{1,}) peer\\(s\\)",
|
||||
"Display As": "Mostrar com a",
|
||||
"List": "Llista",
|
||||
"Grid": "Graella",
|
||||
"Protocol": "Protocol",
|
||||
"Open File": "Obrir Fitxer",
|
||||
"Advanced Options": "Opcions Avançades",
|
||||
"Allowed IPs Validation": "Validació d'IPs permeses",
|
||||
"Update Name": "Actualitzar Nom",
|
||||
"To update this configuration's name, WGDashboard will execute the following operations:": "Per actualitzar el nom d'aquesta configuració, WGDashboard executarà les operacions següents:",
|
||||
"Duplicate current configuration's database table and \\.conf file with the new name": "Duplicar la taula de base de dades i el fitxer \\.conf amb el nou nom",
|
||||
"Delete current configuration's database table and \\.conf file": "Eliminarla taula de base de dades i el fitxer \\.conf de la configuració actual",
|
||||
"Danger Zone": "Zona de Perill",
|
||||
"Configuration File": "Fitxer de Configuració",
|
||||
"Edit Raw Configuration File": "Editar el fitxer de configuració en brut",
|
||||
"Peer Configuration File": "Fitxer de Configuració del Peer",
|
||||
"Share with Email": "Compartir per correu electrònic",
|
||||
"Email Account": "Compte de correu electrònic",
|
||||
"Ready": "Preparat",
|
||||
"Port": "Port",
|
||||
"Encryption": "Encriptació",
|
||||
"No Encryption": "No encriptació",
|
||||
"Send From": "Enviar des de",
|
||||
"Send Test Email": "Enviar correu electrònic de prova",
|
||||
"Email Body Template": "Plantilla del cos del correu electrònic",
|
||||
"Live Preview": "Vista prèvia en directe",
|
||||
"Include configuration file as an attachment": "Inclogui el fitxer de configuració com a fitxer adjunt",
|
||||
"Send": "Enviar",
|
||||
"Sending\\.\\.\\.": "Enviant\\.\\.\\.",
|
||||
"Email sent successfully!": "Correu elctrònic enviat correctament!",
|
||||
"AmneziaWG Peer Setting": "Paràmetre del Peer d'AmneziaQG",
|
||||
"System Status": "Estat del sistema",
|
||||
"CPU": "CPU",
|
||||
"Memory": "Memòria",
|
||||
"Swap Memory": "Memòria Swap",
|
||||
"Processes": "Processos",
|
||||
"CPU Usage": "Ús de CPU",
|
||||
"Memory Usage": "Memòria Utilitzada",
|
||||
"Swap Memory Usage": "Ús de Memoria Swap",
|
||||
"Network": "Xarxa",
|
||||
"([0-9]{1,}) Interfaces": "([0-9]{1,}) Interfícies",
|
||||
"Storage": "Emmagatzematge",
|
||||
"([0-9]{1,}) Partitions": "([0-9]{1,}) Particions",
|
||||
"(.*) Used": "(.*) Utilitzat",
|
||||
"Untitled Peer": "Peer sense títol",
|
||||
"Table": "",
|
||||
"Hop": "",
|
||||
"Average RTT \\(ms\\)": "",
|
||||
"Min RTT \\(ms\\)": "",
|
||||
"Max RTT \\(ms\\)": "",
|
||||
"You can visit our: ": "",
|
||||
"Official Documentation": "",
|
||||
"Discord Server": "",
|
||||
"Are you sure to restore this backup\\?": "",
|
||||
"Who are you sending to\\?": "",
|
||||
"What\\'s the subject\\?": "",
|
||||
"What\\'s the body\\?": ""
|
||||
}
|
||||
@@ -257,7 +257,6 @@
|
||||
"Create Backup": "Vytvořit zálohu",
|
||||
"No backup yet, click the button above to create backup\\.": "Žádná dostupná záloha, klikněte na tlačítko výše pro vytvoření",
|
||||
"Are you sure to delete this backup\\?": "Určitě chcete smazat tuto zálohu?",
|
||||
"Are you sure to restore this backup?\\": "Určitě chcete obnovit tuto zálohu?",
|
||||
"Backup Date": "Datum zálohy",
|
||||
"File": "Soubor",
|
||||
"Are you sure to delete this configuration\\?": "Určitě chcete smazat tuto konfiguraci?",
|
||||
@@ -308,5 +307,63 @@
|
||||
"By adding peers by bulk, each peer's name will be auto generated, and Allowed IP will be assign to the next available IP\\.": "Při hromadném importu bude jméno každého peera vygenerované automaticky, a povolená IP adresa bude nastavena na další v pořadí",
|
||||
"How many peers you want to add\\?": "Kolik peerů chcete přidat?",
|
||||
"Adding\\.\\.\\.": "Přidávám...",
|
||||
"Dashboard IP Address \\& Listen Port": "Dashboard IP adresa a otevřený port"
|
||||
}
|
||||
"Dashboard IP Address \\& Listen Port": "Dashboard IP adresa a otevřený port",
|
||||
"Table": "",
|
||||
"Search": "",
|
||||
"Hop": "",
|
||||
"Average RTT \\(ms\\)": "",
|
||||
"Min RTT \\(ms\\)": "",
|
||||
"Max RTT \\(ms\\)": "",
|
||||
"You can visit our: ": "",
|
||||
"Official Documentation": "",
|
||||
"Discord Server": "",
|
||||
"Are you sure to restore this backup\\?": "",
|
||||
"Download": "",
|
||||
"Display As": "",
|
||||
"List": "",
|
||||
"Grid": "",
|
||||
"Protocol": "",
|
||||
"Open File": "",
|
||||
"Advanced Options": "",
|
||||
"Allowed IPs Validation": "",
|
||||
"Update Name": "",
|
||||
"To update this configuration's name, WGDashboard will execute the following operations:": "",
|
||||
"Duplicate current configuration's database table and \\.conf file with the new name": "",
|
||||
"Delete current configuration's database table and \\.conf file": "",
|
||||
"Danger Zone": "",
|
||||
"Configuration File": "",
|
||||
"Edit Raw Configuration File": "",
|
||||
"Peer Configuration File": "",
|
||||
"Share with Email": "",
|
||||
"Email Account": "",
|
||||
"Ready": "",
|
||||
"Port": "",
|
||||
"Encryption": "",
|
||||
"No Encryption": "",
|
||||
"Send From": "",
|
||||
"Send Test Email": "",
|
||||
"Email Body Template": "",
|
||||
"Live Preview": "",
|
||||
"Include configuration file as an attachment": "",
|
||||
"Send": "",
|
||||
"Sending\\.\\.\\.": "",
|
||||
"Email sent successfully!": "",
|
||||
"AmneziaWG Peer Setting": "",
|
||||
"System Status": "",
|
||||
"CPU": "",
|
||||
"Memory": "",
|
||||
"Swap Memory": "",
|
||||
"Processes": "",
|
||||
"CPU Usage": "",
|
||||
"Memory Usage": "",
|
||||
"Swap Memory Usage": "",
|
||||
"Network": "",
|
||||
"([0-9]{1,}) Interfaces": "",
|
||||
"Storage": "",
|
||||
"([0-9]{1,}) Partitions": "",
|
||||
"(.*) Used": "",
|
||||
"Untitled Peer": "",
|
||||
"Who are you sending to\\?": "",
|
||||
"What\\'s the subject\\?": "",
|
||||
"What\\'s the body\\?": ""
|
||||
}
|
||||
@@ -307,6 +307,63 @@
|
||||
"By adding peers by bulk, each peer's name will be auto generated, and Allowed IP will be assign to the next available IP\\.": "Bei der Massenerstellung wird der Name jedes Peers automatisch generiert, und die erlaubte IP wird der nächsten verfügbaren IP zugewiesen.",
|
||||
"How many peers you want to add\\?": "Wie viele Peers möchtest du hinzufügen?",
|
||||
"Adding\\.\\.\\.": "Füge hinzu...",
|
||||
"Dashboard IP Address \\& Listen Port": "",
|
||||
"Are you sure to restore this backup?\\": "Sind Sie sicher, dass Sie dieses Backup wiederherstellen möchten?"
|
||||
}
|
||||
"Dashboard IP Address \\& Listen Port": "Dashboard IP-Adresse & Empfangsport",
|
||||
"Table": "Tabelle",
|
||||
"Search": "Suchen",
|
||||
"Hop": "Hop",
|
||||
"Average RTT \\(ms\\)": "Durchschnittliche RTT ($1ms)",
|
||||
"Min RTT \\(ms\\)": "Min RTT ($1ms)",
|
||||
"Max RTT \\(ms\\)": "Max RTT ($1ms)",
|
||||
"You can visit our: ": "Besuche unsere:",
|
||||
"Official Documentation": "Offizielle Dokumentation",
|
||||
"Discord Server": "Discord Server",
|
||||
"Are you sure to restore this backup\\?": "Bist du sicher, dass du dieses Backup wiederherstellen möchtest?",
|
||||
"Download": "Herunterladen",
|
||||
"Display As": "Anzeigen als",
|
||||
"List": "Liste",
|
||||
"Grid": "Netz",
|
||||
"Protocol": "Protokoll",
|
||||
"Open File": "Datei öffnen",
|
||||
"Advanced Options": "Erweiterte Optionen",
|
||||
"Allowed IPs Validation": "Erlaubte IP\\'s Validierung",
|
||||
"Update Name": "Name ändern",
|
||||
"To update this configuration's name, WGDashboard will execute the following operations:": "",
|
||||
"Duplicate current configuration's database table and \\.conf file with the new name": "",
|
||||
"Delete current configuration's database table and \\.conf file": "",
|
||||
"Danger Zone": "Gefahrenzone",
|
||||
"Configuration File": "Konfigurationsdatei",
|
||||
"Edit Raw Configuration File": "Bearbeiten der Konfigurationsdatei",
|
||||
"Peer Configuration File": "Peer Konfigurationsdatei",
|
||||
"Share with Email": "Per E-Mail teilen",
|
||||
"Email Account": "E-Mail Konto",
|
||||
"Ready": "Bereit",
|
||||
"Port": "Port",
|
||||
"Encryption": "Verschlüsselung",
|
||||
"No Encryption": "Keine Verschlüsselung",
|
||||
"Send From": "Gesendet von",
|
||||
"Send Test Email": "Sende Test E-Mail",
|
||||
"Email Body Template": "E-Mail Textvorlage",
|
||||
"Live Preview": "Vorschau",
|
||||
"Include configuration file as an attachment": "Konfigurationsdatei als Anhang beifügen",
|
||||
"Send": "Senden",
|
||||
"Sending\\.\\.\\.": "Senden\\.\\.\\.",
|
||||
"Email sent successfully!": "E-Mail erfolgreich gesendet!",
|
||||
"AmneziaWG Peer Setting": "AmneziaWG Peer-Einstellungen",
|
||||
"System Status": "System Status",
|
||||
"CPU": "CPU",
|
||||
"Memory": "Arbeitsspeicher",
|
||||
"Swap Memory": "",
|
||||
"Processes": "Prozesse",
|
||||
"CPU Usage": "Auslastung",
|
||||
"Memory Usage": "Auslastung",
|
||||
"Swap Memory Usage": "Auslastung",
|
||||
"Network": "Netzwerk",
|
||||
"([0-9]{1,}) Interfaces": "$1 Interfaces",
|
||||
"Storage": "Speicher",
|
||||
"([0-9]{1,}) Partitions": "$1 Partionen",
|
||||
"(.*) Used": "genutzt",
|
||||
"Untitled Peer": "Unbenannter Peer",
|
||||
"Who are you sending to\\?": "",
|
||||
"What\\'s the subject\\?": "Betreff",
|
||||
"What\\'s the body\\?": "Inhalt"
|
||||
}
|
||||
|
||||
@@ -305,8 +305,8 @@
|
||||
"Failed to allow access of peer (.*)": "Fallo de habilitar acceso del peer $1",
|
||||
"Failed to save configuration through WireGuard": "Fallo de salvar configuración a través de WireGuard",
|
||||
"Allow access successfully": "Acceso permitido con éxito",
|
||||
"Deleted ([0-9]{1,}) peer\\(s\\)": "Eliminados $1 peer(s)",
|
||||
"Deleted ([0-9]{1,}) peer\\(s\\) successfully. Failed to delete ([0-9]{1,}) peer\\(s\\)": "Eliminados $1 peer(s) con éxito. Fallo al eliminar $2 peer(s)",
|
||||
"Restricted ([0-9]{1,}) peer\\(s\\)": "Restringidos $1 peer(s)",
|
||||
"Restricted ([0-9]{1,}) peer\\(s\\) successfully. Failed to restrict ([0-9]{1,}) peer\\(s\\)": "Restringidos $1 peer(s) con éxito. Fallo al restringir $2 peer(s)"
|
||||
"Deleted ([0-9]{1,}) peer\\(s\\)": "$1 peer(s) eliminado(s)",
|
||||
"Deleted ([0-9]{1,}) peer\\(s\\) successfully. Failed to delete ([0-9]{1,}) peer\\(s\\)": "$1 peer(s) eliminado(s) con éxito. Fallo al eliminar $2 peer(s)",
|
||||
"Restricted ([0-9]{1,}) peer\\(s\\)": "$1 peer(s) restringido(s)",
|
||||
"Restricted ([0-9]{1,}) peer\\(s\\) successfully. Failed to restrict ([0-9]{1,}) peer\\(s\\)": "$1 peer(s) restringido(s) con éxito. Fallo al restringir $2 peer(s)"
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user