mirror of
https://github.com/h44z/wg-portal.git
synced 2025-10-06 00:16:17 +00:00
Compare commits
30 Commits
v2.0.0-rc.
...
v2.0.1
Author | SHA1 | Date | |
---|---|---|---|
|
18296673d7 | ||
|
7df4e4b813 | ||
|
657c4307b3 | ||
|
b918fb6522 | ||
|
78deede360 | ||
|
a8fb4365cf | ||
|
0102588d23 | ||
|
6a96925be7 | ||
|
f018babca7 | ||
|
c6253e7c15 | ||
|
2a1d82251e | ||
|
99d6ce73ad | ||
|
3eb84f0ee9 | ||
|
d8a57edef9 | ||
|
4ccc59c109 | ||
|
8271dd7c1f | ||
|
4ca37089bc | ||
|
8e5d5138c0 | ||
|
c73286e11a | ||
|
b4aa6f8ef3 | ||
|
432c627f9b | ||
|
cd60761ea7 | ||
|
2c8304417b | ||
|
e6b01a9903 | ||
|
2f79dd04c0 | ||
|
e5ed9736b3 | ||
|
c8353b85ae | ||
|
6142031387 | ||
|
dd86d0ff49 | ||
|
bdd426a679 |
6
.github/workflows/docker-publish.yml
vendored
6
.github/workflows/docker-publish.yml
vendored
@@ -4,7 +4,7 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
branches: [master]
|
branches: [master]
|
||||||
push:
|
push:
|
||||||
branches: [master, stable]
|
branches: [master]
|
||||||
# Publish vX.X.X tags as releases.
|
# Publish vX.X.X tags as releases.
|
||||||
tags: ["v*.*.*"]
|
tags: ["v*.*.*"]
|
||||||
|
|
||||||
@@ -64,12 +64,12 @@ jobs:
|
|||||||
# major and major.minor tags are not available for alpha or beta releases
|
# major and major.minor tags are not available for alpha or beta releases
|
||||||
type=semver,pattern={{major}}.{{minor}}
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
type=semver,pattern={{major}}
|
type=semver,pattern={{major}}
|
||||||
|
type=semver,pattern=v{{major}}.{{minor}}
|
||||||
|
type=semver,pattern=v{{major}}
|
||||||
# add v{{major}} tag, even for beta or release-canidate releases
|
# add v{{major}} tag, even for beta or release-canidate releases
|
||||||
type=match,pattern=(v\d),group=1,enable=${{ contains(github.ref, 'beta') || contains(github.ref, 'rc') }}
|
type=match,pattern=(v\d),group=1,enable=${{ contains(github.ref, 'beta') || contains(github.ref, 'rc') }}
|
||||||
# add {{major}} tag, even for beta releases or release-canidate releases
|
# add {{major}} tag, even for beta releases or release-canidate releases
|
||||||
type=match,pattern=v(\d),group=1,enable=${{ contains(github.ref, 'beta') || contains(github.ref, 'rc') }}
|
type=match,pattern=v(\d),group=1,enable=${{ contains(github.ref, 'beta') || contains(github.ref, 'rc') }}
|
||||||
# set latest tag for default branch
|
|
||||||
type=raw,value=latest,enable={{is_default_branch}}
|
|
||||||
|
|
||||||
- name: Build and push Docker image
|
- name: Build and push Docker image
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
|
13
.github/workflows/pages.yml
vendored
13
.github/workflows/pages.yml
vendored
@@ -2,7 +2,11 @@ name: github-pages
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [master]
|
branches: [master]
|
||||||
tags: ["v*"]
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
- '!v*-alpha*'
|
||||||
|
- '!v*-beta*'
|
||||||
|
- '!v*-rc*'
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
@@ -23,6 +27,13 @@ jobs:
|
|||||||
run: pip install mike mkdocs-material[imaging] mkdocs-minify-plugin mkdocs-swagger-ui-tag
|
run: pip install mike mkdocs-material[imaging] mkdocs-minify-plugin mkdocs-swagger-ui-tag
|
||||||
|
|
||||||
- name: Publish documentation
|
- name: Publish documentation
|
||||||
|
if: ${{ ! startsWith(github.ref, 'refs/tags/') }}
|
||||||
|
run: mike deploy --push ${{ github.ref_name }}
|
||||||
|
env:
|
||||||
|
GIT_COMMITTER_NAME: "github-actions[bot]"
|
||||||
|
GIT_COMMITTER_EMAIL: "41898282+github-actions[bot]@users.noreply.github.com"
|
||||||
|
- name: Publish latest documentation
|
||||||
|
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
||||||
run: mike deploy --push --update-aliases ${{ github.ref_name }} latest
|
run: mike deploy --push --update-aliases ${{ github.ref_name }} latest
|
||||||
env:
|
env:
|
||||||
GIT_COMMITTER_NAME: "github-actions[bot]"
|
GIT_COMMITTER_NAME: "github-actions[bot]"
|
||||||
|
19
README.md
19
README.md
@@ -1,4 +1,4 @@
|
|||||||
# WireGuard Portal (v2 - testing)
|
# WireGuard Portal v2
|
||||||
|
|
||||||
[](https://github.com/h44z/wg-portal/actions/workflows/docker-publish.yml)
|
[](https://github.com/h44z/wg-portal/actions/workflows/docker-publish.yml)
|
||||||
[](https://opensource.org/licenses/MIT)
|
[](https://opensource.org/licenses/MIT)
|
||||||
@@ -8,14 +8,6 @@
|
|||||||

|

|
||||||
[](https://hub.docker.com/r/wgportal/wg-portal/)
|
[](https://hub.docker.com/r/wgportal/wg-portal/)
|
||||||
|
|
||||||
> [!CAUTION]
|
|
||||||
> Version 2 is currently under development and may contain bugs and breaking changes.
|
|
||||||
> It is not advised to use this version in production. Use version [v1](https://github.com/h44z/wg-portal/tree/stable) instead.
|
|
||||||
|
|
||||||
> [!IMPORTANT]
|
|
||||||
> Since the project was accepted by the Docker-Sponsored Open Source Program, the Docker image location has moved to [wgportal/wg-portal](https://hub.docker.com/r/wgportal/wg-portal).
|
|
||||||
> Please update the Docker image from **h44z/wg-portal** to **wgportal/wg-portal**.
|
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
<!-- Text from this line # is included in docs/documentation/overview.md -->
|
<!-- Text from this line # is included in docs/documentation/overview.md -->
|
||||||
**WireGuard Portal** is a simple, web-based configuration portal for [WireGuard](https://wireguard.com) server management.
|
**WireGuard Portal** is a simple, web-based configuration portal for [WireGuard](https://wireguard.com) server management.
|
||||||
@@ -23,7 +15,7 @@ The portal uses the WireGuard [wgctrl](https://github.com/WireGuard/wgctrl-go) l
|
|||||||
interfaces. This allows for the seamless activation or deactivation of new users without disturbing existing VPN
|
interfaces. This allows for the seamless activation or deactivation of new users without disturbing existing VPN
|
||||||
connections.
|
connections.
|
||||||
|
|
||||||
The configuration portal supports using a database (SQLite, MySQL, MsSQL or Postgres), OAuth or LDAP
|
The configuration portal supports using a database (SQLite, MySQL, MsSQL, or Postgres), OAuth or LDAP
|
||||||
(Active Directory or OpenLDAP) as a user source for authentication and profile data.
|
(Active Directory or OpenLDAP) as a user source for authentication and profile data.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
@@ -44,7 +36,7 @@ The configuration portal supports using a database (SQLite, MySQL, MsSQL or Post
|
|||||||
* Handles route and DNS settings like wg-quick does
|
* Handles route and DNS settings like wg-quick does
|
||||||
* Exposes Prometheus metrics for monitoring and alerting
|
* Exposes Prometheus metrics for monitoring and alerting
|
||||||
* REST API for management and client deployment
|
* REST API for management and client deployment
|
||||||
* Webhook for custom actions on peer, interface or user updates
|
* Webhook for custom actions on peer, interface, or user updates
|
||||||
|
|
||||||
<!-- Text to this line # is included in docs/documentation/overview.md -->
|
<!-- Text to this line # is included in docs/documentation/overview.md -->
|
||||||

|

|
||||||
@@ -68,3 +60,8 @@ For the complete documentation visit [wgportal.org](https://wgportal.org).
|
|||||||
## License
|
## License
|
||||||
|
|
||||||
* MIT License. [MIT](LICENSE.txt) or <https://opensource.org/licenses/MIT>
|
* MIT License. [MIT](LICENSE.txt) or <https://opensource.org/licenses/MIT>
|
||||||
|
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> Since the project was accepted by the Docker-Sponsored Open Source Program, the Docker image location has moved to [wgportal/wg-portal](https://hub.docker.com/r/wgportal/wg-portal).
|
||||||
|
> Please update the Docker image from **h44z/wg-portal** to **wgportal/wg-portal**.
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
services:
|
services:
|
||||||
wg-portal:
|
wg-portal:
|
||||||
image: wgportal/wg-portal:latest
|
image: wgportal/wg-portal:v2
|
||||||
container_name: wg-portal
|
container_name: wg-portal
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
logging:
|
logging:
|
||||||
@@ -10,6 +10,7 @@ services:
|
|||||||
max-file: "3"
|
max-file: "3"
|
||||||
cap_add:
|
cap_add:
|
||||||
- NET_ADMIN
|
- NET_ADMIN
|
||||||
|
# Use host network mode for WireGuard and the UI. Ensure that access to the UI is properly secured.
|
||||||
network_mode: "host"
|
network_mode: "host"
|
||||||
volumes:
|
volumes:
|
||||||
# left side is the host path, right side is the container path
|
# left side is the host path, right side is the container path
|
||||||
|
@@ -15,7 +15,7 @@ web:
|
|||||||
site_title: My WireGuard Server
|
site_title: My WireGuard Server
|
||||||
site_company_name: My Company
|
site_company_name: My Company
|
||||||
listening_address: :8080
|
listening_address: :8080
|
||||||
external_url: https://my.externa-domain.com
|
external_url: https://my.external-domain.com
|
||||||
csrf_secret: super-s3cr3t-csrf
|
csrf_secret: super-s3cr3t-csrf
|
||||||
session_secret: super-s3cr3t-session
|
session_secret: super-s3cr3t-session
|
||||||
request_logging: true
|
request_logging: true
|
||||||
@@ -72,7 +72,8 @@ auth:
|
|||||||
|
|
||||||
auth:
|
auth:
|
||||||
oidc:
|
oidc:
|
||||||
# a sample Entra ID provider with environment variable substitution
|
# A sample Entra ID provider with environment variable substitution.
|
||||||
|
# Only users with an @outlook.com email address are allowed to register or login.
|
||||||
- id: azure
|
- id: azure
|
||||||
provider_name: azure
|
provider_name: azure
|
||||||
display_name: Login with</br>Entra ID
|
display_name: Login with</br>Entra ID
|
||||||
@@ -80,6 +81,8 @@ auth:
|
|||||||
base_url: "https://login.microsoftonline.com/${AZURE_TENANT_ID}/v2.0"
|
base_url: "https://login.microsoftonline.com/${AZURE_TENANT_ID}/v2.0"
|
||||||
client_id: "${AZURE_CLIENT_ID}"
|
client_id: "${AZURE_CLIENT_ID}"
|
||||||
client_secret: "${AZURE_CLIENT_SECRET}"
|
client_secret: "${AZURE_CLIENT_SECRET}"
|
||||||
|
allowed_domains:
|
||||||
|
- "outlook.com"
|
||||||
extra_scopes:
|
extra_scopes:
|
||||||
- profile
|
- profile
|
||||||
- email
|
- email
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
This page provides an overview of **all available configuration options** for WireGuard Portal.
|
This page provides an overview of **all available configuration options** for WireGuard Portal.
|
||||||
|
|
||||||
You can supply these configurations in a **YAML** file (e.g. `config.yaml`) when starting the Portal.
|
You can supply these configurations in a **YAML** file when starting the Portal.
|
||||||
The path of the configuration file defaults to **config/config.yaml** (or config/config.yml) in the working directory of the executable.
|
The path of the configuration file defaults to `config/config.yaml` (or `config/config.yml`) in the working directory of the executable.
|
||||||
It is possible to override configuration filepath using the environment variable `WG_PORTAL_CONFIG`.
|
It is possible to override the configuration filepath using the environment variable `WG_PORTAL_CONFIG`.
|
||||||
For example: `WG_PORTAL_CONFIG=/etc/wg-portal/config.yaml ./wg-portal`.
|
For example: `WG_PORTAL_CONFIG=/etc/wg-portal/config.yaml ./wg-portal`.
|
||||||
Also, environment variable substitution in config file is supported. Refer to [syntax](https://github.com/a8m/envsubst?tab=readme-ov-file#docs).
|
Also, environment variable substitution in the config file is supported. Refer to the [syntax](https://github.com/a8m/envsubst?tab=readme-ov-file#docs).
|
||||||
|
|
||||||
Configuration examples are available on the [Examples](./examples.md) page.
|
Configuration examples are available on the [Examples](./examples.md) page.
|
||||||
|
|
||||||
@@ -15,6 +15,7 @@ Configuration examples are available on the [Examples](./examples.md) page.
|
|||||||
core:
|
core:
|
||||||
admin_user: admin@wgportal.local
|
admin_user: admin@wgportal.local
|
||||||
admin_password: wgportal
|
admin_password: wgportal
|
||||||
|
admin_api_token: ""
|
||||||
editable_keys: true
|
editable_keys: true
|
||||||
create_default_peer: false
|
create_default_peer: false
|
||||||
create_default_peer_on_creation: false
|
create_default_peer_on_creation: false
|
||||||
@@ -35,6 +36,7 @@ advanced:
|
|||||||
config_storage_path: ""
|
config_storage_path: ""
|
||||||
expiry_check_interval: 15m
|
expiry_check_interval: 15m
|
||||||
rule_prio_offset: 20000
|
rule_prio_offset: 20000
|
||||||
|
route_table_offset: 20000
|
||||||
api_admin_only: true
|
api_admin_only: true
|
||||||
|
|
||||||
database:
|
database:
|
||||||
@@ -42,6 +44,7 @@ database:
|
|||||||
slow_query_threshold: "0"
|
slow_query_threshold: "0"
|
||||||
type: sqlite
|
type: sqlite
|
||||||
dsn: data/sqlite.db
|
dsn: data/sqlite.db
|
||||||
|
encryption_passphrase: ""
|
||||||
|
|
||||||
statistics:
|
statistics:
|
||||||
use_ping_checks: true
|
use_ping_checks: true
|
||||||
@@ -79,6 +82,7 @@ web:
|
|||||||
session_secret: very_secret
|
session_secret: very_secret
|
||||||
csrf_secret: extremely_secret
|
csrf_secret: extremely_secret
|
||||||
request_logging: false
|
request_logging: false
|
||||||
|
expose_host_info: false
|
||||||
cert_file: ""
|
cert_file: ""
|
||||||
key_File: ""
|
key_File: ""
|
||||||
|
|
||||||
@@ -282,7 +286,7 @@ Controls how WireGuard Portal collects and reports usage statistics, including p
|
|||||||
|
|
||||||
### `listening_address`
|
### `listening_address`
|
||||||
- **Default:** `:8787`
|
- **Default:** `:8787`
|
||||||
- **Description:** Address and port for the integrated Prometheus metric server (e.g., `:8787` or `127.0.0.1:8888`).
|
- **Description:** Address and port for the integrated Prometheus metric server (e.g., `:8787` or `127.0.0.1:8787`).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -364,6 +368,10 @@ Below are the properties for each OIDC provider entry inside `auth.oidc`:
|
|||||||
- **Default:** *(empty)*
|
- **Default:** *(empty)*
|
||||||
- **Description:** A list of additional OIDC scopes (e.g., `profile`, `email`).
|
- **Description:** A list of additional OIDC scopes (e.g., `profile`, `email`).
|
||||||
|
|
||||||
|
#### `allowed_domains`
|
||||||
|
- **Default:** *(empty)*
|
||||||
|
- **Description:** A list of allowlisted domains. Only users with email addresses in these domains can log in or register. This is useful for restricting access to specific organizations or groups.
|
||||||
|
|
||||||
#### `field_map`
|
#### `field_map`
|
||||||
- **Default:** *(empty)*
|
- **Default:** *(empty)*
|
||||||
- **Description:** Maps OIDC claims to WireGuard Portal user fields.
|
- **Description:** Maps OIDC claims to WireGuard Portal user fields.
|
||||||
@@ -433,6 +441,10 @@ Below are the properties for each OAuth provider entry inside `auth.oauth`:
|
|||||||
- **Default:** *(empty)*
|
- **Default:** *(empty)*
|
||||||
- **Description:** A list of OAuth scopes.
|
- **Description:** A list of OAuth scopes.
|
||||||
|
|
||||||
|
#### `allowed_domains`
|
||||||
|
- **Default:** *(empty)*
|
||||||
|
- **Description:** A list of allowlisted domains. Only users with email addresses in these domains can log in or register. This is useful for restricting access to specific organizations or groups.
|
||||||
|
|
||||||
#### `field_map`
|
#### `field_map`
|
||||||
- **Default:** *(empty)*
|
- **Default:** *(empty)*
|
||||||
- **Description:** Maps OAuth attributes to WireGuard Portal fields.
|
- **Description:** Maps OAuth attributes to WireGuard Portal fields.
|
||||||
@@ -576,7 +588,8 @@ Without a valid `external_url`, the login process may fail due to CSRF protectio
|
|||||||
|
|
||||||
### `listening_address`
|
### `listening_address`
|
||||||
- **Default:** `:8888`
|
- **Default:** `:8888`
|
||||||
- **Description:** The listening port of the web server.
|
- **Description:** The listening address and port for the web server (e.g., `:8888` to bind on all interfaces or `127.0.0.1:8888` to bind only on the loopback interface).
|
||||||
|
Ensure that access to WireGuard Portal is protected against unauthorized access, especially if binding to all interfaces.
|
||||||
|
|
||||||
### `external_url`
|
### `external_url`
|
||||||
- **Default:** `http://localhost:8888`
|
- **Default:** `http://localhost:8888`
|
||||||
@@ -607,6 +620,10 @@ Without a valid `external_url`, the login process may fail due to CSRF protectio
|
|||||||
- **Default:** `false`
|
- **Default:** `false`
|
||||||
- **Description:** Log all HTTP requests.
|
- **Description:** Log all HTTP requests.
|
||||||
|
|
||||||
|
### `expose_host_info`
|
||||||
|
- **Default:** `false`
|
||||||
|
- **Description:** Expose the hostname and version of the WireGuard Portal server in an HTTP header. This is useful for debugging but may expose sensitive information.
|
||||||
|
|
||||||
### `cert_file`
|
### `cert_file`
|
||||||
- **Default:** *(empty)*
|
- **Default:** *(empty)*
|
||||||
- **Description:** (Optional) Path to the TLS certificate file.
|
- **Description:** (Optional) Path to the TLS certificate file.
|
||||||
|
@@ -3,23 +3,31 @@ These binary versions can be manually downloaded and installed.
|
|||||||
|
|
||||||
## Download
|
## Download
|
||||||
|
|
||||||
|
Make sure that you download the correct binary for your architecture. The available binaries are:
|
||||||
|
|
||||||
|
- `wg-portal_linux_amd64` - Linux x86_64
|
||||||
|
- `wg-portal_linux_arm64` - Linux ARM 64-bit
|
||||||
|
- `wg-portal_linux_arm_v7` - Linux ARM 32-bit
|
||||||
|
|
||||||
With `curl`:
|
With `curl`:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
curl -L -o wg-portal https://github.com/h44z/wg-portal/releases/download/${WG_PORTAL_VERSION}/wg-portal_linux_amd64
|
curl -L -o wg-portal https://github.com/h44z/wg-portal/releases/download/${WG_PORTAL_VERSION}/wg-portal_linux_amd64
|
||||||
```
|
```
|
||||||
|
|
||||||
With `wget`:
|
With `wget`:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
wget -O wg-portal https://github.com/h44z/wg-portal/releases/download/${WG_PORTAL_VERSION}/wg-portal_linux_amd64
|
wget -O wg-portal https://github.com/h44z/wg-portal/releases/download/${WG_PORTAL_VERSION}/wg-portal_linux_amd64
|
||||||
```
|
```
|
||||||
|
|
||||||
with `gh cli`:
|
with `gh cli`:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
gh release download ${WG_PORTAL_VERSION} --repo h44z/wg-portal --output wg-portal --pattern '*amd64'
|
gh release download ${WG_PORTAL_VERSION} --repo h44z/wg-portal --output wg-portal --pattern '*amd64'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
@@ -28,7 +36,7 @@ sudo mkdir -p /opt/wg-portal
|
|||||||
sudo install wg-portal /opt/wg-portal/
|
sudo install wg-portal /opt/wg-portal/
|
||||||
```
|
```
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased versions (master branch builds)
|
||||||
|
|
||||||
|
Unreleased versions can be fetched directly from the artifacts section of the [GitHub Workflow](https://github.com/h44z/wg-portal/actions/workflows/docker-publish.yml?query=branch%3Amaster).
|
||||||
|
|
||||||
Unreleased versions could be downloaded from
|
|
||||||
[GitHub Workflow](https://github.com/h44z/wg-portal/actions/workflows/docker-publish.yml?query=branch%3Amaster) artifacts also.
|
|
||||||
|
@@ -10,10 +10,10 @@ The recommended method for deploying WireGuard Portal is via Docker Compose for
|
|||||||
A sample docker-compose.yml (managing WireGuard interfaces directly on the host) is provided below:
|
A sample docker-compose.yml (managing WireGuard interfaces directly on the host) is provided below:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
--8<-- "docker-compose.yml::17"
|
--8<-- "docker-compose.yml::19"
|
||||||
```
|
```
|
||||||
|
|
||||||
By default, the webserver is listening on port **8888**.
|
By default, the webserver for the UI is listening on port **8888** on all available interfaces.
|
||||||
|
|
||||||
Volumes for `/app/data` and `/app/config` should be used ensure data persistence across container restarts.
|
Volumes for `/app/data` and `/app/config` should be used ensure data persistence across container restarts.
|
||||||
|
|
||||||
@@ -32,6 +32,8 @@ WireGuard Portal supports managing WireGuard interfaces through three distinct d
|
|||||||
network_mode: "host"
|
network_mode: "host"
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
> :warning: If host networking is used, the WireGuard Portal UI will be accessible on all the host's IP addresses if the listening address is set to `:8888` in the configuration file.
|
||||||
|
To avoid this, you can bind the listening address to a specific IP address, for example, the loopback address (`127.0.0.1:8888`). It is also possible to deploy firewall rules to restrict access to the WireGuard Portal UI.
|
||||||
|
|
||||||
- **Within the WireGuard Portal Docker container**:
|
- **Within the WireGuard Portal Docker container**:
|
||||||
WireGuard interfaces can be managed directly from within the WireGuard Portal container itself.
|
WireGuard interfaces can be managed directly from within the WireGuard Portal container itself.
|
||||||
@@ -39,7 +41,7 @@ WireGuard Portal supports managing WireGuard interfaces through three distinct d
|
|||||||
```yaml
|
```yaml
|
||||||
services:
|
services:
|
||||||
wg-portal:
|
wg-portal:
|
||||||
image: wgportal/wg-portal:latest
|
image: wgportal/wg-portal:v2
|
||||||
container_name: wg-portal
|
container_name: wg-portal
|
||||||
...
|
...
|
||||||
cap_add:
|
cap_add:
|
||||||
@@ -65,7 +67,7 @@ WireGuard Portal supports managing WireGuard interfaces through three distinct d
|
|||||||
```yaml
|
```yaml
|
||||||
services:
|
services:
|
||||||
wg-portal:
|
wg-portal:
|
||||||
image: wgportal/wg-portal:latest
|
image: wgportal/wg-portal:v2
|
||||||
container_name: wg-portal
|
container_name: wg-portal
|
||||||
...
|
...
|
||||||
cap_add:
|
cap_add:
|
||||||
@@ -108,31 +110,33 @@ WireGuard Portal supports managing WireGuard interfaces through three distinct d
|
|||||||
## Image Versioning
|
## Image Versioning
|
||||||
|
|
||||||
All images are hosted on Docker Hub at [https://hub.docker.com/r/wgportal/wg-portal](https://hub.docker.com/r/wgportal/wg-portal) or in the [GitHub Container Registry](https://github.com/h44z/wg-portal/pkgs/container/wg-portal).
|
All images are hosted on Docker Hub at [https://hub.docker.com/r/wgportal/wg-portal](https://hub.docker.com/r/wgportal/wg-portal) or in the [GitHub Container Registry](https://github.com/h44z/wg-portal/pkgs/container/wg-portal).
|
||||||
|
|
||||||
|
Version **2** is the current stable release. Version **1** has moved to legacy status and is no longer recommended.
|
||||||
|
|
||||||
There are three types of tags in the repository:
|
There are three types of tags in the repository:
|
||||||
|
|
||||||
#### Semantic versioned tags
|
#### Semantic versioned tags
|
||||||
|
|
||||||
For example, `2.0.0-rc.1` or `v2.0.0-rc.1`.
|
For example, `2.0.0-rc.1` or `v2.0.0-rc.1`.
|
||||||
|
|
||||||
These are official releases of WireGuard Portal. They correspond to the GitHub tags that we make, and you can see the release notes for them here: [https://github.com/h44z/wg-portal/releases](https://github.com/h44z/wg-portal/releases).
|
These are official releases of WireGuard Portal. For production deployments of WireGuard Portal, we strongly recommend using one of these versioned tags instead of the latest or canary tags.
|
||||||
|
|
||||||
Once these tags show up in this repository, they will never change.
|
There are different types of these tags:
|
||||||
|
|
||||||
For production deployments of WireGuard Portal, we strongly recommend using one of these tags, e.g. **wgportal/wg-portal:1.0.19**, instead of the latest or canary tags.
|
- Major version tags: `v2` or `2`. These tags always refer to the latest image for WireGuard Portal version **2**.
|
||||||
|
- Minor version tags: `v2.x` or `2.0`. These tags always refer to the latest image for WireGuard Portal version **2.x**.
|
||||||
|
- Specific version tags (patch version): `v2.0.0` or `2.0.0`. These tags denote a very specific release. They correspond to the GitHub tags that we make, and you can see the release notes for them here: [https://github.com/h44z/wg-portal/releases](https://github.com/h44z/wg-portal/releases). Once these tags for a specific version show up in the Docker repository, they will never change.
|
||||||
|
|
||||||
If you only want to stay at the same major or major+minor version, use either `v[MAJOR]` or `[MAJOR].[MINOR]` tags. For example `v1` or `1.0`.
|
#### The `latest` tag
|
||||||
|
|
||||||
Version **1** is currently **stable**, version **2** is in **development**.
|
The lastest tag is the latest stable release of WireGuard Portal. For version **2**, this is the same as the `v2` tag.
|
||||||
|
|
||||||
#### latest
|
#### The `master` tag
|
||||||
|
|
||||||
This is the most recent build to master! It changes a lot and is very unstable.
|
This is the most recent build to the main branch! It changes a lot and is very unstable.
|
||||||
|
|
||||||
We recommend that you don't use it except for development purposes.
|
We recommend that you don't use it except for development purposes or to test the latest features.
|
||||||
|
|
||||||
#### Branch tags
|
|
||||||
|
|
||||||
For each commit in the master and the stable branch, a corresponding Docker image is build. These images use the `master` or `stable` tags.
|
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
@@ -149,7 +153,7 @@ You should mount those directories as a volume:
|
|||||||
|
|
||||||
A detailed description of the configuration options can be found [here](../configuration/overview.md).
|
A detailed description of the configuration options can be found [here](../configuration/overview.md).
|
||||||
|
|
||||||
If you want to access configuration files in wg-quick format, you can mount the `/etc/wireguard` directory to a location of your choice.
|
If you want to access configuration files in wg-quick format, you can mount the `/etc/wireguard` directory inside the container to a location of your choice.
|
||||||
Also enable the `config_storage_path` option in the configuration file:
|
Also enable the `config_storage_path` option in the configuration file:
|
||||||
```yaml
|
```yaml
|
||||||
advanced:
|
advanced:
|
||||||
|
@@ -44,7 +44,7 @@ services:
|
|||||||
- 'traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https'
|
- 'traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https'
|
||||||
|
|
||||||
wg-portal:
|
wg-portal:
|
||||||
image: wgportal/wg-portal:latest
|
image: wgportal/wg-portal:v2
|
||||||
container_name: wg-portal
|
container_name: wg-portal
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
logging:
|
logging:
|
||||||
|
@@ -22,4 +22,5 @@ make build
|
|||||||
## Install
|
## Install
|
||||||
|
|
||||||
Compiled binary will be available in `./dist` directory.
|
Compiled binary will be available in `./dist` directory.
|
||||||
|
|
||||||
For installation instructions, check the [Binaries](./binaries.md) section.
|
For installation instructions, check the [Binaries](./binaries.md) section.
|
||||||
|
@@ -13,7 +13,7 @@ By default, WG-Portal exposes Prometheus metrics on port `8787` if interface/pee
|
|||||||
|
|
||||||
## Prometheus Config
|
## Prometheus Config
|
||||||
|
|
||||||
Add following scrape job to your Prometheus config file:
|
Add the following scrape job to your Prometheus config file:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
# prometheus.yaml
|
# prometheus.yaml
|
||||||
|
@@ -1 +1 @@
|
|||||||
--8<-- "README.md:20:47"
|
--8<-- "README.md:12:41"
|
||||||
|
@@ -692,6 +692,7 @@ paths:
|
|||||||
tags:
|
tags:
|
||||||
- Interfaces
|
- Interfaces
|
||||||
put:
|
put:
|
||||||
|
description: This endpoint updates an existing interface with the provided data. All required fields must be filled (e.g. name, private key, public key, ...).
|
||||||
operationId: interfaces_handleUpdatePut
|
operationId: interfaces_handleUpdatePut
|
||||||
parameters:
|
parameters:
|
||||||
- description: The interface identifier.
|
- description: The interface identifier.
|
||||||
@@ -739,6 +740,7 @@ paths:
|
|||||||
- Interfaces
|
- Interfaces
|
||||||
/interface/new:
|
/interface/new:
|
||||||
post:
|
post:
|
||||||
|
description: This endpoint creates a new interface with the provided data. All required fields must be filled (e.g. name, private key, public key, ...).
|
||||||
operationId: interfaces_handleCreatePost
|
operationId: interfaces_handleCreatePost
|
||||||
parameters:
|
parameters:
|
||||||
- description: The interface data.
|
- description: The interface data.
|
||||||
@@ -779,6 +781,34 @@ paths:
|
|||||||
summary: Create a new interface record.
|
summary: Create a new interface record.
|
||||||
tags:
|
tags:
|
||||||
- Interfaces
|
- Interfaces
|
||||||
|
/interface/prepare:
|
||||||
|
get:
|
||||||
|
description: This endpoint returns a new interface with default values (fresh key pair, valid name, new IP address pool, ...).
|
||||||
|
operationId: interfaces_handlePrepareGet
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/models.Interface'
|
||||||
|
"401":
|
||||||
|
description: Unauthorized
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/models.Error'
|
||||||
|
"403":
|
||||||
|
description: Forbidden
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/models.Error'
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/models.Error'
|
||||||
|
security:
|
||||||
|
- BasicAuth: []
|
||||||
|
summary: Prepare a new interface record.
|
||||||
|
tags:
|
||||||
|
- Interfaces
|
||||||
/metrics/by-interface/{id}:
|
/metrics/by-interface/{id}:
|
||||||
get:
|
get:
|
||||||
operationId: metrics_handleMetricsForInterfaceGet
|
operationId: metrics_handleMetricsForInterfaceGet
|
||||||
@@ -967,7 +997,7 @@ paths:
|
|||||||
tags:
|
tags:
|
||||||
- Peers
|
- Peers
|
||||||
put:
|
put:
|
||||||
description: Only admins can update existing records.
|
description: Only admins can update existing records. The peer record must contain all required fields (e.g., public key, allowed IPs).
|
||||||
operationId: peers_handleUpdatePut
|
operationId: peers_handleUpdatePut
|
||||||
parameters:
|
parameters:
|
||||||
- description: The peer identifier.
|
- description: The peer identifier.
|
||||||
@@ -1078,7 +1108,7 @@ paths:
|
|||||||
- Peers
|
- Peers
|
||||||
/peer/new:
|
/peer/new:
|
||||||
post:
|
post:
|
||||||
description: Only admins can create new records.
|
description: Only admins can create new records. The peer record must contain all required fields (e.g., public key, allowed IPs).
|
||||||
operationId: peers_handleCreatePost
|
operationId: peers_handleCreatePost
|
||||||
parameters:
|
parameters:
|
||||||
- description: The peer data.
|
- description: The peer data.
|
||||||
@@ -1119,6 +1149,48 @@ paths:
|
|||||||
summary: Create a new peer record.
|
summary: Create a new peer record.
|
||||||
tags:
|
tags:
|
||||||
- Peers
|
- Peers
|
||||||
|
/peer/prepare/{id}:
|
||||||
|
get:
|
||||||
|
description: This endpoint is used to prepare a new peer record. The returned data contains a fresh key pair and valid ip address.
|
||||||
|
operationId: peers_handlePrepareGet
|
||||||
|
parameters:
|
||||||
|
- description: The interface identifier.
|
||||||
|
in: path
|
||||||
|
name: id
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/models.Peer'
|
||||||
|
"400":
|
||||||
|
description: Bad Request
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/models.Error'
|
||||||
|
"401":
|
||||||
|
description: Unauthorized
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/models.Error'
|
||||||
|
"403":
|
||||||
|
description: Forbidden
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/models.Error'
|
||||||
|
"404":
|
||||||
|
description: Not Found
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/models.Error'
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/models.Error'
|
||||||
|
security:
|
||||||
|
- BasicAuth: []
|
||||||
|
summary: Prepare a new peer record for the given WireGuard interface.
|
||||||
|
tags:
|
||||||
|
- Peers
|
||||||
/provisioning/data/peer-config:
|
/provisioning/data/peer-config:
|
||||||
get:
|
get:
|
||||||
description: Normal users can only access their own record. Admins can access all records.
|
description: Normal users can only access their own record. Admins can access all records.
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
For production deployments of WireGuard Portal, we strongly recommend using version 1.
|
Major upgrades between different versions may require special procedures, which are described in the following sections.
|
||||||
If you want to use version 2, please be aware that it is still a release candidate and not yet fully stable.
|
|
||||||
|
|
||||||
## Upgrade from v1 to v2
|
## Upgrade from v1 to v2
|
||||||
|
|
||||||
@@ -14,7 +13,9 @@ To upgrade from a previous SQLite database, start wg-portal like:
|
|||||||
./wg-portal-amd64 -migrateFrom=old_wg_portal.db
|
./wg-portal-amd64 -migrateFrom=old_wg_portal.db
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also specify the database type using the parameter **-migrateFromType**, supported types: mysql, mssql, postgres or sqlite.
|
You can also specify the database type using the parameter **-migrateFromType**.
|
||||||
|
Supported database types: `mysql`, `mssql`, `postgres` or `sqlite`.
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
@@ -29,8 +30,8 @@ If you are using Docker, you can adapt the docker-compose.yml file to start the
|
|||||||
```yaml
|
```yaml
|
||||||
services:
|
services:
|
||||||
wg-portal:
|
wg-portal:
|
||||||
image: wgportal/wg-portal:latest
|
image: wgportal/wg-portal:v2
|
||||||
# ... other settings
|
# ... other settings
|
||||||
restart: no
|
restart: no
|
||||||
command: ["-migrateFrom=/app/data/wg_portal.db"]
|
command: ["-migrateFrom=/app/data/old_wg_portal.db"]
|
||||||
```
|
```
|
||||||
|
@@ -24,7 +24,7 @@
|
|||||||
<div id="toasts"></div>
|
<div id="toasts"></div>
|
||||||
|
|
||||||
<!-- main application -->
|
<!-- main application -->
|
||||||
<div id="app"></div>
|
<div id="app" class="d-flex flex-column flex-grow-1"></div>
|
||||||
|
|
||||||
<!-- vue teleport will add modals and dialogs here -->
|
<!-- vue teleport will add modals and dialogs here -->
|
||||||
<div id="modals"></div>
|
<div id="modals"></div>
|
||||||
|
20
frontend/package-lock.json
generated
20
frontend/package-lock.json
generated
@@ -29,7 +29,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-vue": "^5.2.3",
|
"@vitejs/plugin-vue": "^5.2.3",
|
||||||
"sass-embedded": "^1.86.3",
|
"sass-embedded": "^1.86.3",
|
||||||
"vite": "6.3.2"
|
"vite": "6.3.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/helper-string-parser": {
|
"node_modules/@babel/helper-string-parser": {
|
||||||
@@ -2012,13 +2012,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tinyglobby": {
|
"node_modules/tinyglobby": {
|
||||||
"version": "0.2.12",
|
"version": "0.2.13",
|
||||||
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz",
|
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz",
|
||||||
"integrity": "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==",
|
"integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fdir": "^6.4.3",
|
"fdir": "^6.4.4",
|
||||||
"picomatch": "^4.0.2"
|
"picomatch": "^4.0.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -2043,18 +2043,18 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "6.3.2",
|
"version": "6.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-6.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-6.3.4.tgz",
|
||||||
"integrity": "sha512-ZSvGOXKGceizRQIZSz7TGJ0pS3QLlVY/9hwxVh17W3re67je1RKYzFHivZ/t0tubU78Vkyb9WnHPENSBCzbckg==",
|
"integrity": "sha512-BiReIiMS2fyFqbqNT/Qqt4CVITDU9M9vE+DKcVAsB+ZV0wvTKd+3hMbkpxz1b+NmEDMegpVbisKiAZOnvO92Sw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.25.0",
|
"esbuild": "^0.25.0",
|
||||||
"fdir": "^6.4.3",
|
"fdir": "^6.4.4",
|
||||||
"picomatch": "^4.0.2",
|
"picomatch": "^4.0.2",
|
||||||
"postcss": "^8.5.3",
|
"postcss": "^8.5.3",
|
||||||
"rollup": "^4.34.9",
|
"rollup": "^4.34.9",
|
||||||
"tinyglobby": "^0.2.12"
|
"tinyglobby": "^0.2.13"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"vite": "bin/vite.js"
|
"vite": "bin/vite.js"
|
||||||
|
@@ -29,6 +29,6 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-vue": "^5.2.3",
|
"@vitejs/plugin-vue": "^5.2.3",
|
||||||
"sass-embedded": "^1.86.3",
|
"sass-embedded": "^1.86.3",
|
||||||
"vite": "6.3.2"
|
"vite": "6.3.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -140,6 +140,7 @@ const currentYear = ref(new Date().getFullYear())
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</footer></template>
|
</footer>
|
||||||
|
</template>
|
||||||
|
|
||||||
<style></style>
|
<style></style>
|
||||||
|
@@ -5,6 +5,10 @@ $web-font-path: false;
|
|||||||
@import "bootstrap/scss/bootstrap";
|
@import "bootstrap/scss/bootstrap";
|
||||||
@import "bootswatch/dist/lux/bootswatch";
|
@import "bootswatch/dist/lux/bootswatch";
|
||||||
|
|
||||||
|
// fix strange border width bug in bootswatch 5.3
|
||||||
|
:root {
|
||||||
|
--bs-border-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
// for future use, once bootswatch supports @use
|
// for future use, once bootswatch supports @use
|
||||||
/*
|
/*
|
||||||
|
@@ -26,7 +26,7 @@
|
|||||||
"placeholder": "Bitte geben Sie Ihren Benutzernamen ein"
|
"placeholder": "Bitte geben Sie Ihren Benutzernamen ein"
|
||||||
},
|
},
|
||||||
"password": {
|
"password": {
|
||||||
"label": "Kennwort",
|
"label": "Passwort",
|
||||||
"placeholder": "Bitte geben Sie Ihr Passwort ein"
|
"placeholder": "Bitte geben Sie Ihr Passwort ein"
|
||||||
},
|
},
|
||||||
"button": "Anmelden"
|
"button": "Anmelden"
|
||||||
@@ -38,6 +38,7 @@
|
|||||||
"lang": "Sprache ändern",
|
"lang": "Sprache ändern",
|
||||||
"profile": "Mein Profil",
|
"profile": "Mein Profil",
|
||||||
"settings": "Einstellungen",
|
"settings": "Einstellungen",
|
||||||
|
"audit": "Event Protokoll",
|
||||||
"login": "Anmelden",
|
"login": "Anmelden",
|
||||||
"logout": "Abmelden",
|
"logout": "Abmelden",
|
||||||
"keygen": "Schlüsselgenerator"
|
"keygen": "Schlüsselgenerator"
|
||||||
@@ -80,77 +81,77 @@
|
|||||||
},
|
},
|
||||||
"interfaces": {
|
"interfaces": {
|
||||||
"headline": "Schnittstellenverwaltung",
|
"headline": "Schnittstellenverwaltung",
|
||||||
"headline-peers": "Current VPN Peers",
|
"headline-peers": "Aktuelle VPN-Peers",
|
||||||
"headline-endpoints": "Current Endpoints",
|
"headline-endpoints": "Aktuelle Endpunkte",
|
||||||
"no-interface": {
|
"no-interface": {
|
||||||
"default-selection": "No Interface available",
|
"default-selection": "Keine Schnittstelle verfügbar",
|
||||||
"headline": "No interfaces found...",
|
"headline": "Keine Schnittstellen gefunden...",
|
||||||
"abstract": "Click the plus button above to create a new WireGuard interface."
|
"abstract": "Klicken Sie auf die Plus-Schaltfläche oben, um eine neue WireGuard-Schnittstelle zu erstellen."
|
||||||
},
|
},
|
||||||
"no-peer": {
|
"no-peer": {
|
||||||
"headline": "No peers available",
|
"headline": "Keine Peers verfügbar",
|
||||||
"abstract": "Currently, there are no peers available for the selected WireGuard interface."
|
"abstract": "Derzeit sind keine Peers für die ausgewählte WireGuard-Schnittstelle verfügbar."
|
||||||
},
|
},
|
||||||
"table-heading": {
|
"table-heading": {
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
"user": "User",
|
"user": "Benutzer",
|
||||||
"ip": "IP's",
|
"ip": "IP's",
|
||||||
"endpoint": "Endpoint",
|
"endpoint": "Endpunkt",
|
||||||
"status": "Status"
|
"status": "Status"
|
||||||
},
|
},
|
||||||
"interface": {
|
"interface": {
|
||||||
"headline": "Interface status for",
|
"headline": "Schnittstellenstatus für",
|
||||||
"mode": "mode",
|
"mode": "Modus",
|
||||||
"key": "Public Key",
|
"key": "Öffentlicher Schlüssel",
|
||||||
"endpoint": "Public Endpoint",
|
"endpoint": "Öffentlicher Endpunkt",
|
||||||
"port": "Listening Port",
|
"port": "Port",
|
||||||
"peers": "Enabled Peers",
|
"peers": "Aktive Peers",
|
||||||
"total-peers": "Total Peers",
|
"total-peers": "Gesamtanzahl Peers",
|
||||||
"endpoints": "Enabled Endpoints",
|
"endpoints": "Aktive Endpunkte",
|
||||||
"total-endpoints": "Total Endpoints",
|
"total-endpoints": "Gesamtanzahl Endpunkte",
|
||||||
"ip": "IP Address",
|
"ip": "IP-Adresse",
|
||||||
"default-allowed-ip": "Default allowed IPs",
|
"default-allowed-ip": "Standard Erlaubte-IPs",
|
||||||
"dns": "DNS Servers",
|
"dns": "DNS-Server",
|
||||||
"mtu": "MTU",
|
"mtu": "MTU",
|
||||||
"default-keep-alive": "Default Keepalive Interval",
|
"default-keep-alive": "Standard Keepalive-Intervall",
|
||||||
"button-show-config": "Show configuration",
|
"button-show-config": "Konfiguration anzeigen",
|
||||||
"button-download-config": "Download configuration",
|
"button-download-config": "Konfiguration herunterladen",
|
||||||
"button-store-config": "Store configuration for wg-quick",
|
"button-store-config": "Konfiguration für wg-quick speichern",
|
||||||
"button-edit": "Edit interface"
|
"button-edit": "Schnittstelle bearbeiten"
|
||||||
},
|
},
|
||||||
"button-add-interface": "Add Interface",
|
"button-add-interface": "Schnittstelle hinzufügen",
|
||||||
"button-add-peer": "Add Peer",
|
"button-add-peer": "Peer hinzufügen",
|
||||||
"button-add-peers": "Add Multiple Peers",
|
"button-add-peers": "Mehrere Peers hinzufügen",
|
||||||
"button-show-peer": "Show Peer",
|
"button-show-peer": "Peer anzeigen",
|
||||||
"button-edit-peer": "Edit Peer",
|
"button-edit-peer": "Peer bearbeiten",
|
||||||
"peer-disabled": "Peer is disabled, reason:",
|
"peer-disabled": "Peer ist deaktiviert, Grund:",
|
||||||
"peer-expiring": "Peer is expiring at",
|
"peer-expiring": "Peer läuft ab am",
|
||||||
"peer-connected": "Connected",
|
"peer-connected": "Verbunden",
|
||||||
"peer-not-connected": "Not Connected",
|
"peer-not-connected": "Nicht verbunden",
|
||||||
"peer-handshake": "Last handshake:"
|
"peer-handshake": "Letzter Handshake:"
|
||||||
},
|
},
|
||||||
"users": {
|
"users": {
|
||||||
"headline": "Benutzerverwaltung",
|
"headline": "Benutzerverwaltung",
|
||||||
"table-heading": {
|
"table-heading": {
|
||||||
"id": "ID",
|
"id": "ID",
|
||||||
"email": "E-Mail",
|
"email": "E-Mail",
|
||||||
"firstname": "Firstname",
|
"firstname": "Vorname",
|
||||||
"lastname": "Lastname",
|
"lastname": "Nachname",
|
||||||
"source": "Source",
|
"source": "Quelle",
|
||||||
"peers": "Peers",
|
"peers": "Peers",
|
||||||
"admin": "Admin"
|
"admin": "Admin"
|
||||||
},
|
},
|
||||||
"no-user": {
|
"no-user": {
|
||||||
"headline": "No users available",
|
"headline": "Keine Benutzer verfügbar",
|
||||||
"abstract": "Currently, there are no users registered with WireGuard Portal."
|
"abstract": "Derzeit sind keine Benutzer im WireGuard-Portal registriert."
|
||||||
},
|
},
|
||||||
"button-add-user": "Add User",
|
"button-add-user": "Benutzer hinzufügen",
|
||||||
"button-show-user": "Show User",
|
"button-show-user": "Benutzer anzeigen",
|
||||||
"button-edit-user": "Edit User",
|
"button-edit-user": "Benutzer bearbeiten",
|
||||||
"user-disabled": "User is disabled, reason:",
|
"user-disabled": "Benutzer ist deaktiviert, Grund:",
|
||||||
"user-locked": "Account is locked, reason:",
|
"user-locked": "Konto ist gesperrt, Grund:",
|
||||||
"admin": "User has administrator privileges",
|
"admin": "Benutzer hat Administratorrechte",
|
||||||
"no-admin": "User has no administrator privileges"
|
"no-admin": "Benutzer hat keine Administratorrechte"
|
||||||
},
|
},
|
||||||
"profile": {
|
"profile": {
|
||||||
"headline": "Meine VPN-Konfigurationen",
|
"headline": "Meine VPN-Konfigurationen",
|
||||||
@@ -158,16 +159,16 @@
|
|||||||
"name": "Name",
|
"name": "Name",
|
||||||
"ip": "IP's",
|
"ip": "IP's",
|
||||||
"stats": "Status",
|
"stats": "Status",
|
||||||
"interface": "Server Interface"
|
"interface": "Server-Schnittstelle"
|
||||||
},
|
},
|
||||||
"no-peer": {
|
"no-peer": {
|
||||||
"headline": "No peers available",
|
"headline": "Keine Peers verfügbar",
|
||||||
"abstract": "Currently, there are no peers associated with your user profile."
|
"abstract": "Derzeit sind keine Peers mit Ihrem Benutzerprofil verknüpft."
|
||||||
},
|
},
|
||||||
"peer-connected": "Connected",
|
"peer-connected": "Verbunden",
|
||||||
"button-add-peer": "Add Peer",
|
"button-add-peer": "Peer hinzufügen",
|
||||||
"button-show-peer": "Show Peer",
|
"button-show-peer": "Peer anzeigen",
|
||||||
"button-edit-peer": "Edit Peer"
|
"button-edit-peer": "Peer bearbeiten"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"headline": "Einstellungen",
|
"headline": "Einstellungen",
|
||||||
@@ -189,345 +190,362 @@
|
|||||||
"api-link": "API Dokumentation"
|
"api-link": "API Dokumentation"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"audit": {
|
||||||
|
"headline": "Eventprotokoll",
|
||||||
|
"abstract": "Hier finden Sie das Eventprotokoll aller im WireGuard-Portal vorgenommenen Aktionen.",
|
||||||
|
"no-entries": {
|
||||||
|
"headline": "Keine Protokolleinträge verfügbar",
|
||||||
|
"abstract": "Derzeit sind keine Eventprotokolle aufgezeichnet."
|
||||||
|
},
|
||||||
|
"entries-headline": "Protokolleinträge",
|
||||||
|
"table-heading": {
|
||||||
|
"id": "#",
|
||||||
|
"time": "Zeit",
|
||||||
|
"user": "Benutzer",
|
||||||
|
"severity": "Schweregrad",
|
||||||
|
"origin": "Ursprung",
|
||||||
|
"message": "Nachricht"
|
||||||
|
}
|
||||||
|
},
|
||||||
"keygen": {
|
"keygen": {
|
||||||
"headline": "WireGuard Key Generator",
|
"headline": "WireGuard Key Generator",
|
||||||
"abstract": "Hier können Sie WireGuard Schlüsselpaare generieren. Die Schlüssel werden lokal auf Ihrem Computer generiert und niemals an den Server gesendet.",
|
"abstract": "Hier können Sie WireGuard Schlüsselpaare generieren. Die Schlüssel werden lokal auf Ihrem Computer generiert und niemals an den Server gesendet.",
|
||||||
"headline-keypair": "Neues Schlüsselpaar",
|
"headline-keypair": "Neues Schlüsselpaar",
|
||||||
"headline-preshared-key": "Neuer Pre-shared Key",
|
"headline-preshared-key": "Neuer Pre-Shared Key",
|
||||||
"button-generate": "Erzeugen",
|
"button-generate": "Erzeugen",
|
||||||
"private-key": {
|
"private-key": {
|
||||||
"label": "Private Key",
|
"label": "Privater Schlüssel",
|
||||||
"placeholder": "Der private Schlüssel"
|
"placeholder": "Der private Schlüssel"
|
||||||
},
|
},
|
||||||
"public-key": {
|
"public-key": {
|
||||||
"label": "Public Key",
|
"label": "Öffentlicher Schlüssel",
|
||||||
"placeholder": "Der öffentliche Schlüssel"
|
"placeholder": "Der öffentliche Schlüssel"
|
||||||
},
|
},
|
||||||
"preshared-key": {
|
"preshared-key": {
|
||||||
"label": "Preshared Key",
|
"label": "Pre-Shared Key",
|
||||||
"placeholder": "Der Pre-shared Schlüssel"
|
"placeholder": "Der geteilte Schlüssel"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"modals": {
|
"modals": {
|
||||||
"user-view": {
|
"user-view": {
|
||||||
"headline": "User Account:",
|
"headline": "Benutzerkonto:",
|
||||||
"tab-user": "Information",
|
"tab-user": "Informationen",
|
||||||
"tab-peers": "Peers",
|
"tab-peers": "Peers",
|
||||||
"headline-info": "User Information:",
|
"headline-info": "Benutzerinformationen:",
|
||||||
"headline-notes": "Notes:",
|
"headline-notes": "Notizen:",
|
||||||
"email": "E-Mail",
|
"email": "E-Mail",
|
||||||
"firstname": "Firstname",
|
"firstname": "Vorname",
|
||||||
"lastname": "Lastname",
|
"lastname": "Nachname",
|
||||||
"phone": "Phone number",
|
"phone": "Telefonnummer",
|
||||||
"department": "Department",
|
"department": "Abteilung",
|
||||||
"disabled": "Account Disabled",
|
"api-enabled": "API-Zugriff",
|
||||||
"locked": "Account Locked",
|
"disabled": "Konto deaktiviert",
|
||||||
"no-peers": "User has no associated peers.",
|
"locked": "Konto gesperrt",
|
||||||
|
"no-peers": "Benutzer hat keine zugeordneten Peers.",
|
||||||
"peers": {
|
"peers": {
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
"interface": "Interface",
|
"interface": "Schnittstelle",
|
||||||
"ip": "IP's"
|
"ip": "IP's"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"user-edit": {
|
"user-edit": {
|
||||||
"headline-edit": "Edit user:",
|
"headline-edit": "Benutzer bearbeiten:",
|
||||||
"headline-new": "New user",
|
"headline-new": "Neuer Benutzer",
|
||||||
"header-general": "General",
|
"header-general": "Allgemein",
|
||||||
"header-personal": "User Information",
|
"header-personal": "Benutzerinformationen",
|
||||||
"header-notes": "Notes",
|
"header-notes": "Notizen",
|
||||||
"header-state": "State",
|
"header-state": "Status",
|
||||||
"identifier": {
|
"identifier": {
|
||||||
"label": "Identifier",
|
"label": "Kennung",
|
||||||
"placeholder": "The unique user identifier"
|
"placeholder": "Die eindeutige Benutzerkennung"
|
||||||
},
|
},
|
||||||
"source": {
|
"source": {
|
||||||
"label": "Source",
|
"label": "Quelle",
|
||||||
"placeholder": "The user source"
|
"placeholder": "Die Benutzerquelle"
|
||||||
},
|
},
|
||||||
"password": {
|
"password": {
|
||||||
"label": "Password",
|
"label": "Passwort",
|
||||||
"placeholder": "A super secret password",
|
"placeholder": "Ein super geheimes Passwort",
|
||||||
"description": "Leave this field blank to keep current password."
|
"description": "Lassen Sie dieses Feld leer, um das aktuelle Passwort beizubehalten."
|
||||||
},
|
},
|
||||||
"email": {
|
"email": {
|
||||||
"label": "Email",
|
"label": "E-Mail",
|
||||||
"placeholder": "The email address"
|
"placeholder": "Die E-Mail-Adresse"
|
||||||
},
|
},
|
||||||
"phone": {
|
"phone": {
|
||||||
"label": "Phone",
|
"label": "Telefon",
|
||||||
"placeholder": "The phone number"
|
"placeholder": "Die Telefonnummer"
|
||||||
},
|
},
|
||||||
"department": {
|
"department": {
|
||||||
"label": "Department",
|
"label": "Abteilung",
|
||||||
"placeholder": "The department"
|
"placeholder": "Die Abteilung"
|
||||||
},
|
},
|
||||||
"firstname": {
|
"firstname": {
|
||||||
"label": "Firstname",
|
"label": "Vorname",
|
||||||
"placeholder": "Firstname"
|
"placeholder": "Vorname"
|
||||||
},
|
},
|
||||||
"lastname": {
|
"lastname": {
|
||||||
"label": "Lastname",
|
"label": "Nachname",
|
||||||
"placeholder": "Lastname"
|
"placeholder": "Nachname"
|
||||||
},
|
},
|
||||||
"notes": {
|
"notes": {
|
||||||
"label": "Notes",
|
"label": "Notizen",
|
||||||
"placeholder": ""
|
"placeholder": ""
|
||||||
},
|
},
|
||||||
"disabled": {
|
"disabled": {
|
||||||
"label": "Disabled (no WireGuard connection and no login possible)"
|
"label": "Deaktiviert (keine WireGuard-Verbindung und kein Login möglich)"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"label": "Locked (no login possible, WireGuard connections still work)"
|
"label": "Gesperrt (kein Login möglich, WireGuard-Verbindungen funktionieren weiterhin)"
|
||||||
},
|
},
|
||||||
"admin": {
|
"admin": {
|
||||||
"label": "Is Admin"
|
"label": "Ist Administrator"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"interface-view": {
|
"interface-view": {
|
||||||
"headline": "Config for Interface:"
|
"headline": "Konfiguration für Schnittstelle:"
|
||||||
},
|
},
|
||||||
"interface-edit": {
|
"interface-edit": {
|
||||||
"headline-edit": "Edit Interface:",
|
"headline-edit": "Schnittstelle bearbeiten:",
|
||||||
"headline-new": "New Interface",
|
"headline-new": "Neue Schnittstelle",
|
||||||
"tab-interface": "Interface",
|
"tab-interface": "Schnittstelle",
|
||||||
"tab-peerdef": "Peer Defaults",
|
"tab-peerdef": "Peer-Standardeinstellungen",
|
||||||
"header-general": "General",
|
"header-general": "Allgemein",
|
||||||
"header-network": "Network",
|
"header-network": "Netzwerk",
|
||||||
"header-crypto": "Cryptography",
|
"header-crypto": "Kryptografie",
|
||||||
"header-hooks": "Interface Hooks",
|
"header-hooks": "Schnittstellen-Hooks",
|
||||||
"header-peer-hooks": "Hooks",
|
"header-peer-hooks": "Hooks",
|
||||||
"header-state": "State",
|
"header-state": "Status",
|
||||||
"identifier": {
|
"identifier": {
|
||||||
"label": "Identifier",
|
"label": "Kennung",
|
||||||
"placeholder": "The unique interface identifier"
|
"placeholder": "Die eindeutige Schnittstellenkennung"
|
||||||
},
|
},
|
||||||
"mode": {
|
"mode": {
|
||||||
"label": "Interface Mode",
|
"label": "Schnittstellenmodus",
|
||||||
"server": "Server Mode",
|
"server": "Server-Modus",
|
||||||
"client": "Client Mode",
|
"client": "Client-Modus",
|
||||||
"any": "Unknown Mode"
|
"any": "Unbekannter Modus"
|
||||||
},
|
},
|
||||||
"display-name": {
|
"display-name": {
|
||||||
"label": "Display Name",
|
"label": "Anzeigename",
|
||||||
"placeholder": "The descriptive name for the interface"
|
"placeholder": "Der beschreibende Name für die Schnittstelle"
|
||||||
},
|
},
|
||||||
"private-key": {
|
"private-key": {
|
||||||
"label": "Private Key",
|
"label": "Privater Schlüssel",
|
||||||
"placeholder": "The private key"
|
"placeholder": "Der private Schlüssel"
|
||||||
},
|
},
|
||||||
"public-key": {
|
"public-key": {
|
||||||
"label": "Public Key",
|
"label": "Öffentlicher Schlüssel",
|
||||||
"placeholder": "The public key"
|
"placeholder": "Der öffentliche Schlüssel"
|
||||||
},
|
},
|
||||||
"ip": {
|
"ip": {
|
||||||
"label": "IP Addresses",
|
"label": "IP-Adressen",
|
||||||
"placeholder": "IP Addresses (CIDR format)"
|
"placeholder": "IP-Adressen (CIDR-Format)"
|
||||||
},
|
},
|
||||||
"listen-port": {
|
"listen-port": {
|
||||||
"label": "Listen Port",
|
"label": "Port",
|
||||||
"placeholder": "The listening port"
|
"placeholder": "Der Port der WireGuard Schnittstelle"
|
||||||
},
|
},
|
||||||
"dns": {
|
"dns": {
|
||||||
"label": "DNS Server",
|
"label": "DNS-Server",
|
||||||
"placeholder": "The DNS servers that should be used"
|
"placeholder": "Die zu verwendenden DNS-Server"
|
||||||
},
|
},
|
||||||
"dns-search": {
|
"dns-search": {
|
||||||
"label": "DNS Search Domains",
|
"label": "DNS-Suchdomänen",
|
||||||
"placeholder": "DNS search prefixes"
|
"placeholder": "DNS-Suchpräfixe"
|
||||||
},
|
},
|
||||||
"mtu": {
|
"mtu": {
|
||||||
"label": "MTU",
|
"label": "MTU",
|
||||||
"placeholder": "The interface MTU (0 = keep default)"
|
"placeholder": "Die Schnittstellen-MTU (0 = Standard beibehalten)"
|
||||||
},
|
},
|
||||||
"firewall-mark": {
|
"firewall-mark": {
|
||||||
"label": "Firewall Mark",
|
"label": "Firewall-Markierung",
|
||||||
"placeholder": "Firewall mark that is applied to outgoing traffic. (0 = automatic)"
|
"placeholder": "Firewall-Markierung, die auf ausgehenden Datenverkehr angewendet wird. (0 = automatisch)"
|
||||||
},
|
},
|
||||||
"routing-table": {
|
"routing-table": {
|
||||||
"label": "Routing Table",
|
"label": "Routing-Tabelle",
|
||||||
"placeholder": "The routing table ID",
|
"placeholder": "Die Routing-Tabellen-ID",
|
||||||
"description": "Special cases: off = do not manage routes, 0 = automatic"
|
"description": "Spezialfälle: off = Routen nicht verwalten, 0 = automatisch"
|
||||||
},
|
},
|
||||||
"pre-up": {
|
"pre-up": {
|
||||||
"label": "Pre-Up",
|
"label": "Pre-Up",
|
||||||
"placeholder": "One or multiple bash commands separated by ;"
|
"placeholder": "Ein oder mehrere Bash-Befehle, getrennt durch ;"
|
||||||
},
|
},
|
||||||
"post-up": {
|
"post-up": {
|
||||||
"label": "Post-Up",
|
"label": "Post-Up",
|
||||||
"placeholder": "One or multiple bash commands separated by ;"
|
"placeholder": "Ein oder mehrere Bash-Befehle, getrennt durch ;"
|
||||||
},
|
},
|
||||||
"pre-down": {
|
"pre-down": {
|
||||||
"label": "Pre-Down",
|
"label": "Pre-Down",
|
||||||
"placeholder": "One or multiple bash commands separated by ;"
|
"placeholder": "Ein oder mehrere Bash-Befehle, getrennt durch ;"
|
||||||
},
|
},
|
||||||
"post-down": {
|
"post-down": {
|
||||||
"label": "Post-Down",
|
"label": "Post-Down",
|
||||||
"placeholder": "One or multiple bash commands separated by ;"
|
"placeholder": "Ein oder mehrere Bash-Befehle, getrennt durch ;"
|
||||||
},
|
},
|
||||||
"disabled": {
|
"disabled": {
|
||||||
"label": "Interface Disabled"
|
"label": "Schnittstelle deaktiviert"
|
||||||
},
|
},
|
||||||
"save-config": {
|
"save-config": {
|
||||||
"label": "Automatically save wg-quick config"
|
"label": "wg-quick Konfiguration automatisch speichern"
|
||||||
},
|
},
|
||||||
"defaults": {
|
"defaults": {
|
||||||
"endpoint": {
|
"endpoint": {
|
||||||
"label": "Endpoint Address",
|
"label": "Endpunktadresse",
|
||||||
"placeholder": "Endpoint Address",
|
"placeholder": "Endpunktadresse",
|
||||||
"description": "The endpoint address that peers will connect to. (e.g. wg.example.com or wg.example.com:51820)"
|
"description": "Die Endpunktadresse, mit der sich Peers verbinden. (z.B. wg.example.com oder wg.example.com:51820)"
|
||||||
},
|
},
|
||||||
"networks": {
|
"networks": {
|
||||||
"label": "IP Networks",
|
"label": "IP-Netzwerke",
|
||||||
"placeholder": "Network Addresses",
|
"placeholder": "Netzwerkadressen",
|
||||||
"description": "Peers will get IP addresses from those subnets."
|
"description": "Peers erhalten IP-Adressen aus diesen Subnetzen."
|
||||||
},
|
},
|
||||||
"allowed-ip": {
|
"allowed-ip": {
|
||||||
"label": "Allowed IP Addresses",
|
"label": "Erlaubte IP-Adressen",
|
||||||
"placeholder": "Default Allowed IP Addresses"
|
"placeholder": "Erlaubte IP-Adressen für Peers"
|
||||||
},
|
},
|
||||||
"mtu": {
|
"mtu": {
|
||||||
"label": "MTU",
|
"label": "MTU",
|
||||||
"placeholder": "The client MTU (0 = keep default)"
|
"placeholder": "Die Client-MTU (0 = Standard beibehalten)"
|
||||||
},
|
},
|
||||||
"keep-alive": {
|
"keep-alive": {
|
||||||
"label": "Keep Alive Interval",
|
"label": "Keepalive-Intervall",
|
||||||
"placeholder": "Persistent Keepalive (0 = default)"
|
"placeholder": "Persistentes Keepalive (0 = Standard)"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"button-apply-defaults": "Peer-Standardeinstellungen anwenden"
|
||||||
"button-apply-defaults": "Apply Peer Defaults"
|
|
||||||
},
|
},
|
||||||
"peer-view": {
|
"peer-view": {
|
||||||
"headline-peer": "Peer:",
|
"headline-peer": "Peer:",
|
||||||
"headline-endpoint": "Endpoint:",
|
"headline-endpoint": "Endpunkt:",
|
||||||
"section-info": "Peer Information",
|
"section-info": "Peer-Informationen",
|
||||||
"section-status": "Current Status",
|
"section-status": "Aktueller Status",
|
||||||
"section-config": "Configuration",
|
"section-config": "Konfiguration",
|
||||||
"identifier": "Identifier",
|
"identifier": "Kennung",
|
||||||
"ip": "IP Addresses",
|
"ip": "IP-Adressen",
|
||||||
"user": "Associated User",
|
"user": "Zugeordneter Benutzer",
|
||||||
"notes": "Notes",
|
"notes": "Notizen",
|
||||||
"expiry-status": "Expires At",
|
"expiry-status": "Läuft ab am",
|
||||||
"disabled-status": "Disabled At",
|
"disabled-status": "Deaktiviert am",
|
||||||
"traffic": "Traffic",
|
"traffic": "Datenverkehr",
|
||||||
"connection-status": "Connection Stats",
|
"connection-status": "Verbindungsstatistiken",
|
||||||
"upload": "Uploaded Bytes (from Server to Peer)",
|
"upload": "Hochgeladene Bytes (vom Server zum Peer)",
|
||||||
"download": "Downloaded Bytes (from Peer to Server)",
|
"download": "Heruntergeladene Bytes (vom Peer zum Server)",
|
||||||
"pingable": "Is Pingable",
|
"pingable": "Pingbar",
|
||||||
"handshake": "Last Handshake",
|
"handshake": "Letzter Handshake",
|
||||||
"connected-since": "Connected since",
|
"connected-since": "Verbunden seit",
|
||||||
"endpoint": "Endpoint",
|
"endpoint": "Endpunkt",
|
||||||
"button-download": "Download configuration",
|
"button-download": "Konfiguration herunterladen",
|
||||||
"button-email": "Send configuration via E-Mail"
|
"button-email": "Konfiguration per E-Mail senden"
|
||||||
},
|
},
|
||||||
"peer-edit": {
|
"peer-edit": {
|
||||||
"headline-edit-peer": "Edit peer:",
|
"headline-edit-peer": "Peer bearbeiten:",
|
||||||
"headline-edit-endpoint": "Edit endpoint:",
|
"headline-edit-endpoint": "Endpunkt bearbeiten:",
|
||||||
"headline-new-peer": "Create peer",
|
"headline-new-peer": "Peer erstellen",
|
||||||
"headline-new-endpoint": "Create endpoint",
|
"headline-new-endpoint": "Endpunkt erstellen",
|
||||||
"header-general": "General",
|
"header-general": "Allgemein",
|
||||||
"header-network": "Network",
|
"header-network": "Netzwerk",
|
||||||
"header-crypto": "Cryptography",
|
"header-crypto": "Kryptografie",
|
||||||
"header-hooks": "Hooks (Executed on Peer)",
|
"header-hooks": "Hooks (beim Peer ausgeführt)",
|
||||||
"header-state": "State",
|
"header-state": "Status",
|
||||||
"display-name": {
|
"display-name": {
|
||||||
"label": "Display Name",
|
"label": "Anzeigename",
|
||||||
"placeholder": "The descriptive name for the peer"
|
"placeholder": "Der beschreibende Name für den Peer"
|
||||||
},
|
},
|
||||||
"linked-user": {
|
"linked-user": {
|
||||||
"label": "Linked User",
|
"label": "Verknüpfter Benutzer",
|
||||||
"placeholder": "The user account which owns this peer"
|
"placeholder": "Das Benutzerkonto, dem dieser Peer gehört"
|
||||||
},
|
},
|
||||||
"private-key": {
|
"private-key": {
|
||||||
"label": "Private Key",
|
"label": "Privater Schlüssel",
|
||||||
"placeholder": "The private key",
|
"placeholder": "Der private Schlüssel",
|
||||||
"help": "Der private Schlüssel wird sicher auf dem Server gespeichert. Wenn der Benutzer bereits eine Kopie besitzt, kann dieses Feld entfallen. Der Server funktioniert auch ausschließlich mit dem öffentlichen Schlüssel des Peers."
|
"help": "Der private Schlüssel wird sicher auf dem Server gespeichert. Wenn der Benutzer bereits eine Kopie besitzt, kann dieses Feld entfallen. Der Server funktioniert auch ausschließlich mit dem öffentlichen Schlüssel des Peers."
|
||||||
},
|
},
|
||||||
"public-key": {
|
"public-key": {
|
||||||
"label": "Public Key",
|
"label": "Öffentlicher Schlüssel",
|
||||||
"placeholder": "The public key"
|
"placeholder": "Der öffentliche Schlüssel"
|
||||||
},
|
},
|
||||||
"preshared-key": {
|
"preshared-key": {
|
||||||
"label": "Preshared Key",
|
"label": "Pre-Shared Key",
|
||||||
"placeholder": "Optional pre-shared key"
|
"placeholder": "Optionaler geteilter Schlüssel"
|
||||||
},
|
},
|
||||||
"endpoint-public-key": {
|
"endpoint-public-key": {
|
||||||
"label": "Endpoint public Key",
|
"label": "Öffentlicher Endpunktschlüssel",
|
||||||
"placeholder": "The public key of the remote endpoint"
|
"placeholder": "Der öffentliche Schlüssel des entfernten Endpunkts"
|
||||||
},
|
},
|
||||||
"endpoint": {
|
"endpoint": {
|
||||||
"label": "Endpoint Address",
|
"label": "Endpunktadresse",
|
||||||
"placeholder": "The address of the remote endpoint"
|
"placeholder": "Die Adresse des entfernten Endpunkts"
|
||||||
},
|
},
|
||||||
"ip": {
|
"ip": {
|
||||||
"label": "IP Addresses",
|
"label": "IP-Adressen",
|
||||||
"placeholder": "IP Addresses (CIDR format)"
|
"placeholder": "IP-Adressen (CIDR-Format)"
|
||||||
},
|
},
|
||||||
"allowed-ip": {
|
"allowed-ip": {
|
||||||
"label": "Allowed IP Addresses",
|
"label": "Erlaubte IP-Adressen",
|
||||||
"placeholder": "Allowed IP Addresses (CIDR format)"
|
"placeholder": "Erlaubte IP-Adressen (CIDR-Format)"
|
||||||
},
|
},
|
||||||
"extra-allowed-ip": {
|
"extra-allowed-ip": {
|
||||||
"label": "Extra allowed IP Addresses",
|
"label": "Zusätzliche erlaubte IP-Adressen",
|
||||||
"placeholder": "Extra allowed IP's (Server Sided)",
|
"placeholder": "Zusätzliche erlaubte IP's (Server-seitig)",
|
||||||
"description": "Those IP's will be added on the remote WireGuard interface as allowed IP's."
|
"description": "Diese IPs werden an der entfernten WireGuard-Schnittstelle als erlaubte IPs hinzugefügt."
|
||||||
},
|
},
|
||||||
"dns": {
|
"dns": {
|
||||||
"label": "DNS Server",
|
"label": "DNS-Server",
|
||||||
"placeholder": "The DNS servers that should be used"
|
"placeholder": "Die zu verwendenden DNS-Server"
|
||||||
},
|
},
|
||||||
"dns-search": {
|
"dns-search": {
|
||||||
"label": "DNS Search Domains",
|
"label": "DNS-Suchdomänen",
|
||||||
"placeholder": "DNS search prefixes"
|
"placeholder": "DNS-Suchpräfixe"
|
||||||
},
|
},
|
||||||
"keep-alive": {
|
"keep-alive": {
|
||||||
"label": "Keep Alive Interval",
|
"label": "Keepalive-Intervall",
|
||||||
"placeholder": "Persistent Keepalive (0 = default)"
|
"placeholder": "Persistentes Keepalive (0 = Standard)"
|
||||||
},
|
},
|
||||||
"mtu": {
|
"mtu": {
|
||||||
"label": "MTU",
|
"label": "MTU",
|
||||||
"placeholder": "The client MTU (0 = keep default)"
|
"placeholder": "Die Client-MTU (0 = Standard beibehalten)"
|
||||||
},
|
},
|
||||||
"pre-up": {
|
"pre-up": {
|
||||||
"label": "Pre-Up",
|
"label": "Pre-Up",
|
||||||
"placeholder": "One or multiple bash commands separated by ;"
|
"placeholder": "Ein oder mehrere Bash-Befehle, getrennt durch ;"
|
||||||
},
|
},
|
||||||
"post-up": {
|
"post-up": {
|
||||||
"label": "Post-Up",
|
"label": "Post-Up",
|
||||||
"placeholder": "One or multiple bash commands separated by ;"
|
"placeholder": "Ein oder mehrere Bash-Befehle, getrennt durch ;"
|
||||||
},
|
},
|
||||||
"pre-down": {
|
"pre-down": {
|
||||||
"label": "Pre-Down",
|
"label": "Pre-Down",
|
||||||
"placeholder": "One or multiple bash commands separated by ;"
|
"placeholder": "Ein oder mehrere Bash-Befehle, getrennt durch ;"
|
||||||
},
|
},
|
||||||
"post-down": {
|
"post-down": {
|
||||||
"label": "Post-Down",
|
"label": "Post-Down",
|
||||||
"placeholder": "One or multiple bash commands separated by ;"
|
"placeholder": "Ein oder mehrere Bash-Befehle, getrennt durch ;"
|
||||||
},
|
},
|
||||||
"disabled": {
|
"disabled": {
|
||||||
"label": "Peer Disabled"
|
"label": "Peer deaktiviert"
|
||||||
},
|
},
|
||||||
"ignore-global": {
|
"ignore-global": {
|
||||||
"label": "Ignore global settings"
|
"label": "Globale Einstellungen ignorieren"
|
||||||
},
|
},
|
||||||
"expires-at": {
|
"expires-at": {
|
||||||
"label": "Expiry date"
|
"label": "Ablaufdatum"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"peer-multi-create": {
|
"peer-multi-create": {
|
||||||
"headline-peer": "Create multiple peers",
|
"headline-peer": "Mehrere Peers erstellen",
|
||||||
"headline-endpoint": "Create multiple endpoints",
|
"headline-endpoint": "Mehrere Endpunkte erstellen",
|
||||||
"identifiers": {
|
"identifiers": {
|
||||||
"label": "User Identifiers",
|
"label": "Benutzerkennungen",
|
||||||
"placeholder": "User Identifiers",
|
"placeholder": "Benutzerkennungen",
|
||||||
"description": "A user identifier (the username) for which a peer should be created."
|
"description": "Eine Benutzerkennung (der Benutzername), für die ein Peer erstellt werden soll."
|
||||||
},
|
},
|
||||||
"prefix": {
|
"prefix": {
|
||||||
"headline-peer": "Peer:",
|
"headline-peer": "Peer:",
|
||||||
"headline-endpoint": "Endpoint:",
|
"headline-endpoint": "Endpunkt:",
|
||||||
"label": "Display Name Prefix",
|
"label": "Anzeigename-Präfix",
|
||||||
"placeholder": "The prefix",
|
"placeholder": "Das Präfix",
|
||||||
"description": "A prefix that is added to the peers display name."
|
"description": "Ein Präfix, das dem Anzeigenamen des Peers hinzugefügt wird."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,14 +20,14 @@
|
|||||||
"delete": "Eliminar"
|
"delete": "Eliminar"
|
||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"headline": "Por favor, inicie sessão",
|
"headline": "Por favor, inicie a sessão",
|
||||||
"username": {
|
"username": {
|
||||||
"label": "Nome de utilizador",
|
"label": "Nome de utilizador",
|
||||||
"placeholder": "Introduza o seu nome de utilizador"
|
"placeholder": "Por favor, insira o seu nome de utilizador"
|
||||||
},
|
},
|
||||||
"password": {
|
"password": {
|
||||||
"label": "Palavra-passe",
|
"label": "Palavra-passe",
|
||||||
"placeholder": "Introduza a sua palavra-passe"
|
"placeholder": "Por favor, insira a sua palavra-passe"
|
||||||
},
|
},
|
||||||
"button": "Iniciar sessão"
|
"button": "Iniciar sessão"
|
||||||
},
|
},
|
||||||
@@ -40,143 +40,513 @@
|
|||||||
"settings": "Definições",
|
"settings": "Definições",
|
||||||
"audit": "Registo de Auditoria",
|
"audit": "Registo de Auditoria",
|
||||||
"login": "Iniciar Sessão",
|
"login": "Iniciar Sessão",
|
||||||
"logout": "Terminar Sessão"
|
"logout": "Terminar Sessão",
|
||||||
|
"keygen": "Gerador de Chave"
|
||||||
},
|
},
|
||||||
"home": {
|
"home": {
|
||||||
"title": "Início",
|
"headline": "WireGuard® Portal VPN",
|
||||||
"card": {
|
"info-headline": "Mais Informações",
|
||||||
"interfaces": "Interfaces",
|
"abstract": "WireGuard® é uma VPN extremamente simples, mas rápida e moderna que utiliza criptografia de última geração. O seu objetivo é ser mais rápida, simples, leve e útil que o IPsec, enquanto evita grandes dores de cabeça. Pretende ser consideravelmente mais eficiente que o OpenVPN.",
|
||||||
"users": "Utilizadores"
|
"installation": {
|
||||||
|
"box-header": "Instalação do WireGuard",
|
||||||
|
"headline": "Instalação",
|
||||||
|
"content": "As instruções de instalação para o software cliente podem ser encontradas no site oficial do WireGuard.",
|
||||||
|
"button": "Abrir Instruções"
|
||||||
|
},
|
||||||
|
"about-wg": {
|
||||||
|
"box-header": "Sobre o WireGuard",
|
||||||
|
"headline": "Sobre",
|
||||||
|
"content": "WireGuard® é uma VPN extremamente simples, mas rápida e moderna que utiliza criptografia de última geração.",
|
||||||
|
"button": "Mais"
|
||||||
|
},
|
||||||
|
"about-portal": {
|
||||||
|
"box-header": "Sobre o WireGuard Portal",
|
||||||
|
"headline": "WireGuard Portal",
|
||||||
|
"content": "WireGuard Portal é um portal web de configuração simples para o WireGuard.",
|
||||||
|
"button": "Mais"
|
||||||
|
},
|
||||||
|
"profiles": {
|
||||||
|
"headline": "Perfis VPN",
|
||||||
|
"abstract": "Pode aceder e baixar as suas configurações pessoais de VPN através do seu Perfil de Utilizador.",
|
||||||
|
"content": "Para encontrar todos os seus perfis configurados, clique no botão abaixo.",
|
||||||
|
"button": "Abrir meu perfil"
|
||||||
|
},
|
||||||
|
"admin": {
|
||||||
|
"headline": "Área de Administração",
|
||||||
|
"abstract": "Na área de administração, pode gerir os peers do WireGuard, a interface do servidor e os utilizadores que têm permissão para aceder ao Portal WireGuard.",
|
||||||
|
"content": "",
|
||||||
|
"button-admin": "Abrir Administração do Servidor",
|
||||||
|
"button-user": "Abrir Administração de Utilizadores"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"interfaces": {
|
"interfaces": {
|
||||||
"title": "Interfaces",
|
"headline": "Administração de Interfaces",
|
||||||
"create": "Criar Interface",
|
"headline-peers": "Peers VPN Atuais",
|
||||||
|
"headline-endpoints": "Endpoints Atuais",
|
||||||
|
"no-interface": {
|
||||||
|
"default-selection": "Nenhuma interface disponível",
|
||||||
|
"headline": "Nenhuma interface encontrada...",
|
||||||
|
"abstract": "Clique no botão + acima para criar uma nova interface WireGuard."
|
||||||
|
},
|
||||||
|
"no-peer": {
|
||||||
|
"headline": "Nenhum peer disponível",
|
||||||
|
"abstract": "Atualmente, não há peers disponíveis para a interface WireGuard selecionada."
|
||||||
|
},
|
||||||
|
"table-heading": {
|
||||||
"name": "Nome",
|
"name": "Nome",
|
||||||
"address": "Endereço",
|
"user": "Utilizador",
|
||||||
"listen-port": "Porta de Escuta",
|
"ip": "IPs",
|
||||||
"public-key": "Chave Pública",
|
"endpoint": "Endpoint",
|
||||||
"private-key": "Chave Privada",
|
"status": "Status"
|
||||||
"actions": "Ações",
|
|
||||||
"delete-dialog": {
|
|
||||||
"title": "Eliminar Interface",
|
|
||||||
"text": "Tem a certeza de que deseja eliminar a interface '{{name}}'?"
|
|
||||||
},
|
},
|
||||||
"form": {
|
"interface": {
|
||||||
"name": {
|
"headline": "Status da interface para",
|
||||||
"label": "Nome",
|
"mode": "modo",
|
||||||
"placeholder": "Introduza um nome exclusivo para a interface"
|
"key": "Chave Pública",
|
||||||
|
"endpoint": "Endpoint Público",
|
||||||
|
"port": "Porta de Escuta",
|
||||||
|
"peers": "Peers Ativados",
|
||||||
|
"total-peers": "Total de Peers",
|
||||||
|
"endpoints": "Endpoints Ativados",
|
||||||
|
"total-endpoints": "Total de Endpoints",
|
||||||
|
"ip": "Endereço IP",
|
||||||
|
"default-allowed-ip": "IPs permitidos por padrão",
|
||||||
|
"dns": "Servidores DNS",
|
||||||
|
"mtu": "MTU",
|
||||||
|
"default-keep-alive": "Intervalo de Keepalive Padrão",
|
||||||
|
"button-show-config": "Mostrar configuração",
|
||||||
|
"button-download-config": "Baixar configuração",
|
||||||
|
"button-store-config": "Armazenar configuração para wg-quick",
|
||||||
|
"button-edit": "Editar interface"
|
||||||
},
|
},
|
||||||
"address": {
|
"button-add-interface": "Adicionar Interface",
|
||||||
"label": "Endereço",
|
"button-add-peer": "Adicionar Peer",
|
||||||
"placeholder": "Introduza um endereço válido (ex: 10.0.0.1/24)"
|
"button-add-peers": "Adicionar Vários Peers",
|
||||||
},
|
"button-show-peer": "Mostrar Peer",
|
||||||
"listen-port": {
|
"button-edit-peer": "Editar Peer",
|
||||||
"label": "Porta de Escuta",
|
"peer-disabled": "Peer desativado, razão:",
|
||||||
"placeholder": "Introduza a porta onde o WireGuard irá escutar (ex: 51820)"
|
"peer-expiring": "Peer expira em",
|
||||||
},
|
"peer-connected": "Conectado",
|
||||||
"private-key": {
|
"peer-not-connected": "Não Conectado",
|
||||||
"label": "Chave Privada",
|
"peer-handshake": "Último handshake:"
|
||||||
"placeholder": "Será gerada automaticamente se não for fornecida"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"users": {
|
"users": {
|
||||||
"title": "Utilizadores",
|
"headline": "Administração de Utilizadores",
|
||||||
"create": "Criar Utilizador",
|
"table-heading": {
|
||||||
|
"id": "ID",
|
||||||
|
"email": "E-Mail",
|
||||||
|
"firstname": "Primeiro Nome",
|
||||||
|
"lastname": "Último Nome",
|
||||||
|
"source": "Fonte",
|
||||||
|
"peers": "Peers",
|
||||||
|
"admin": "Administrador"
|
||||||
|
},
|
||||||
|
"no-user": {
|
||||||
|
"headline": "Nenhum utilizador disponível",
|
||||||
|
"abstract": "Atualmente, não há utilizadores registados no Portal WireGuard."
|
||||||
|
},
|
||||||
|
"button-add-user": "Adicionar Utilizador",
|
||||||
|
"button-show-user": "Mostrar Utilizador",
|
||||||
|
"button-edit-user": "Editar Utilizador",
|
||||||
|
"user-disabled": "Utilizador desativado, razão:",
|
||||||
|
"user-locked": "Conta bloqueada, razão:",
|
||||||
|
"admin": "O utilizador tem privilégios de administrador",
|
||||||
|
"no-admin": "O utilizador não tem privilégios de administrador"
|
||||||
|
},
|
||||||
|
"profile": {
|
||||||
|
"headline": "Os Meus Peers VPN",
|
||||||
|
"table-heading": {
|
||||||
"name": "Nome",
|
"name": "Nome",
|
||||||
"email": "Email",
|
"ip": "IPs",
|
||||||
"enabled": "Ativo",
|
"stats": "Status",
|
||||||
"is-admin": "Administrador",
|
"interface": "Interface do Servidor"
|
||||||
"actions": "Ações",
|
|
||||||
"edit": "Editar",
|
|
||||||
"delete-dialog": {
|
|
||||||
"title": "Eliminar Utilizador",
|
|
||||||
"text": "Tem a certeza de que deseja eliminar o utilizador '{{nome}}'?"
|
|
||||||
},
|
},
|
||||||
"form": {
|
"no-peer": {
|
||||||
"name": {
|
"headline": "Nenhum peer disponível",
|
||||||
"label": "Nome",
|
"abstract": "Atualmente, não há peers associados ao seu perfil de utilizador."
|
||||||
"placeholder": "Introduza o nome do utilizador"
|
|
||||||
},
|
},
|
||||||
"email": {
|
"peer-connected": "Conectado",
|
||||||
"label": "Email",
|
"button-add-peer": "Adicionar Peer",
|
||||||
"placeholder": "Introduza o email do utilizador"
|
"button-show-peer": "Mostrar Peer",
|
||||||
|
"button-edit-peer": "Editar Peer"
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"headline": "Definições",
|
||||||
|
"abstract": "Aqui pode alterar suas Definições pessoais.",
|
||||||
|
"api": {
|
||||||
|
"headline": "Definições da API",
|
||||||
|
"abstract": "Aqui pode configurar as definições da API RESTful.",
|
||||||
|
"active-description": "A API está atualmente ativa para a sua conta de utilizador. Todos os pedidos para a API são autenticadas com Basic Auth. Use as seguintes credenciais para autenticação.",
|
||||||
|
"inactive-description": "A API está atualmente inativa. Pressione o botão abaixo para ativá-la.",
|
||||||
|
"user-label": "Nome de utilizador API:",
|
||||||
|
"user-placeholder": "O utilizador da API",
|
||||||
|
"token-label": "Senha da API:",
|
||||||
|
"token-placeholder": "O token da API",
|
||||||
|
"token-created-label": "Acesso API concedido em: ",
|
||||||
|
"button-disable-title": "Desativar API, invalidando o token atual.",
|
||||||
|
"button-disable-text": "Desativar API",
|
||||||
|
"button-enable-title": "Ativar API, gerando um novo token.",
|
||||||
|
"button-enable-text": "Ativar API",
|
||||||
|
"api-link": "Documentação da API"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"audit": {
|
||||||
|
"headline": "Registo de Auditoria",
|
||||||
|
"abstract": "Aqui pode encontrar o registo de auditoria de todas as ações realizadas no WireGuard Portal.",
|
||||||
|
"no-entries": {
|
||||||
|
"headline": "Nenhuma entrada no registo",
|
||||||
|
"abstract": "Atualmente, não há entradas de registo de auditoria gravadas."
|
||||||
|
},
|
||||||
|
"entries-headline": "Entradas do Registo",
|
||||||
|
"table-heading": {
|
||||||
|
"id": "#",
|
||||||
|
"time": "Hora",
|
||||||
|
"user": "Utilizador",
|
||||||
|
"severity": "Gravidade",
|
||||||
|
"origin": "Origem",
|
||||||
|
"message": "Mensagem"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"keygen": {
|
||||||
|
"headline": "Gerador de Chaves WireGuard",
|
||||||
|
"abstract": "Gere novas chaves WireGuard. As chaves são geradas no seu browser e nunca são enviadas para o servidor.",
|
||||||
|
"headline-keypair": "Novo Par de Chaves",
|
||||||
|
"headline-preshared-key": "Nova Chave Pré-Partilhada",
|
||||||
|
"button-generate": "Gerar",
|
||||||
|
"private-key": {
|
||||||
|
"label": "Chave Privada",
|
||||||
|
"placeholder": "A chave privada"
|
||||||
|
},
|
||||||
|
"public-key": {
|
||||||
|
"label": "Chave Pública",
|
||||||
|
"placeholder": "A chave pública"
|
||||||
|
},
|
||||||
|
"preshared-key": {
|
||||||
|
"label": "Chave Pré-Partilhada",
|
||||||
|
"placeholder": "A chave pré-partilhada"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"modals": {
|
||||||
|
"user-view": {
|
||||||
|
"headline": "Conta de Utilizador:",
|
||||||
|
"tab-user": "Informação",
|
||||||
|
"tab-peers": "Peers",
|
||||||
|
"headline-info": "Informação do Utilizador:",
|
||||||
|
"headline-notes": "Notas:",
|
||||||
|
"email": "E-Mail",
|
||||||
|
"firstname": "Primeiro Nome",
|
||||||
|
"lastname": "Último Nome",
|
||||||
|
"phone": "Número de Telefone",
|
||||||
|
"department": "Departamento",
|
||||||
|
"api-enabled": "Acesso API",
|
||||||
|
"disabled": "Conta Desativada",
|
||||||
|
"locked": "Conta Bloqueada",
|
||||||
|
"no-peers": "O utilizador não tem peers associados.",
|
||||||
|
"peers": {
|
||||||
|
"name": "Nome",
|
||||||
|
"interface": "Interface",
|
||||||
|
"ip": "IP's"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"user-edit": {
|
||||||
|
"headline-edit": "Editar utilizador:",
|
||||||
|
"headline-new": "Novo utilizador",
|
||||||
|
"header-general": "Geral",
|
||||||
|
"header-personal": "Informação do Utilizador",
|
||||||
|
"header-notes": "Notas",
|
||||||
|
"header-state": "Estado",
|
||||||
|
"identifier": {
|
||||||
|
"label": "Identificador",
|
||||||
|
"placeholder": "O identificador único do utilizador"
|
||||||
|
},
|
||||||
|
"source": {
|
||||||
|
"label": "Fonte",
|
||||||
|
"placeholder": "A fonte do utilizador"
|
||||||
},
|
},
|
||||||
"password": {
|
"password": {
|
||||||
"label": "Palavra-passe",
|
"label": "Palavra-passe",
|
||||||
"placeholder": "Deixe em branco para manter a atual"
|
"placeholder": "Uma palavra-passe super secreta",
|
||||||
|
"description": "Deixe este campo em branco para manter a palavra-passe atual."
|
||||||
},
|
},
|
||||||
"is-admin": {
|
"email": {
|
||||||
"label": "Administrador"
|
"label": "Email",
|
||||||
|
"placeholder": "O endereço de e-mail"
|
||||||
},
|
},
|
||||||
"enabled": {
|
"phone": {
|
||||||
"label": "Ativo"
|
"label": "Telefone",
|
||||||
}
|
"placeholder": "O número de telefone"
|
||||||
|
},
|
||||||
|
"department": {
|
||||||
|
"label": "Departamento",
|
||||||
|
"placeholder": "O departamento"
|
||||||
|
},
|
||||||
|
"firstname": {
|
||||||
|
"label": "Primeiro Nome",
|
||||||
|
"placeholder": "Primeiro Nome"
|
||||||
|
},
|
||||||
|
"lastname": {
|
||||||
|
"label": "Último Nome",
|
||||||
|
"placeholder": "Último Nome"
|
||||||
|
},
|
||||||
|
"notes": {
|
||||||
|
"label": "Notas",
|
||||||
|
"placeholder": ""
|
||||||
|
},
|
||||||
|
"disabled": {
|
||||||
|
"label": "Desativado (sem conexão WireGuard e login possível)"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"label": "Bloqueado (sem login possível, as conexões WireGuard ainda funcionam)"
|
||||||
|
},
|
||||||
|
"admin": {
|
||||||
|
"label": "É Administrador"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"peers": {
|
"interface-view": {
|
||||||
"title": "Peers",
|
"headline": "Configuração para a Interface:"
|
||||||
"create": "Criar Peer",
|
},
|
||||||
"public-key": "Chave Pública",
|
"interface-edit": {
|
||||||
"preshared-key": "Chave Pré-partilhada",
|
"headline-edit": "Editar Interface:",
|
||||||
"endpoint": "Endpoint",
|
"headline-new": "Nova Interface",
|
||||||
"allowed-ips": "IPs Permitidos",
|
"tab-interface": "Interface",
|
||||||
"latest-handshake": "Último Handshake",
|
"tab-peerdef": "Padrões de Peer",
|
||||||
"transfer-rx": "Recebido",
|
"header-general": "Geral",
|
||||||
"transfer-tx": "Enviado",
|
"header-network": "Rede",
|
||||||
"persistent-keepalive": "Keepalive Persistente",
|
"header-crypto": "Criptografia",
|
||||||
"actions": "Ações",
|
"header-hooks": "Hooks da Interface",
|
||||||
"edit": "Editar",
|
"header-peer-hooks": "Hooks",
|
||||||
"delete-dialog": {
|
"header-state": "Estado",
|
||||||
"title": "Eliminar Peer",
|
"identifier": {
|
||||||
"text": "Tem a certeza de que deseja eliminar este peer?"
|
"label": "Identificador",
|
||||||
|
"placeholder": "O identificador único da interface"
|
||||||
|
},
|
||||||
|
"mode": {
|
||||||
|
"label": "Modo da Interface",
|
||||||
|
"server": "Modo Servidor",
|
||||||
|
"client": "Modo Cliente",
|
||||||
|
"any": "Modo Desconhecido"
|
||||||
|
},
|
||||||
|
"display-name": {
|
||||||
|
"label": "Nome de Exibição",
|
||||||
|
"placeholder": "O nome descritivo para a interface"
|
||||||
|
},
|
||||||
|
"private-key": {
|
||||||
|
"label": "Chave Privada",
|
||||||
|
"placeholder": "A chave privada"
|
||||||
},
|
},
|
||||||
"form": {
|
|
||||||
"public-key": {
|
"public-key": {
|
||||||
"label": "Chave Pública",
|
"label": "Chave Pública",
|
||||||
"placeholder": "Introduza a chave pública do peer"
|
"placeholder": "A chave pública"
|
||||||
|
},
|
||||||
|
"ip": {
|
||||||
|
"label": "Endereços IP",
|
||||||
|
"placeholder": "Endereços IP (formato CIDR)"
|
||||||
|
},
|
||||||
|
"listen-port": {
|
||||||
|
"label": "Porta de Escuta",
|
||||||
|
"placeholder": "A porta de escuta"
|
||||||
|
},
|
||||||
|
"dns": {
|
||||||
|
"label": "Servidor DNS",
|
||||||
|
"placeholder": "Os servidores DNS que devem ser usados"
|
||||||
|
},
|
||||||
|
"dns-search": {
|
||||||
|
"label": "Domínios de Pesquisa DNS",
|
||||||
|
"placeholder": "Prefixos de pesquisa DNS"
|
||||||
|
},
|
||||||
|
"mtu": {
|
||||||
|
"label": "MTU",
|
||||||
|
"placeholder": "O MTU da interface (0 = manter o valor padrão)"
|
||||||
|
},
|
||||||
|
"firewall-mark": {
|
||||||
|
"label": "Marca de Firewall",
|
||||||
|
"placeholder": "Marca de firewall aplicada ao tráfego de saída. (0 = automático)"
|
||||||
|
},
|
||||||
|
"routing-table": {
|
||||||
|
"label": "Tabela de Roteamento",
|
||||||
|
"placeholder": "O ID da tabela de roteamento",
|
||||||
|
"description": "Casos especiais: off = não gerenciar rotas, 0 = automático"
|
||||||
|
},
|
||||||
|
"pre-up": {
|
||||||
|
"label": "Pre-Up",
|
||||||
|
"placeholder": "Um ou vários comandos bash separados por ;"
|
||||||
|
},
|
||||||
|
"post-up": {
|
||||||
|
"label": "Post-Up",
|
||||||
|
"placeholder": "Um ou vários comandos bash separados por ;"
|
||||||
|
},
|
||||||
|
"pre-down": {
|
||||||
|
"label": "Pre-Down",
|
||||||
|
"placeholder": "Um ou vários comandos bash separados por ;"
|
||||||
|
},
|
||||||
|
"post-down": {
|
||||||
|
"label": "Post-Down",
|
||||||
|
"placeholder": "Um ou vários comandos bash separados por ;"
|
||||||
|
},
|
||||||
|
"disabled": {
|
||||||
|
"label": "Interface Desativada"
|
||||||
|
},
|
||||||
|
"save-config": {
|
||||||
|
"label": "Guardar configuração wg-quick automaticamente"
|
||||||
|
},
|
||||||
|
"defaults": {
|
||||||
|
"endpoint": {
|
||||||
|
"label": "Endereço do Endpoint",
|
||||||
|
"placeholder": "Endereço do Endpoint",
|
||||||
|
"description": "O endereço do endpoint ao qual os peers se irão conectar. (ex. wg.exemplo.com ou wg.exemplo.com:51820)"
|
||||||
|
},
|
||||||
|
"networks": {
|
||||||
|
"label": "Redes IP",
|
||||||
|
"placeholder": "Endereços de Rede",
|
||||||
|
"description": "Os peers irão obter endereços IP a partir dessas sub-redes."
|
||||||
|
},
|
||||||
|
"allowed-ip": {
|
||||||
|
"label": "Endereços IP Permitidos",
|
||||||
|
"placeholder": "Endereços IP Permitidos por padrão"
|
||||||
|
},
|
||||||
|
"mtu": {
|
||||||
|
"label": "MTU",
|
||||||
|
"placeholder": "O MTU do cliente (0 = manter o valor padrão)"
|
||||||
|
},
|
||||||
|
"keep-alive": {
|
||||||
|
"label": "Intervalo de Keep Alive",
|
||||||
|
"placeholder": "Keepalive persistente (0 = padrão)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"button-apply-defaults": "Aplicar Padrões de Peer"
|
||||||
|
},
|
||||||
|
"peer-view": {
|
||||||
|
"headline-peer": "Peer:",
|
||||||
|
"headline-endpoint": "Endpoint:",
|
||||||
|
"section-info": "Informação do Peer",
|
||||||
|
"section-status": "Estado Atual",
|
||||||
|
"section-config": "Configuração",
|
||||||
|
"identifier": "Identificador",
|
||||||
|
"ip": "Endereços IP",
|
||||||
|
"user": "Utilizador Associado",
|
||||||
|
"notes": "Notas",
|
||||||
|
"expiry-status": "Expira em",
|
||||||
|
"disabled-status": "Desativado em",
|
||||||
|
"traffic": "Tráfego",
|
||||||
|
"connection-status": "Estatísticas de Conexão",
|
||||||
|
"upload": "Bytes Enviados (do Servidor para o Peer)",
|
||||||
|
"download": "Bytes Recebidos (do Peer para o Servidor)",
|
||||||
|
"pingable": "É Pingável",
|
||||||
|
"handshake": "Último Handshake",
|
||||||
|
"connected-since": "Conectado desde",
|
||||||
|
"endpoint": "Endpoint",
|
||||||
|
"button-download": "Baixar configuração",
|
||||||
|
"button-email": "Enviar configuração por E-Mail"
|
||||||
|
},
|
||||||
|
"peer-edit": {
|
||||||
|
"headline-edit-peer": "Editar peer:",
|
||||||
|
"headline-edit-endpoint": "Editar endpoint:",
|
||||||
|
"headline-new-peer": "Criar peer",
|
||||||
|
"headline-new-endpoint": "Criar endpoint",
|
||||||
|
"header-general": "Geral",
|
||||||
|
"header-network": "Rede",
|
||||||
|
"header-crypto": "Criptografia",
|
||||||
|
"header-hooks": "Hooks (Executados no Peer)",
|
||||||
|
"header-state": "Estado",
|
||||||
|
"display-name": {
|
||||||
|
"label": "Nome de Exibição",
|
||||||
|
"placeholder": "O nome descritivo para o peer"
|
||||||
|
},
|
||||||
|
"linked-user": {
|
||||||
|
"label": "Utilizador Associado",
|
||||||
|
"placeholder": "A conta de utilizador que possui este peer"
|
||||||
|
},
|
||||||
|
"private-key": {
|
||||||
|
"label": "Chave Privada",
|
||||||
|
"placeholder": "A chave privada",
|
||||||
|
"help": "A chave privada é armazenada de forma segura no servidor. Se o utilizador já tiver uma cópia, pode omitir este campo. O servidor ainda funciona exclusivamente com a chave pública do peer."
|
||||||
|
},
|
||||||
|
"public-key": {
|
||||||
|
"label": "Chave Pública",
|
||||||
|
"placeholder": "A chave pública"
|
||||||
},
|
},
|
||||||
"preshared-key": {
|
"preshared-key": {
|
||||||
"label": "Chave Pré-partilhada",
|
"label": "Chave Pré-Partilhada",
|
||||||
"placeholder": "Opcional: Chave partilhada adicional para maior segurança"
|
"placeholder": "Chave pré-partilhada opcional"
|
||||||
|
},
|
||||||
|
"endpoint-public-key": {
|
||||||
|
"label": "Chave Pública do Endpoint",
|
||||||
|
"placeholder": "A chave pública do endpoint remoto"
|
||||||
},
|
},
|
||||||
"endpoint": {
|
"endpoint": {
|
||||||
"label": "Endpoint",
|
"label": "Endereço do Endpoint",
|
||||||
"placeholder": "Endereço público do peer (ex: 1.2.3.4:51820)"
|
"placeholder": "O endereço do endpoint remoto"
|
||||||
},
|
},
|
||||||
"allowed-ips": {
|
"ip": {
|
||||||
"label": "IPs Permitidos",
|
"label": "Endereços IP",
|
||||||
"placeholder": "Lista de IPs (ex: 10.0.0.2/32, 192.168.1.0/24)"
|
"placeholder": "Endereços IP (formato CIDR)"
|
||||||
},
|
},
|
||||||
"persistent-keepalive": {
|
"allowed-ip": {
|
||||||
"label": "Keepalive Persistente",
|
"label": "Endereços IP Permitidos",
|
||||||
"placeholder": "Ex: 25 (em segundos)"
|
"placeholder": "Endereços IP permitidos"
|
||||||
}
|
},
|
||||||
|
"extra-allowed-ip": {
|
||||||
|
"label": "Endereços IP adicionais permitidos",
|
||||||
|
"placeholder": "IPs adicionais permitidos (lado do servidor)",
|
||||||
|
"description": "Esses IPs serão adicionados à interface WireGuard remota como IPs permitidos."
|
||||||
|
},
|
||||||
|
"dns": {
|
||||||
|
"label": "Servidor DNS",
|
||||||
|
"placeholder": "Os servidores DNS que devem ser utilizados"
|
||||||
|
},
|
||||||
|
"dns-search": {
|
||||||
|
"label": "Domínios de Pesquisa DNS",
|
||||||
|
"placeholder": "Prefixos de pesquisa DNS"
|
||||||
|
},
|
||||||
|
"keep-alive": {
|
||||||
|
"label": "Intervalo de Keep Alive",
|
||||||
|
"placeholder": "Keepalive persistente (0 = padrão)"
|
||||||
|
},
|
||||||
|
"mtu": {
|
||||||
|
"label": "MTU",
|
||||||
|
"placeholder": "O MTU do cliente (0 = manter o padrão)"
|
||||||
|
},
|
||||||
|
"pre-up": {
|
||||||
|
"label": "Pre-Up",
|
||||||
|
"placeholder": "Um ou vários comandos bash separados por ;"
|
||||||
|
},
|
||||||
|
"post-up": {
|
||||||
|
"label": "Post-Up",
|
||||||
|
"placeholder": "Um ou vários comandos bash separados por ;"
|
||||||
|
},
|
||||||
|
"pre-down": {
|
||||||
|
"label": "Pre-Down",
|
||||||
|
"placeholder": "Um ou vários comandos bash separados por ;"
|
||||||
|
},
|
||||||
|
"post-down": {
|
||||||
|
"label": "Post-Down",
|
||||||
|
"placeholder": "Um ou vários comandos bash separados por ;"
|
||||||
|
},
|
||||||
|
"disabled": {
|
||||||
|
"label": "Peer Desativado"
|
||||||
|
},
|
||||||
|
"ignore-global": {
|
||||||
|
"label": "Ignorar definições globais"
|
||||||
|
},
|
||||||
|
"expires-at": {
|
||||||
|
"label": "Data de expiração"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"settings": {
|
"peer-multi-create": {
|
||||||
"title": "Definições",
|
"headline-peer": "Criar múltiplos peers",
|
||||||
"password": {
|
"headline-endpoint": "Criar múltiplos endpoints",
|
||||||
"label": "Nova Palavra-passe",
|
"identifiers": {
|
||||||
"placeholder": "Deixe em branco para manter a atual"
|
"label": "Identificadores de utilizador",
|
||||||
|
"placeholder": "Identificadores de utilizador",
|
||||||
|
"description": "Um identificador de utilizador (nome de utilizador) para o qual um peer deve ser criado."
|
||||||
},
|
},
|
||||||
"save": "Guardar Alterações"
|
"prefix": {
|
||||||
},
|
"headline-peer": "Peer:",
|
||||||
"audit": {
|
"headline-endpoint": "Endpoint:",
|
||||||
"title": "Registo de Auditoria",
|
"label": "Prefixo do nome exibido",
|
||||||
"username": "Utilizador",
|
"placeholder": "O prefixo",
|
||||||
"ip": "Endereço IP",
|
"description": "Um prefixo que será adicionado ao nome exibido do peer."
|
||||||
"method": "Método",
|
}
|
||||||
"path": "Caminho",
|
}
|
||||||
"status": "Estado",
|
|
||||||
"timestamp": "Data/Hora"
|
|
||||||
},
|
|
||||||
"errors": {
|
|
||||||
"required": "Este campo é obrigatório",
|
|
||||||
"invalid-email": "Endereço de email inválido",
|
|
||||||
"invalid-address": "Endereço inválido",
|
|
||||||
"invalid-endpoint": "Endpoint inválido",
|
|
||||||
"invalid-allowed-ips": "Formato de IPs Permitidos inválido"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -129,7 +129,7 @@ export const profileStore = defineStore('profile', {
|
|||||||
return apiWrapper.post(`${baseUrl}/${base64_url_encode(currentUser)}/api/enable`)
|
return apiWrapper.post(`${baseUrl}/${base64_url_encode(currentUser)}/api/enable`)
|
||||||
.then(this.setUser)
|
.then(this.setUser)
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
this.setPeers([])
|
this.fetching = false
|
||||||
console.log("Failed to activate API for ", currentUser, ": ", error)
|
console.log("Failed to activate API for ", currentUser, ": ", error)
|
||||||
notify({
|
notify({
|
||||||
title: "Backend Connection Failure",
|
title: "Backend Connection Failure",
|
||||||
@@ -143,7 +143,7 @@ export const profileStore = defineStore('profile', {
|
|||||||
return apiWrapper.post(`${baseUrl}/${base64_url_encode(currentUser)}/api/disable`)
|
return apiWrapper.post(`${baseUrl}/${base64_url_encode(currentUser)}/api/disable`)
|
||||||
.then(this.setUser)
|
.then(this.setUser)
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
this.setPeers([])
|
this.fetching = false
|
||||||
console.log("Failed to deactivate API for ", currentUser, ": ", error)
|
console.log("Failed to deactivate API for ", currentUser, ": ", error)
|
||||||
notify({
|
notify({
|
||||||
title: "Backend Connection Failure",
|
title: "Backend Connection Failure",
|
||||||
|
@@ -81,7 +81,7 @@ onMounted(async () => {
|
|||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<label class="col-sm-6 col-form-label text-end" for="paginationSelector">{{ $t('general.pagination.size') }}:</label>
|
<label class="col-sm-6 col-form-label text-end" for="paginationSelector">{{ $t('general.pagination.size') }}:</label>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<select v-model.number="audit.pageSize" class="form-select" @click="audit.afterPageSizeChange()">
|
<select id="paginationSelector" v-model.number="audit.pageSize" class="form-select" @click="audit.afterPageSizeChange()">
|
||||||
<option value="10">10</option>
|
<option value="10">10</option>
|
||||||
<option value="25">25</option>
|
<option value="25">25</option>
|
||||||
<option value="50">50</option>
|
<option value="50">50</option>
|
||||||
|
@@ -416,7 +416,7 @@ onMounted(async () => {
|
|||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<label class="col-sm-6 col-form-label text-end" for="paginationSelector">{{ $t('general.pagination.size') }}:</label>
|
<label class="col-sm-6 col-form-label text-end" for="paginationSelector">{{ $t('general.pagination.size') }}:</label>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<select v-model.number="peers.pageSize" class="form-select" @click="peers.afterPageSizeChange()">
|
<select id="paginationSelector" v-model.number="peers.pageSize" class="form-select" @click="peers.afterPageSizeChange()">
|
||||||
<option value="10">10</option>
|
<option value="10">10</option>
|
||||||
<option value="25">25</option>
|
<option value="25">25</option>
|
||||||
<option value="50">50</option>
|
<option value="50">50</option>
|
||||||
|
@@ -178,7 +178,7 @@ onMounted(async () => {
|
|||||||
{{ $t('general.pagination.size')}}:
|
{{ $t('general.pagination.size')}}:
|
||||||
</label>
|
</label>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<select v-model.number="profile.pageSize" class="form-select" @click="profile.afterPageSizeChange()">
|
<select id="paginationSelector" v-model.number="profile.pageSize" class="form-select" @click="profile.afterPageSizeChange()">
|
||||||
<option value="10">10</option>
|
<option value="10">10</option>
|
||||||
<option value="25">25</option>
|
<option value="25">25</option>
|
||||||
<option value="50">50</option>
|
<option value="50">50</option>
|
||||||
|
@@ -116,7 +116,7 @@ onMounted(() => {
|
|||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<label class="col-sm-6 col-form-label text-end" for="paginationSelector">{{ $t('general.pagination.size') }}:</label>
|
<label class="col-sm-6 col-form-label text-end" for="paginationSelector">{{ $t('general.pagination.size') }}:</label>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<select v-model.number="users.pageSize" class="form-select" @click="users.afterPageSizeChange()">
|
<select id="paginationSelector" v-model.number="users.pageSize" class="form-select" @click="users.afterPageSizeChange()">
|
||||||
<option value="10">10</option>
|
<option value="10">10</option>
|
||||||
<option value="25">25</option>
|
<option value="25">25</option>
|
||||||
<option value="50">50</option>
|
<option value="50">50</option>
|
||||||
|
15
go.mod
15
go.mod
@@ -16,19 +16,19 @@ require (
|
|||||||
github.com/stretchr/testify v1.10.0
|
github.com/stretchr/testify v1.10.0
|
||||||
github.com/swaggo/swag v1.16.4
|
github.com/swaggo/swag v1.16.4
|
||||||
github.com/vardius/message-bus v1.1.5
|
github.com/vardius/message-bus v1.1.5
|
||||||
github.com/vishvananda/netlink v1.3.0
|
github.com/vishvananda/netlink v1.3.1
|
||||||
github.com/xhit/go-simple-mail/v2 v2.16.0
|
github.com/xhit/go-simple-mail/v2 v2.16.0
|
||||||
github.com/yeqown/go-qrcode/v2 v2.2.5
|
github.com/yeqown/go-qrcode/v2 v2.2.5
|
||||||
github.com/yeqown/go-qrcode/writer/compressed v1.0.1
|
github.com/yeqown/go-qrcode/writer/compressed v1.0.1
|
||||||
golang.org/x/crypto v0.37.0
|
golang.org/x/crypto v0.38.0
|
||||||
golang.org/x/oauth2 v0.29.0
|
golang.org/x/oauth2 v0.30.0
|
||||||
golang.org/x/sys v0.32.0
|
golang.org/x/sys v0.33.0
|
||||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10
|
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
gorm.io/driver/mysql v1.5.7
|
gorm.io/driver/mysql v1.5.7
|
||||||
gorm.io/driver/postgres v1.5.11
|
gorm.io/driver/postgres v1.5.11
|
||||||
gorm.io/driver/sqlserver v1.5.4
|
gorm.io/driver/sqlserver v1.5.4
|
||||||
gorm.io/gorm v1.25.12
|
gorm.io/gorm v1.26.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@@ -62,7 +62,6 @@ require (
|
|||||||
github.com/jinzhu/now v1.1.5 // indirect
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
github.com/josharian/intern v1.0.0 // indirect
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/josharian/native v1.1.0 // indirect
|
github.com/josharian/native v1.1.0 // indirect
|
||||||
github.com/klauspost/compress v1.18.0 // indirect
|
|
||||||
github.com/leodido/go-urn v1.4.0 // indirect
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
github.com/mailru/easyjson v0.9.0 // indirect
|
github.com/mailru/easyjson v0.9.0 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
@@ -82,8 +81,8 @@ require (
|
|||||||
github.com/yeqown/reedsolomon v1.0.0 // indirect
|
github.com/yeqown/reedsolomon v1.0.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect
|
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect
|
||||||
golang.org/x/net v0.39.0 // indirect
|
golang.org/x/net v0.39.0 // indirect
|
||||||
golang.org/x/sync v0.13.0 // indirect
|
golang.org/x/sync v0.14.0 // indirect
|
||||||
golang.org/x/text v0.24.0 // indirect
|
golang.org/x/text v0.25.0 // indirect
|
||||||
golang.org/x/tools v0.32.0 // indirect
|
golang.org/x/tools v0.32.0 // indirect
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 // indirect
|
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 // indirect
|
||||||
google.golang.org/protobuf v1.36.6 // indirect
|
google.golang.org/protobuf v1.36.6 // indirect
|
||||||
|
102
go.sum
102
go.sum
@@ -44,24 +44,16 @@ github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/
|
|||||||
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
|
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
|
||||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
|
||||||
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
|
||||||
github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
|
github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
|
github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
|
||||||
github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec+ruQ=
|
github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec+ruQ=
|
||||||
github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc=
|
github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc=
|
||||||
github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
|
github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
|
||||||
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
|
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.7 h1:DTX+lbVTWaTw1hQ+PbZPlnDZPEIs0SS/GCZAl535dDk=
|
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.7/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo=
|
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo=
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||||
github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
|
|
||||||
github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
|
|
||||||
github.com/go-jose/go-jose/v4 v4.1.0 h1:cYSYxd3pw5zd2FSXk2vGdn9igQU2PS8MuxrCOCl0FdY=
|
github.com/go-jose/go-jose/v4 v4.1.0 h1:cYSYxd3pw5zd2FSXk2vGdn9igQU2PS8MuxrCOCl0FdY=
|
||||||
github.com/go-jose/go-jose/v4 v4.1.0/go.mod h1:GG/vqmYm3Von2nYiB2vGTXzdoNKE5tix5tuc6iAd+sw=
|
github.com/go-jose/go-jose/v4 v4.1.0/go.mod h1:GG/vqmYm3Von2nYiB2vGTXzdoNKE5tix5tuc6iAd+sw=
|
||||||
github.com/go-ldap/ldap/v3 v3.4.10 h1:ot/iwPOhfpNVgB1o+AVXljizWZ9JTp7YF5oeyONmcJU=
|
|
||||||
github.com/go-ldap/ldap/v3 v3.4.10/go.mod h1:JXh4Uxgi40P6E9rdsYqpUtbW46D9UTjJ9QSwGRznplY=
|
|
||||||
github.com/go-ldap/ldap/v3 v3.4.11 h1:4k0Yxweg+a3OyBLjdYn5OKglv18JNvfDykSoI8bW0gU=
|
github.com/go-ldap/ldap/v3 v3.4.11 h1:4k0Yxweg+a3OyBLjdYn5OKglv18JNvfDykSoI8bW0gU=
|
||||||
github.com/go-ldap/ldap/v3 v3.4.11/go.mod h1:bY7t0FLK8OAVpp/vV6sSlpz3EQDGcQwc8pF0ujLgKvM=
|
github.com/go-ldap/ldap/v3 v3.4.11/go.mod h1:bY7t0FLK8OAVpp/vV6sSlpz3EQDGcQwc8pF0ujLgKvM=
|
||||||
github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic=
|
github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic=
|
||||||
@@ -83,8 +75,6 @@ github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91
|
|||||||
github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k=
|
github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k=
|
||||||
github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
|
github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
|
||||||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||||
github.com/go-sql-driver/mysql v1.9.1 h1:FrjNGn/BsJQjVRuSa8CBrM5BWA9BWoXXat3KrtSb/iI=
|
|
||||||
github.com/go-sql-driver/mysql v1.9.1/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
|
|
||||||
github.com/go-sql-driver/mysql v1.9.2 h1:4cNKDYQ1I84SXslGddlsrMhc8k4LeDVj6Ad6WRjiHuU=
|
github.com/go-sql-driver/mysql v1.9.2 h1:4cNKDYQ1I84SXslGddlsrMhc8k4LeDVj6Ad6WRjiHuU=
|
||||||
github.com/go-sql-driver/mysql v1.9.2/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
|
github.com/go-sql-driver/mysql v1.9.2/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
|
||||||
github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
|
github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
|
||||||
@@ -98,12 +88,10 @@ github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2V
|
|||||||
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
||||||
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
|
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
|
||||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo=
|
|
||||||
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
|
|
||||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
|
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
|
||||||
|
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
@@ -117,8 +105,6 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI
|
|||||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||||
github.com/jackc/pgx/v5 v5.7.3 h1:PO1wNKj/bTAwxSJnO1Z4Ai8j4magtqg2SLNjEDzcXQo=
|
|
||||||
github.com/jackc/pgx/v5 v5.7.3/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ=
|
|
||||||
github.com/jackc/pgx/v5 v5.7.4 h1:9wKznZrhWa2QiHL+NjTSPP6yjl3451BX3imWDnokYlg=
|
github.com/jackc/pgx/v5 v5.7.4 h1:9wKznZrhWa2QiHL+NjTSPP6yjl3451BX3imWDnokYlg=
|
||||||
github.com/jackc/pgx/v5 v5.7.4/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ=
|
github.com/jackc/pgx/v5 v5.7.4/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ=
|
||||||
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
||||||
@@ -179,16 +165,10 @@ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmd
|
|||||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus-community/pro-bing v0.6.1 h1:EQukUOma9YFZRPe4DGSscxUf9LH07rpqwisNWjSZrgU=
|
|
||||||
github.com/prometheus-community/pro-bing v0.6.1/go.mod h1:jNCOI3D7pmTCeaoF41cNS6uaxeFY/Gmc3ffwbuJVzAQ=
|
|
||||||
github.com/prometheus-community/pro-bing v0.7.0 h1:KFYFbxC2f2Fp6c+TyxbCOEarf7rbnzr9Gw8eIb0RfZA=
|
github.com/prometheus-community/pro-bing v0.7.0 h1:KFYFbxC2f2Fp6c+TyxbCOEarf7rbnzr9Gw8eIb0RfZA=
|
||||||
github.com/prometheus-community/pro-bing v0.7.0/go.mod h1:Moob9dvlY50Bfq6i88xIwfyw7xLFHH69LUgx9n5zqCE=
|
github.com/prometheus-community/pro-bing v0.7.0/go.mod h1:Moob9dvlY50Bfq6i88xIwfyw7xLFHH69LUgx9n5zqCE=
|
||||||
github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGCQ8YOmu+Ibk=
|
|
||||||
github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg=
|
|
||||||
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
|
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
|
||||||
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
|
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
|
||||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
|
||||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
|
||||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||||
github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k=
|
github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k=
|
||||||
@@ -218,9 +198,8 @@ github.com/toorop/go-dkim v0.0.0-20250226130143-9025cce95817 h1:q0hKh5a5FRkhuTb5
|
|||||||
github.com/toorop/go-dkim v0.0.0-20250226130143-9025cce95817/go.mod h1:BzWtXXrXzZUvMacR0oF/fbDDgUPO8L36tDMmRAf14ns=
|
github.com/toorop/go-dkim v0.0.0-20250226130143-9025cce95817/go.mod h1:BzWtXXrXzZUvMacR0oF/fbDDgUPO8L36tDMmRAf14ns=
|
||||||
github.com/vardius/message-bus v1.1.5 h1:YSAC2WB4HRlwc4neFPTmT88kzzoiQ+9WRRbej/E/LZc=
|
github.com/vardius/message-bus v1.1.5 h1:YSAC2WB4HRlwc4neFPTmT88kzzoiQ+9WRRbej/E/LZc=
|
||||||
github.com/vardius/message-bus v1.1.5/go.mod h1:6xladCV2lMkUAE4bzzS85qKOiB5miV7aBVRafiTJGqw=
|
github.com/vardius/message-bus v1.1.5/go.mod h1:6xladCV2lMkUAE4bzzS85qKOiB5miV7aBVRafiTJGqw=
|
||||||
github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk=
|
github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0=
|
||||||
github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs=
|
github.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4=
|
||||||
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
|
||||||
github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY=
|
github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY=
|
||||||
github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
||||||
github.com/xhit/go-simple-mail/v2 v2.16.0 h1:ouGy/Ww4kuaqu2E2UrDw7SvLaziWTB60ICLkIkNVccA=
|
github.com/xhit/go-simple-mail/v2 v2.16.0 h1:ouGy/Ww4kuaqu2E2UrDw7SvLaziWTB60ICLkIkNVccA=
|
||||||
@@ -237,25 +216,16 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
|
|||||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||||
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
|
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
|
||||||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
|
||||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||||
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
||||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
||||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
|
||||||
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
|
|
||||||
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
|
|
||||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw=
|
|
||||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM=
|
|
||||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM=
|
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM=
|
||||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8=
|
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
|
||||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
|
||||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
|
||||||
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
|
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
|
||||||
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
@@ -268,28 +238,18 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
|||||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||||
golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
||||||
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
||||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
|
||||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
|
||||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
|
||||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
|
||||||
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
|
|
||||||
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
|
||||||
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
|
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
|
||||||
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
|
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
|
||||||
golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98=
|
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||||
golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
||||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
|
||||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
|
||||||
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
|
|
||||||
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
@@ -303,16 +263,11 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
|
||||||
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
|
|
||||||
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
|
||||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
@@ -320,13 +275,9 @@ golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
|||||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||||
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
|
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
|
||||||
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
||||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
|
||||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||||
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
||||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
|
||||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
|
||||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
@@ -337,18 +288,12 @@ golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
|||||||
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||||
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
|
|
||||||
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
|
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
|
||||||
golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=
|
|
||||||
golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ=
|
|
||||||
golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU=
|
golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU=
|
||||||
golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s=
|
golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
@@ -356,8 +301,6 @@ golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uI
|
|||||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA=
|
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA=
|
||||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10 h1:3GDAcqdIg1ozBNLgPy4SLT84nfcBjr6rhGtXYtrkWLU=
|
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10 h1:3GDAcqdIg1ozBNLgPy4SLT84nfcBjr6rhGtXYtrkWLU=
|
||||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10/go.mod h1:T97yPqesLiNrOYxkwmhMI0ZIlJDm+p0PMR8eRVeR5tQ=
|
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10/go.mod h1:T97yPqesLiNrOYxkwmhMI0ZIlJDm+p0PMR8eRVeR5tQ=
|
||||||
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
|
||||||
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
|
||||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
@@ -378,35 +321,26 @@ gorm.io/driver/sqlserver v1.5.4 h1:xA+Y1KDNspv79q43bPyjDMUgHoYHLhXYmdFcYPobg8g=
|
|||||||
gorm.io/driver/sqlserver v1.5.4/go.mod h1:+frZ/qYmuna11zHPlh5oc2O6ZA/lS88Keb0XSH1Zh/g=
|
gorm.io/driver/sqlserver v1.5.4/go.mod h1:+frZ/qYmuna11zHPlh5oc2O6ZA/lS88Keb0XSH1Zh/g=
|
||||||
gorm.io/gorm v1.25.7-0.20240204074919-46816ad31dde/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
gorm.io/gorm v1.25.7-0.20240204074919-46816ad31dde/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||||
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||||
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
|
gorm.io/gorm v1.26.1 h1:ghB2gUI9FkS46luZtn6DLZ0f6ooBJ5IbVej2ENFDjRw=
|
||||||
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
gorm.io/gorm v1.26.1/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
|
||||||
modernc.org/cc/v4 v4.24.4 h1:TFkx1s6dCkQpd6dKurBNmpo+G8Zl4Sq/ztJ+2+DEsh0=
|
|
||||||
modernc.org/cc/v4 v4.24.4/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
|
|
||||||
modernc.org/cc/v4 v4.26.0 h1:QMYvbVduUGH0rrO+5mqF/PSPPRZNpRtg2CLELy7vUpA=
|
modernc.org/cc/v4 v4.26.0 h1:QMYvbVduUGH0rrO+5mqF/PSPPRZNpRtg2CLELy7vUpA=
|
||||||
modernc.org/ccgo/v4 v4.23.16 h1:Z2N+kk38b7SfySC1ZkpGLN2vthNJP1+ZzGZIlH7uBxo=
|
modernc.org/cc/v4 v4.26.0/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
|
||||||
modernc.org/ccgo/v4 v4.23.16/go.mod h1:nNma8goMTY7aQZQNTyN9AIoJfxav4nvTnvKThAeMDdo=
|
|
||||||
modernc.org/ccgo/v4 v4.26.0 h1:gVzXaDzGeBYJ2uXTOpR8FR7OlksDOe9jxnjhIKCsiTc=
|
modernc.org/ccgo/v4 v4.26.0 h1:gVzXaDzGeBYJ2uXTOpR8FR7OlksDOe9jxnjhIKCsiTc=
|
||||||
|
modernc.org/ccgo/v4 v4.26.0/go.mod h1:Sem8f7TFUtVXkG2fiaChQtyyfkqhJBg/zjEJBkmuAVY=
|
||||||
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
|
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
|
||||||
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
|
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
|
||||||
modernc.org/gc/v2 v2.6.3 h1:aJVhcqAte49LF+mGveZ5KPlsp4tdGdAOT4sipJXADjw=
|
|
||||||
modernc.org/gc/v2 v2.6.3/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
|
|
||||||
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
|
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
|
||||||
modernc.org/libc v1.61.13 h1:3LRd6ZO1ezsFiX1y+bHd1ipyEHIJKvuprv0sLTBwLW8=
|
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
|
||||||
modernc.org/libc v1.61.13/go.mod h1:8F/uJWL/3nNil0Lgt1Dpz+GgkApWh04N3el3hxJcA6E=
|
|
||||||
modernc.org/libc v1.63.0 h1:wKzb61wOGCzgahQBORb1b0dZonh8Ufzl/7r4Yf1D5YA=
|
modernc.org/libc v1.63.0 h1:wKzb61wOGCzgahQBORb1b0dZonh8Ufzl/7r4Yf1D5YA=
|
||||||
modernc.org/libc v1.63.0/go.mod h1:wDzH1mgz1wUIEwottFt++POjGRO9sgyQKrpXaz3x89E=
|
modernc.org/libc v1.63.0/go.mod h1:wDzH1mgz1wUIEwottFt++POjGRO9sgyQKrpXaz3x89E=
|
||||||
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
|
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
|
||||||
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
|
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
|
||||||
modernc.org/memory v1.9.1 h1:V/Z1solwAVmMW1yttq3nDdZPJqV1rM05Ccq6KMSZ34g=
|
|
||||||
modernc.org/memory v1.9.1/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
|
|
||||||
modernc.org/memory v1.10.0 h1:fzumd51yQ1DxcOxSO+S6X7+QTuVU+n8/Aj7swYjFfC4=
|
modernc.org/memory v1.10.0 h1:fzumd51yQ1DxcOxSO+S6X7+QTuVU+n8/Aj7swYjFfC4=
|
||||||
modernc.org/memory v1.10.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
|
modernc.org/memory v1.10.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
|
||||||
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
|
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
|
||||||
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
|
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
|
||||||
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
|
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
|
||||||
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
|
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
|
||||||
modernc.org/sqlite v1.36.1 h1:bDa8BJUH4lg6EGkLbahKe/8QqoF8p9gArSc6fTqYhyQ=
|
|
||||||
modernc.org/sqlite v1.36.1/go.mod h1:7MPwH7Z6bREicF9ZVUR78P1IKuxfZ8mRIDHD0iD+8TU=
|
|
||||||
modernc.org/sqlite v1.37.0 h1:s1TMe7T3Q3ovQiK2Ouz4Jwh7dw4ZDqbebSDTlSJdfjI=
|
modernc.org/sqlite v1.37.0 h1:s1TMe7T3Q3ovQiK2Ouz4Jwh7dw4ZDqbebSDTlSJdfjI=
|
||||||
modernc.org/sqlite v1.37.0/go.mod h1:5YiWv+YviqGMuGw4V+PNplcyaJ5v+vQd7TQOgkACoJM=
|
modernc.org/sqlite v1.37.0/go.mod h1:5YiWv+YviqGMuGw4V+PNplcyaJ5v+vQd7TQOgkACoJM=
|
||||||
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
|
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
|
||||||
|
@@ -118,6 +118,7 @@
|
|||||||
"BasicAuth": []
|
"BasicAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"description": "This endpoint updates an existing interface with the provided data. All required fields must be filled (e.g. name, private key, public key, ...).",
|
||||||
"produces": [
|
"produces": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -250,6 +251,7 @@
|
|||||||
"BasicAuth": []
|
"BasicAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"description": "This endpoint creates a new interface with the provided data. All required fields must be filled (e.g. name, private key, public key, ...).",
|
||||||
"produces": [
|
"produces": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -309,6 +311,50 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/interface/prepare": {
|
||||||
|
"get": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"BasicAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "This endpoint returns a new interface with default values (fresh key pair, valid name, new IP address pool, ...).",
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Interfaces"
|
||||||
|
],
|
||||||
|
"summary": "Prepare a new interface record.",
|
||||||
|
"operationId": "interfaces_handlePrepareGet",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/models.Interface"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"401": {
|
||||||
|
"description": "Unauthorized",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/models.Error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"403": {
|
||||||
|
"description": "Forbidden",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/models.Error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/models.Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/metrics/by-interface/{id}": {
|
"/metrics/by-interface/{id}": {
|
||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
@@ -547,7 +593,7 @@
|
|||||||
"BasicAuth": []
|
"BasicAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Only admins can update existing records.",
|
"description": "Only admins can update existing records. The peer record must contain all required fields (e.g., public key, allowed IPs).",
|
||||||
"produces": [
|
"produces": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -779,7 +825,7 @@
|
|||||||
"BasicAuth": []
|
"BasicAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Only admins can create new records.",
|
"description": "Only admins can create new records. The peer record must contain all required fields (e.g., public key, allowed IPs).",
|
||||||
"produces": [
|
"produces": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@@ -839,6 +885,71 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/peer/prepare/{id}": {
|
||||||
|
"get": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"BasicAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "This endpoint is used to prepare a new peer record. The returned data contains a fresh key pair and valid ip address.",
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Peers"
|
||||||
|
],
|
||||||
|
"summary": "Prepare a new peer record for the given WireGuard interface.",
|
||||||
|
"operationId": "peers_handlePrepareGet",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "The interface identifier.",
|
||||||
|
"name": "id",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/models.Peer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Bad Request",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/models.Error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"401": {
|
||||||
|
"description": "Unauthorized",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/models.Error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"403": {
|
||||||
|
"description": "Forbidden",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/models.Error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Not Found",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/models.Error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/models.Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/provisioning/data/peer-config": {
|
"/provisioning/data/peer-config": {
|
||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
|
@@ -748,6 +748,8 @@ paths:
|
|||||||
tags:
|
tags:
|
||||||
- Interfaces
|
- Interfaces
|
||||||
put:
|
put:
|
||||||
|
description: This endpoint updates an existing interface with the provided data.
|
||||||
|
All required fields must be filled (e.g. name, private key, public key, ...).
|
||||||
operationId: interfaces_handleUpdatePut
|
operationId: interfaces_handleUpdatePut
|
||||||
parameters:
|
parameters:
|
||||||
- description: The interface identifier.
|
- description: The interface identifier.
|
||||||
@@ -795,6 +797,8 @@ paths:
|
|||||||
- Interfaces
|
- Interfaces
|
||||||
/interface/new:
|
/interface/new:
|
||||||
post:
|
post:
|
||||||
|
description: This endpoint creates a new interface with the provided data. All
|
||||||
|
required fields must be filled (e.g. name, private key, public key, ...).
|
||||||
operationId: interfaces_handleCreatePost
|
operationId: interfaces_handleCreatePost
|
||||||
parameters:
|
parameters:
|
||||||
- description: The interface data.
|
- description: The interface data.
|
||||||
@@ -835,6 +839,35 @@ paths:
|
|||||||
summary: Create a new interface record.
|
summary: Create a new interface record.
|
||||||
tags:
|
tags:
|
||||||
- Interfaces
|
- Interfaces
|
||||||
|
/interface/prepare:
|
||||||
|
get:
|
||||||
|
description: This endpoint returns a new interface with default values (fresh
|
||||||
|
key pair, valid name, new IP address pool, ...).
|
||||||
|
operationId: interfaces_handlePrepareGet
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/models.Interface'
|
||||||
|
"401":
|
||||||
|
description: Unauthorized
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/models.Error'
|
||||||
|
"403":
|
||||||
|
description: Forbidden
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/models.Error'
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/models.Error'
|
||||||
|
security:
|
||||||
|
- BasicAuth: []
|
||||||
|
summary: Prepare a new interface record.
|
||||||
|
tags:
|
||||||
|
- Interfaces
|
||||||
/metrics/by-interface/{id}:
|
/metrics/by-interface/{id}:
|
||||||
get:
|
get:
|
||||||
operationId: metrics_handleMetricsForInterfaceGet
|
operationId: metrics_handleMetricsForInterfaceGet
|
||||||
@@ -1024,7 +1057,8 @@ paths:
|
|||||||
tags:
|
tags:
|
||||||
- Peers
|
- Peers
|
||||||
put:
|
put:
|
||||||
description: Only admins can update existing records.
|
description: Only admins can update existing records. The peer record must contain
|
||||||
|
all required fields (e.g., public key, allowed IPs).
|
||||||
operationId: peers_handleUpdatePut
|
operationId: peers_handleUpdatePut
|
||||||
parameters:
|
parameters:
|
||||||
- description: The peer identifier.
|
- description: The peer identifier.
|
||||||
@@ -1136,7 +1170,8 @@ paths:
|
|||||||
- Peers
|
- Peers
|
||||||
/peer/new:
|
/peer/new:
|
||||||
post:
|
post:
|
||||||
description: Only admins can create new records.
|
description: Only admins can create new records. The peer record must contain
|
||||||
|
all required fields (e.g., public key, allowed IPs).
|
||||||
operationId: peers_handleCreatePost
|
operationId: peers_handleCreatePost
|
||||||
parameters:
|
parameters:
|
||||||
- description: The peer data.
|
- description: The peer data.
|
||||||
@@ -1177,6 +1212,49 @@ paths:
|
|||||||
summary: Create a new peer record.
|
summary: Create a new peer record.
|
||||||
tags:
|
tags:
|
||||||
- Peers
|
- Peers
|
||||||
|
/peer/prepare/{id}:
|
||||||
|
get:
|
||||||
|
description: This endpoint is used to prepare a new peer record. The returned
|
||||||
|
data contains a fresh key pair and valid ip address.
|
||||||
|
operationId: peers_handlePrepareGet
|
||||||
|
parameters:
|
||||||
|
- description: The interface identifier.
|
||||||
|
in: path
|
||||||
|
name: id
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/models.Peer'
|
||||||
|
"400":
|
||||||
|
description: Bad Request
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/models.Error'
|
||||||
|
"401":
|
||||||
|
description: Unauthorized
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/models.Error'
|
||||||
|
"403":
|
||||||
|
description: Forbidden
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/models.Error'
|
||||||
|
"404":
|
||||||
|
description: Not Found
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/models.Error'
|
||||||
|
"500":
|
||||||
|
description: Internal Server Error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/models.Error'
|
||||||
|
security:
|
||||||
|
- BasicAuth: []
|
||||||
|
summary: Prepare a new peer record for the given WireGuard interface.
|
||||||
|
tags:
|
||||||
|
- Peers
|
||||||
/provisioning/data/peer-config:
|
/provisioning/data/peer-config:
|
||||||
get:
|
get:
|
||||||
description: Normal users can only access their own record. Admins can access
|
description: Normal users can only access their own record. Admins can access
|
||||||
|
@@ -11,6 +11,7 @@ import (
|
|||||||
type InterfaceServiceInterfaceManagerRepo interface {
|
type InterfaceServiceInterfaceManagerRepo interface {
|
||||||
GetAllInterfacesAndPeers(ctx context.Context) ([]domain.Interface, [][]domain.Peer, error)
|
GetAllInterfacesAndPeers(ctx context.Context) ([]domain.Interface, [][]domain.Peer, error)
|
||||||
GetInterfaceAndPeers(ctx context.Context, id domain.InterfaceIdentifier) (*domain.Interface, []domain.Peer, error)
|
GetInterfaceAndPeers(ctx context.Context, id domain.InterfaceIdentifier) (*domain.Interface, []domain.Peer, error)
|
||||||
|
PrepareInterface(ctx context.Context) (*domain.Interface, error)
|
||||||
CreateInterface(ctx context.Context, in *domain.Interface) (*domain.Interface, error)
|
CreateInterface(ctx context.Context, in *domain.Interface) (*domain.Interface, error)
|
||||||
UpdateInterface(ctx context.Context, in *domain.Interface) (*domain.Interface, []domain.Peer, error)
|
UpdateInterface(ctx context.Context, in *domain.Interface) (*domain.Interface, []domain.Peer, error)
|
||||||
DeleteInterface(ctx context.Context, id domain.InterfaceIdentifier) error
|
DeleteInterface(ctx context.Context, id domain.InterfaceIdentifier) error
|
||||||
@@ -60,6 +61,19 @@ func (s InterfaceService) GetById(ctx context.Context, id domain.InterfaceIdenti
|
|||||||
return interfaceData, interfacePeers, nil
|
return interfaceData, interfacePeers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s InterfaceService) Prepare(ctx context.Context) (*domain.Interface, error) {
|
||||||
|
if err := domain.ValidateAdminAccessRights(ctx); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
interfaceData, err := s.interfaces.PrepareInterface(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return interfaceData, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s InterfaceService) Create(ctx context.Context, iface *domain.Interface) (*domain.Interface, error) {
|
func (s InterfaceService) Create(ctx context.Context, iface *domain.Interface) (*domain.Interface, error) {
|
||||||
if err := domain.ValidateAdminAccessRights(ctx); err != nil {
|
if err := domain.ValidateAdminAccessRights(ctx); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@@ -13,6 +13,7 @@ type PeerServicePeerManagerRepo interface {
|
|||||||
GetPeer(ctx context.Context, id domain.PeerIdentifier) (*domain.Peer, error)
|
GetPeer(ctx context.Context, id domain.PeerIdentifier) (*domain.Peer, error)
|
||||||
GetUserPeers(ctx context.Context, id domain.UserIdentifier) ([]domain.Peer, error)
|
GetUserPeers(ctx context.Context, id domain.UserIdentifier) ([]domain.Peer, error)
|
||||||
GetInterfaceAndPeers(ctx context.Context, id domain.InterfaceIdentifier) (*domain.Interface, []domain.Peer, error)
|
GetInterfaceAndPeers(ctx context.Context, id domain.InterfaceIdentifier) (*domain.Interface, []domain.Peer, error)
|
||||||
|
PreparePeer(ctx context.Context, id domain.InterfaceIdentifier) (*domain.Peer, error)
|
||||||
CreatePeer(ctx context.Context, peer *domain.Peer) (*domain.Peer, error)
|
CreatePeer(ctx context.Context, peer *domain.Peer) (*domain.Peer, error)
|
||||||
UpdatePeer(ctx context.Context, peer *domain.Peer) (*domain.Peer, error)
|
UpdatePeer(ctx context.Context, peer *domain.Peer) (*domain.Peer, error)
|
||||||
DeletePeer(ctx context.Context, id domain.PeerIdentifier) error
|
DeletePeer(ctx context.Context, id domain.PeerIdentifier) error
|
||||||
@@ -95,6 +96,19 @@ func (s PeerService) GetById(ctx context.Context, id domain.PeerIdentifier) (*do
|
|||||||
return peer, nil
|
return peer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s PeerService) Prepare(ctx context.Context, id domain.InterfaceIdentifier) (*domain.Peer, error) {
|
||||||
|
if err := domain.ValidateAdminAccessRights(ctx); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
peer, err := s.peers.PreparePeer(ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return peer, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s PeerService) Create(ctx context.Context, peer *domain.Peer) (*domain.Peer, error) {
|
func (s PeerService) Create(ctx context.Context, peer *domain.Peer) (*domain.Peer, error) {
|
||||||
if err := domain.ValidateAdminAccessRights(ctx); err != nil {
|
if err := domain.ValidateAdminAccessRights(ctx); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@@ -15,6 +15,7 @@ import (
|
|||||||
type InterfaceEndpointInterfaceService interface {
|
type InterfaceEndpointInterfaceService interface {
|
||||||
GetAll(context.Context) ([]domain.Interface, [][]domain.Peer, error)
|
GetAll(context.Context) ([]domain.Interface, [][]domain.Peer, error)
|
||||||
GetById(context.Context, domain.InterfaceIdentifier) (*domain.Interface, []domain.Peer, error)
|
GetById(context.Context, domain.InterfaceIdentifier) (*domain.Interface, []domain.Peer, error)
|
||||||
|
Prepare(context.Context) (*domain.Interface, error)
|
||||||
Create(context.Context, *domain.Interface) (*domain.Interface, error)
|
Create(context.Context, *domain.Interface) (*domain.Interface, error)
|
||||||
Update(context.Context, domain.InterfaceIdentifier, *domain.Interface) (*domain.Interface, []domain.Peer, error)
|
Update(context.Context, domain.InterfaceIdentifier, *domain.Interface) (*domain.Interface, []domain.Peer, error)
|
||||||
Delete(context.Context, domain.InterfaceIdentifier) error
|
Delete(context.Context, domain.InterfaceIdentifier) error
|
||||||
@@ -49,6 +50,7 @@ func (e InterfaceEndpoint) RegisterRoutes(g *routegroup.Bundle) {
|
|||||||
apiGroup.HandleFunc("GET /all", e.handleAllGet())
|
apiGroup.HandleFunc("GET /all", e.handleAllGet())
|
||||||
apiGroup.HandleFunc("GET /by-id/{id}", e.handleByIdGet())
|
apiGroup.HandleFunc("GET /by-id/{id}", e.handleByIdGet())
|
||||||
|
|
||||||
|
apiGroup.HandleFunc("GET /prepare", e.handlePrepareGet())
|
||||||
apiGroup.HandleFunc("POST /new", e.handleCreatePost())
|
apiGroup.HandleFunc("POST /new", e.handleCreatePost())
|
||||||
apiGroup.HandleFunc("PUT /by-id/{id}", e.handleUpdatePut())
|
apiGroup.HandleFunc("PUT /by-id/{id}", e.handleUpdatePut())
|
||||||
apiGroup.HandleFunc("DELETE /by-id/{id}", e.handleDelete())
|
apiGroup.HandleFunc("DELETE /by-id/{id}", e.handleDelete())
|
||||||
@@ -112,11 +114,38 @@ func (e InterfaceEndpoint) handleByIdGet() http.HandlerFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handlePrepareGet returns a gorm handler function.
|
||||||
|
//
|
||||||
|
// @ID interfaces_handlePrepareGet
|
||||||
|
// @Tags Interfaces
|
||||||
|
// @Summary Prepare a new interface record.
|
||||||
|
// @Description This endpoint returns a new interface with default values (fresh key pair, valid name, new IP address pool, ...).
|
||||||
|
// @Produce json
|
||||||
|
// @Success 200 {object} models.Interface
|
||||||
|
// @Failure 401 {object} models.Error
|
||||||
|
// @Failure 403 {object} models.Error
|
||||||
|
// @Failure 500 {object} models.Error
|
||||||
|
// @Router /interface/prepare [get]
|
||||||
|
// @Security BasicAuth
|
||||||
|
func (e InterfaceEndpoint) handlePrepareGet() http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
iface, err := e.interfaces.Prepare(r.Context())
|
||||||
|
if err != nil {
|
||||||
|
status, model := ParseServiceError(err)
|
||||||
|
respond.JSON(w, status, model)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
respond.JSON(w, http.StatusOK, models.NewInterface(iface, nil))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// handleCreatePost returns a gorm handler function.
|
// handleCreatePost returns a gorm handler function.
|
||||||
//
|
//
|
||||||
// @ID interfaces_handleCreatePost
|
// @ID interfaces_handleCreatePost
|
||||||
// @Tags Interfaces
|
// @Tags Interfaces
|
||||||
// @Summary Create a new interface record.
|
// @Summary Create a new interface record.
|
||||||
|
// @Description This endpoint creates a new interface with the provided data. All required fields must be filled (e.g. name, private key, public key, ...).
|
||||||
// @Param request body models.Interface true "The interface data."
|
// @Param request body models.Interface true "The interface data."
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} models.Interface
|
// @Success 200 {object} models.Interface
|
||||||
@@ -155,6 +184,7 @@ func (e InterfaceEndpoint) handleCreatePost() http.HandlerFunc {
|
|||||||
// @ID interfaces_handleUpdatePut
|
// @ID interfaces_handleUpdatePut
|
||||||
// @Tags Interfaces
|
// @Tags Interfaces
|
||||||
// @Summary Update an interface record.
|
// @Summary Update an interface record.
|
||||||
|
// @Description This endpoint updates an existing interface with the provided data. All required fields must be filled (e.g. name, private key, public key, ...).
|
||||||
// @Param id path string true "The interface identifier."
|
// @Param id path string true "The interface identifier."
|
||||||
// @Param request body models.Interface true "The interface data."
|
// @Param request body models.Interface true "The interface data."
|
||||||
// @Produce json
|
// @Produce json
|
||||||
|
@@ -16,6 +16,7 @@ type PeerService interface {
|
|||||||
GetForInterface(context.Context, domain.InterfaceIdentifier) ([]domain.Peer, error)
|
GetForInterface(context.Context, domain.InterfaceIdentifier) ([]domain.Peer, error)
|
||||||
GetForUser(context.Context, domain.UserIdentifier) ([]domain.Peer, error)
|
GetForUser(context.Context, domain.UserIdentifier) ([]domain.Peer, error)
|
||||||
GetById(context.Context, domain.PeerIdentifier) (*domain.Peer, error)
|
GetById(context.Context, domain.PeerIdentifier) (*domain.Peer, error)
|
||||||
|
Prepare(ctx context.Context, id domain.InterfaceIdentifier) (*domain.Peer, error)
|
||||||
Create(context.Context, *domain.Peer) (*domain.Peer, error)
|
Create(context.Context, *domain.Peer) (*domain.Peer, error)
|
||||||
Update(context.Context, domain.PeerIdentifier, *domain.Peer) (*domain.Peer, error)
|
Update(context.Context, domain.PeerIdentifier, *domain.Peer) (*domain.Peer, error)
|
||||||
Delete(context.Context, domain.PeerIdentifier) error
|
Delete(context.Context, domain.PeerIdentifier) error
|
||||||
@@ -51,6 +52,7 @@ func (e PeerEndpoint) RegisterRoutes(g *routegroup.Bundle) {
|
|||||||
apiGroup.HandleFunc("GET /by-user/{id}", e.handleAllForUserGet())
|
apiGroup.HandleFunc("GET /by-user/{id}", e.handleAllForUserGet())
|
||||||
apiGroup.HandleFunc("GET /by-id/{id}", e.handleByIdGet())
|
apiGroup.HandleFunc("GET /by-id/{id}", e.handleByIdGet())
|
||||||
|
|
||||||
|
apiGroup.With(e.authenticator.LoggedIn(ScopeAdmin)).HandleFunc("GET /prepare/{id}", e.handlePrepareGet())
|
||||||
apiGroup.With(e.authenticator.LoggedIn(ScopeAdmin)).HandleFunc("POST /new", e.handleCreatePost())
|
apiGroup.With(e.authenticator.LoggedIn(ScopeAdmin)).HandleFunc("POST /new", e.handleCreatePost())
|
||||||
apiGroup.With(e.authenticator.LoggedIn(ScopeAdmin)).HandleFunc("PUT /by-id/{id}", e.handleUpdatePut())
|
apiGroup.With(e.authenticator.LoggedIn(ScopeAdmin)).HandleFunc("PUT /by-id/{id}", e.handleUpdatePut())
|
||||||
apiGroup.With(e.authenticator.LoggedIn(ScopeAdmin)).HandleFunc("DELETE /by-id/{id}", e.handleDelete())
|
apiGroup.With(e.authenticator.LoggedIn(ScopeAdmin)).HandleFunc("DELETE /by-id/{id}", e.handleDelete())
|
||||||
@@ -156,12 +158,48 @@ func (e PeerEndpoint) handleByIdGet() http.HandlerFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handlePrepareGet returns a gorm handler function.
|
||||||
|
//
|
||||||
|
// @ID peers_handlePrepareGet
|
||||||
|
// @Tags Peers
|
||||||
|
// @Summary Prepare a new peer record for the given WireGuard interface.
|
||||||
|
// @Description This endpoint is used to prepare a new peer record. The returned data contains a fresh key pair and valid ip address.
|
||||||
|
// @Param id path string true "The interface identifier."
|
||||||
|
// @Produce json
|
||||||
|
// @Success 200 {object} models.Peer
|
||||||
|
// @Failure 400 {object} models.Error
|
||||||
|
// @Failure 401 {object} models.Error
|
||||||
|
// @Failure 403 {object} models.Error
|
||||||
|
// @Failure 404 {object} models.Error
|
||||||
|
// @Failure 500 {object} models.Error
|
||||||
|
// @Router /peer/prepare/{id} [get]
|
||||||
|
// @Security BasicAuth
|
||||||
|
func (e PeerEndpoint) handlePrepareGet() http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
id := request.Path(r, "id")
|
||||||
|
if id == "" {
|
||||||
|
respond.JSON(w, http.StatusBadRequest,
|
||||||
|
models.Error{Code: http.StatusBadRequest, Message: "missing interface id"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
peer, err := e.peers.Prepare(r.Context(), domain.InterfaceIdentifier(id))
|
||||||
|
if err != nil {
|
||||||
|
status, model := ParseServiceError(err)
|
||||||
|
respond.JSON(w, status, model)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
respond.JSON(w, http.StatusOK, models.NewPeer(peer))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// handleCreatePost returns a gorm handler function.
|
// handleCreatePost returns a gorm handler function.
|
||||||
//
|
//
|
||||||
// @ID peers_handleCreatePost
|
// @ID peers_handleCreatePost
|
||||||
// @Tags Peers
|
// @Tags Peers
|
||||||
// @Summary Create a new peer record.
|
// @Summary Create a new peer record.
|
||||||
// @Description Only admins can create new records.
|
// @Description Only admins can create new records. The peer record must contain all required fields (e.g., public key, allowed IPs).
|
||||||
// @Param request body models.Peer true "The peer data."
|
// @Param request body models.Peer true "The peer data."
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} models.Peer
|
// @Success 200 {object} models.Peer
|
||||||
@@ -200,7 +238,7 @@ func (e PeerEndpoint) handleCreatePost() http.HandlerFunc {
|
|||||||
// @ID peers_handleUpdatePut
|
// @ID peers_handleUpdatePut
|
||||||
// @Tags Peers
|
// @Tags Peers
|
||||||
// @Summary Update a peer record.
|
// @Summary Update a peer record.
|
||||||
// @Description Only admins can update existing records.
|
// @Description Only admins can update existing records. The peer record must contain all required fields (e.g., public key, allowed IPs).
|
||||||
// @Param id path string true "The peer identifier."
|
// @Param id path string true "The peer identifier."
|
||||||
// @Param request body models.Peer true "The peer data."
|
// @Param request body models.Peer true "The peer data."
|
||||||
// @Produce json
|
// @Produce json
|
||||||
|
@@ -63,6 +63,8 @@ type AuthenticatorOauth interface {
|
|||||||
ParseUserInfo(raw map[string]any) (*domain.AuthenticatorUserInfo, error)
|
ParseUserInfo(raw map[string]any) (*domain.AuthenticatorUserInfo, error)
|
||||||
// RegistrationEnabled returns whether registration is enabled for the OAuth authenticator.
|
// RegistrationEnabled returns whether registration is enabled for the OAuth authenticator.
|
||||||
RegistrationEnabled() bool
|
RegistrationEnabled() bool
|
||||||
|
// GetAllowedDomains returns the list of whitelisted domains
|
||||||
|
GetAllowedDomains() []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// AuthenticatorLdap is the interface for all LDAP authenticators.
|
// AuthenticatorLdap is the interface for all LDAP authenticators.
|
||||||
@@ -392,6 +394,23 @@ func (a *Authenticator) randString(nByte int) (string, error) {
|
|||||||
return base64.RawURLEncoding.EncodeToString(b), nil
|
return base64.RawURLEncoding.EncodeToString(b), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isDomainAllowed(email string, allowedDomains []string) bool {
|
||||||
|
if len(allowedDomains) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
parts := strings.Split(email, "@")
|
||||||
|
if len(parts) != 2 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
domain := strings.ToLower(parts[1])
|
||||||
|
for _, allowed := range allowedDomains {
|
||||||
|
if domain == strings.ToLower(allowed) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// OauthLoginStep2 finishes the oauth authentication flow by exchanging the code for an access token and
|
// OauthLoginStep2 finishes the oauth authentication flow by exchanging the code for an access token and
|
||||||
// fetching the user information.
|
// fetching the user information.
|
||||||
func (a *Authenticator) OauthLoginStep2(ctx context.Context, providerId, nonce, code string) (*domain.User, error) {
|
func (a *Authenticator) OauthLoginStep2(ctx context.Context, providerId, nonce, code string) (*domain.User, error) {
|
||||||
@@ -431,6 +450,10 @@ func (a *Authenticator) OauthLoginStep2(ctx context.Context, providerId, nonce,
|
|||||||
return nil, fmt.Errorf("unable to process user information: %w", err)
|
return nil, fmt.Errorf("unable to process user information: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !isDomainAllowed(userInfo.Email, oauthProvider.GetAllowedDomains()) {
|
||||||
|
return nil, fmt.Errorf("user is not in allowed domains: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
if user.IsLocked() || user.IsDisabled() {
|
if user.IsLocked() || user.IsDisabled() {
|
||||||
a.bus.Publish(app.TopicAuditLoginFailed, domain.AuditEventWrapper[audit.AuthEvent]{
|
a.bus.Publish(app.TopicAuditLoginFailed, domain.AuditEventWrapper[audit.AuthEvent]{
|
||||||
Ctx: ctx,
|
Ctx: ctx,
|
||||||
|
@@ -27,6 +27,7 @@ type PlainOauthAuthenticator struct {
|
|||||||
userAdminMapping *config.OauthAdminMapping
|
userAdminMapping *config.OauthAdminMapping
|
||||||
registrationEnabled bool
|
registrationEnabled bool
|
||||||
userInfoLogging bool
|
userInfoLogging bool
|
||||||
|
allowedDomains []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPlainOauthAuthenticator(
|
func newPlainOauthAuthenticator(
|
||||||
@@ -56,6 +57,7 @@ func newPlainOauthAuthenticator(
|
|||||||
provider.userAdminMapping = &cfg.AdminMapping
|
provider.userAdminMapping = &cfg.AdminMapping
|
||||||
provider.registrationEnabled = cfg.RegistrationEnabled
|
provider.registrationEnabled = cfg.RegistrationEnabled
|
||||||
provider.userInfoLogging = cfg.LogUserInfo
|
provider.userInfoLogging = cfg.LogUserInfo
|
||||||
|
provider.allowedDomains = cfg.AllowedDomains
|
||||||
|
|
||||||
return provider, nil
|
return provider, nil
|
||||||
}
|
}
|
||||||
@@ -65,6 +67,10 @@ func (p PlainOauthAuthenticator) GetName() string {
|
|||||||
return p.name
|
return p.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p PlainOauthAuthenticator) GetAllowedDomains() []string {
|
||||||
|
return p.allowedDomains
|
||||||
|
}
|
||||||
|
|
||||||
// RegistrationEnabled returns whether registration is enabled for the OAuth authenticator.
|
// RegistrationEnabled returns whether registration is enabled for the OAuth authenticator.
|
||||||
func (p PlainOauthAuthenticator) RegistrationEnabled() bool {
|
func (p PlainOauthAuthenticator) RegistrationEnabled() bool {
|
||||||
return p.registrationEnabled
|
return p.registrationEnabled
|
||||||
|
@@ -24,6 +24,7 @@ type OidcAuthenticator struct {
|
|||||||
userAdminMapping *config.OauthAdminMapping
|
userAdminMapping *config.OauthAdminMapping
|
||||||
registrationEnabled bool
|
registrationEnabled bool
|
||||||
userInfoLogging bool
|
userInfoLogging bool
|
||||||
|
allowedDomains []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newOidcAuthenticator(
|
func newOidcAuthenticator(
|
||||||
@@ -57,6 +58,7 @@ func newOidcAuthenticator(
|
|||||||
provider.userAdminMapping = &cfg.AdminMapping
|
provider.userAdminMapping = &cfg.AdminMapping
|
||||||
provider.registrationEnabled = cfg.RegistrationEnabled
|
provider.registrationEnabled = cfg.RegistrationEnabled
|
||||||
provider.userInfoLogging = cfg.LogUserInfo
|
provider.userInfoLogging = cfg.LogUserInfo
|
||||||
|
provider.allowedDomains = cfg.AllowedDomains
|
||||||
|
|
||||||
return provider, nil
|
return provider, nil
|
||||||
}
|
}
|
||||||
@@ -66,6 +68,10 @@ func (o OidcAuthenticator) GetName() string {
|
|||||||
return o.name
|
return o.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o OidcAuthenticator) GetAllowedDomains() []string {
|
||||||
|
return o.allowedDomains
|
||||||
|
}
|
||||||
|
|
||||||
// RegistrationEnabled returns whether registration is enabled for this authenticator.
|
// RegistrationEnabled returns whether registration is enabled for this authenticator.
|
||||||
func (o OidcAuthenticator) RegistrationEnabled() bool {
|
func (o OidcAuthenticator) RegistrationEnabled() bool {
|
||||||
return o.registrationEnabled
|
return o.registrationEnabled
|
||||||
|
@@ -88,15 +88,14 @@ func (s GormEncryptedStringSerializer) Value(
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if !s.useEncryption {
|
|
||||||
return fieldValue, nil // keep the original value
|
|
||||||
}
|
|
||||||
|
|
||||||
switch v := fieldValue.(type) {
|
switch v := fieldValue.(type) {
|
||||||
case string:
|
case string:
|
||||||
if v == "" {
|
if v == "" {
|
||||||
return "", nil // empty string, no need to encrypt
|
return "", nil // empty string, no need to encrypt
|
||||||
}
|
}
|
||||||
|
if !s.useEncryption {
|
||||||
|
return v, nil // keep the original value
|
||||||
|
}
|
||||||
encryptedString, err := EncryptAES256(v, s.keyPhrase)
|
encryptedString, err := EncryptAES256(v, s.keyPhrase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -106,6 +105,9 @@ func (s GormEncryptedStringSerializer) Value(
|
|||||||
if v == "" {
|
if v == "" {
|
||||||
return "", nil // empty string, no need to encrypt
|
return "", nil // empty string, no need to encrypt
|
||||||
}
|
}
|
||||||
|
if !s.useEncryption {
|
||||||
|
return string(v), nil // keep the original value
|
||||||
|
}
|
||||||
encryptedString, err := EncryptAES256(string(v), s.keyPhrase)
|
encryptedString, err := EncryptAES256(string(v), s.keyPhrase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@@ -188,6 +188,9 @@ type OpenIDConnectProvider struct {
|
|||||||
// ExtraScopes specifies optional requested permissions.
|
// ExtraScopes specifies optional requested permissions.
|
||||||
ExtraScopes []string `yaml:"extra_scopes"`
|
ExtraScopes []string `yaml:"extra_scopes"`
|
||||||
|
|
||||||
|
// AllowedDomains defines the list of allowed domains
|
||||||
|
AllowedDomains []string `yaml:"allowed_domains"`
|
||||||
|
|
||||||
// FieldMap is used to map the names of the user-info endpoint fields to wg-portal fields
|
// FieldMap is used to map the names of the user-info endpoint fields to wg-portal fields
|
||||||
FieldMap OauthFields `yaml:"field_map"`
|
FieldMap OauthFields `yaml:"field_map"`
|
||||||
|
|
||||||
@@ -226,6 +229,9 @@ type OAuthProvider struct {
|
|||||||
// Scope specifies optional requested permissions.
|
// Scope specifies optional requested permissions.
|
||||||
Scopes []string `yaml:"scopes"`
|
Scopes []string `yaml:"scopes"`
|
||||||
|
|
||||||
|
// AllowedDomains defines the list of allowed domains
|
||||||
|
AllowedDomains []string `yaml:"allowed_domains"`
|
||||||
|
|
||||||
// FieldMap is used to map the names of the user-info endpoint fields to wg-portal fields
|
// FieldMap is used to map the names of the user-info endpoint fields to wg-portal fields
|
||||||
FieldMap OauthFields `yaml:"field_map"`
|
FieldMap OauthFields `yaml:"field_map"`
|
||||||
|
|
||||||
|
@@ -30,6 +30,15 @@ plugins:
|
|||||||
- minify:
|
- minify:
|
||||||
minify_html: true
|
minify_html: true
|
||||||
- swagger-ui-tag
|
- swagger-ui-tag
|
||||||
|
- mike:
|
||||||
|
# These fields are all optional; the defaults are as below...
|
||||||
|
alias_type: symlink
|
||||||
|
redirect_template: null
|
||||||
|
deploy_prefix: ''
|
||||||
|
canonical_version: null
|
||||||
|
version_selector: true
|
||||||
|
css_dir: css
|
||||||
|
javascript_dir: js
|
||||||
|
|
||||||
extra:
|
extra:
|
||||||
version:
|
version:
|
||||||
|
Reference in New Issue
Block a user