Compare commits

..

21 Commits

Author SHA1 Message Date
Bernd Storath a0b4192cbd Bump version to 15.2.1 2026-01-14 08:51:01 +01:00
Bernd Storath 32a055093a exclude i18n from setup middleware 2026-01-13 13:15:46 +01:00
Bernd Storath 51558c7027 refactor: session handling (#2398)
* refactor session handling

* simplify
2026-01-13 10:11:13 +01:00
binnichtaktiv b85286f0ab Lang(de): Improve and add missing translations (#2393)
* add missing german translations

* fix typos and improve existing translations

* fix punctuation

* fix last overlooked typos
2026-01-13 08:21:08 +01:00
Bernd Storath 48f3fbd715 always generate awg h1-h5 2026-01-13 08:07:13 +01:00
Bernd Storath 458f66818a fix search magnifying icon 2026-01-12 12:04:50 +01:00
Bernd Storath 7964dc7993 Bump version to 15.2.0 2026-01-12 08:28:23 +01:00
RaffaelHold 0ac5d7d461 feat(docs): Extend docs for routed setup with nftables (#2380)
* Extend docs for routed setup with nftables

When using nftables in a routed setup different up and down hooks need to be used. 
To limit interaction with docker managed chains a custom WG_EASY chain is added as a jump target.
Since nft only supports deletion via handles awk is needed to get the handle of the jump rule for deletion

* Remove link to podman-nft

* Fix formatting according to prettier rules

* Add additional whitespace
2026-01-12 08:21:18 +01:00
Bernd Storath 826914a4f3 update packages 2026-01-12 08:19:01 +01:00
Bernd Storath 261da431e7 Fix: reset onetimelink expiration instead of failing (#2370)
* update expiresAt instead of failing

* add changelog
2025-12-29 19:12:53 +01:00
Bernd Storath 94b33abf5e Remove armv7 support (#2369)
remove armv7 support
2025-12-29 18:54:47 +01:00
Bernd Storath 8325056ccc update lockfile 2025-12-29 18:47:48 +01:00
Bernd Storath 81a1b2c907 update packages 2025-12-29 18:36:51 +01:00
dependabot[bot] fc8f89fb83 build(deps): bump actions/download-artifact from 6 to 7 (#2343)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 6 to 7.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-18 07:58:23 +01:00
dependabot[bot] d846c7745f build(deps): bump actions/upload-artifact from 5 to 6 (#2344)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5 to 6.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-18 07:58:12 +01:00
Bernd Storath 61c6fd6c02 update packages 2025-12-15 08:03:25 +01:00
David DIVERRES abe5708058 Update fr.json (#2326)
Update fr.json - Add missing translations and improve existing ones

- Add missing keys: client.delete, client.search, client.config, client.viewConfig
- Add complete copy section (4 keys)
- Add complete awg section (27 keys for AmneziaWG parameters)
- Fix terminology: "double facteur" → "deux facteurs" (standard French)
- Fix zod.generic.validBoolean translation
- Fix zod.generic.stringMin capitalization and wording
- Translate zod.client.id to French
- Improve admin.general route descriptions
2025-12-08 08:51:38 +01:00
Bernd Storath 626339bddb update packages 2025-12-08 08:30:53 +01:00
Danya 381ae23c07 Update ru (#2324)
* Update ru.json

Full revision of the Russian localization for the AWG configuration block, including terminology corrections, improved consistency, and clarified parameter descriptions.

* Update ru.json

* fix formatting

---------

Co-authored-by: Bernd Storath <999999bst@gmail.com>
2025-12-05 15:59:12 +01:00
Nikolas 52382d1d7a Update uk.json (#2323) 2025-12-05 07:35:15 +01:00
Mike 68e5216d4b Update ru.json (#2319)
* Update ru.json

* format

---------

Co-authored-by: Bernd Storath <999999bst@gmail.com>
2025-12-02 12:26:04 +01:00
34 changed files with 1977 additions and 1646 deletions
+4 -4
View File
@@ -18,8 +18,8 @@ jobs:
os: ubuntu-latest os: ubuntu-latest
- platform: linux/arm64 - platform: linux/arm64
os: ubuntu-24.04-arm os: ubuntu-24.04-arm
- platform: linux/arm/v7 # - platform: linux/arm/v7
os: ubuntu-24.04-arm # os: ubuntu-24.04-arm
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v6
@@ -69,7 +69,7 @@ jobs:
touch "${{ runner.temp }}/digests/${digest#sha256:}" touch "${{ runner.temp }}/digests/${digest#sha256:}"
- name: Upload digest - name: Upload digest
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@v6
with: with:
name: digests-${{ env.PLATFORM_PAIR }} name: digests-${{ env.PLATFORM_PAIR }}
path: ${{ runner.temp }}/digests/* path: ${{ runner.temp }}/digests/*
@@ -85,7 +85,7 @@ jobs:
needs: docker-build needs: docker-build
steps: steps:
- name: Download digests - name: Download digests
uses: actions/download-artifact@v6 uses: actions/download-artifact@v7
with: with:
path: ${{ runner.temp }}/digests path: ${{ runner.temp }}/digests
pattern: digests-* pattern: digests-*
+4 -4
View File
@@ -25,8 +25,8 @@ jobs:
os: ubuntu-latest os: ubuntu-latest
- platform: linux/arm64 - platform: linux/arm64
os: ubuntu-24.04-arm os: ubuntu-24.04-arm
- platform: linux/arm/v7 # - platform: linux/arm/v7
os: ubuntu-24.04-arm # os: ubuntu-24.04-arm
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v6
with: with:
@@ -78,7 +78,7 @@ jobs:
touch "${{ runner.temp }}/digests/${digest#sha256:}" touch "${{ runner.temp }}/digests/${digest#sha256:}"
- name: Upload digest - name: Upload digest
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@v6
with: with:
name: digests-${{ env.PLATFORM_PAIR }} name: digests-${{ env.PLATFORM_PAIR }}
path: ${{ runner.temp }}/digests/* path: ${{ runner.temp }}/digests/*
@@ -94,7 +94,7 @@ jobs:
needs: docker-build needs: docker-build
steps: steps:
- name: Download digests - name: Download digests
uses: actions/download-artifact@v6 uses: actions/download-artifact@v7
with: with:
path: ${{ runner.temp }}/digests path: ${{ runner.temp }}/digests
pattern: digests-* pattern: digests-*
+2 -2
View File
@@ -21,8 +21,8 @@ jobs:
os: ubuntu-latest os: ubuntu-latest
- platform: linux/arm64 - platform: linux/arm64
os: ubuntu-24.04-arm os: ubuntu-24.04-arm
- platform: linux/arm/v7 # - platform: linux/arm/v7
os: ubuntu-24.04-arm # os: ubuntu-24.04-arm
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v6
+4 -4
View File
@@ -26,8 +26,8 @@ jobs:
os: ubuntu-latest os: ubuntu-latest
- platform: linux/arm64 - platform: linux/arm64
os: ubuntu-24.04-arm os: ubuntu-24.04-arm
- platform: linux/arm/v7 # - platform: linux/arm/v7
os: ubuntu-24.04-arm # os: ubuntu-24.04-arm
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v6
@@ -77,7 +77,7 @@ jobs:
touch "${{ runner.temp }}/digests/${digest#sha256:}" touch "${{ runner.temp }}/digests/${digest#sha256:}"
- name: Upload digest - name: Upload digest
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@v6
with: with:
name: digests-${{ env.PLATFORM_PAIR }} name: digests-${{ env.PLATFORM_PAIR }}
path: ${{ runner.temp }}/digests/* path: ${{ runner.temp }}/digests/*
@@ -95,7 +95,7 @@ jobs:
needs: docker-build needs: docker-build
steps: steps:
- name: Download digests - name: Download digests
uses: actions/download-artifact@v6 uses: actions/download-artifact@v7
with: with:
path: ${{ runner.temp }}/digests path: ${{ runner.temp }}/digests
pattern: digests-* pattern: digests-*
+1 -1
View File
@@ -3,7 +3,7 @@
"aaron-bond.better-comments", "aaron-bond.better-comments",
"dbaeumer.vscode-eslint", "dbaeumer.vscode-eslint",
"antfu.goto-alias", "antfu.goto-alias",
"esbenp.prettier-vscode", "prettier.prettier-vscode",
"yoavbls.pretty-ts-errors", "yoavbls.pretty-ts-errors",
"bradlc.vscode-tailwindcss", "bradlc.vscode-tailwindcss",
"vue.volar", "vue.volar",
+5 -5
View File
@@ -1,22 +1,22 @@
{ {
"editor.tabSize": 2, "editor.tabSize": 2,
"editor.useTabStops": false, "editor.useTabStops": false,
"editor.defaultFormatter": "esbenp.prettier-vscode", "editor.defaultFormatter": "prettier.prettier-vscode",
"editor.formatOnSave": true, "editor.formatOnSave": true,
"editor.codeActionsOnSave": { "editor.codeActionsOnSave": {
"source.fixAll.eslint": "always" "source.fixAll.eslint": "always"
}, },
"[vue]": { "[vue]": {
"editor.defaultFormatter": "esbenp.prettier-vscode" "editor.defaultFormatter": "prettier.prettier-vscode"
}, },
"[typescript]": { "[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode" "editor.defaultFormatter": "prettier.prettier-vscode"
}, },
"[json]": { "[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode" "editor.defaultFormatter": "prettier.prettier-vscode"
}, },
"[markdown]": { "[markdown]": {
"editor.defaultFormatter": "esbenp.prettier-vscode", "editor.defaultFormatter": "prettier.prettier-vscode",
"editor.tabSize": 4, "editor.tabSize": 4,
"editor.useTabStops": false "editor.useTabStops": false
}, },
+17 -5
View File
@@ -7,7 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
## Added ## [15.2.1] - 2026-01-14
### Fixed
- Icon in Searchbar (https://github.com/wg-easy/wg-easy/commit/458f66818a400f181e2c6326ede077c8793d71f2)
- Interface save not working (https://github.com/wg-easy/wg-easy/commit/48f3fbd715a889e2425702a8a46332f2752aef91)
- Error Messages in Setup (https://github.com/wg-easy/wg-easy/commit/32a055093a76342c40858d8dcf563b0700a8bd48)
## [15.2.0] - 2026-01-12
### Added
- AmneziaWG integration (https://github.com/wg-easy/wg-easy/pull/2102, https://github.com/wg-easy/wg-easy/pull/2226) - AmneziaWG integration (https://github.com/wg-easy/wg-easy/pull/2102, https://github.com/wg-easy/wg-easy/pull/2226)
- Search / filter box (https://github.com/wg-easy/wg-easy/pull/2170) - Search / filter box (https://github.com/wg-easy/wg-easy/pull/2170)
@@ -15,13 +25,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Show client endpoint (https://github.com/wg-easy/wg-easy/pull/2058) - Show client endpoint (https://github.com/wg-easy/wg-easy/pull/2058)
- Add option to view and copy config (https://github.com/wg-easy/wg-easy/pull/2289) - Add option to view and copy config (https://github.com/wg-easy/wg-easy/pull/2289)
## Fixed ### Fixed
- Fix download as conf.txt (https://github.com/wg-easy/wg-easy/pull/2269) - Fix download as conf.txt (https://github.com/wg-easy/wg-easy/pull/2269)
- Clean filename for OTL download (https://github.com/wg-easy/wg-easy/pull/2253) - Clean filename for OTL download (https://github.com/wg-easy/wg-easy/pull/2253)
- Text color in admin menu in light mode (https://github.com/wg-easy/wg-easy/pull/2307) - Text color in admin menu in light mode (https://github.com/wg-easy/wg-easy/pull/2307)
## Changed ### Changed
- Allow lower MTU (https://github.com/wg-easy/wg-easy/pull/2228) - Allow lower MTU (https://github.com/wg-easy/wg-easy/pull/2228)
- Use /32 and /128 for client Cidr (https://github.com/wg-easy/wg-easy/pull/2217) - Use /32 and /128 for client Cidr (https://github.com/wg-easy/wg-easy/pull/2217)
@@ -30,11 +40,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Allow empty DNS (https://github.com/wg-easy/wg-easy/pull/2052, https://github.com/wg-easy/wg-easy/pull/2057) - Allow empty DNS (https://github.com/wg-easy/wg-easy/pull/2052, https://github.com/wg-easy/wg-easy/pull/2057)
- Don't include keys in API responses (https://github.com/wg-easy/wg-easy/pull/2015) - Don't include keys in API responses (https://github.com/wg-easy/wg-easy/pull/2015)
- Try all QR ecc levels (https://github.com/wg-easy/wg-easy/pull/2288) - Try all QR ecc levels (https://github.com/wg-easy/wg-easy/pull/2288)
- Update OneTimeLink expiry on reuse (https://github.com/wg-easy/wg-easy/pull/2370)
- Removed ARMv7 support (https://github.com/wg-easy/wg-easy/pull/2369)
## Docs ### Docs
- Add AdGuard Home (https://github.com/wg-easy/wg-easy/pull/2175) - Add AdGuard Home (https://github.com/wg-easy/wg-easy/pull/2175)
- Add Routed (No NAT) docs (https://github.com/wg-easy/wg-easy/pull/2181) - Add Routed (No NAT) docs (https://github.com/wg-easy/wg-easy/pull/2181, https://github.com/wg-easy/wg-easy/pull/2380)
- Add AmneziaWG docs (https://github.com/wg-easy/wg-easy/pull/2108, https://github.com/wg-easy/wg-easy/pull/2292) - Add AmneziaWG docs (https://github.com/wg-easy/wg-easy/pull/2108, https://github.com/wg-easy/wg-easy/pull/2292)
## [15.1.0] - 2025-07-01 ## [15.1.0] - 2025-07-01
@@ -7,7 +7,7 @@ This guide will help you migrate from `v14` to version `v15` of `wg-easy`.
## Changes ## Changes
- This is a complete rewrite of the `wg-easy` project, therefore the configuration files and the way you interact with the project have changed. - This is a complete rewrite of the `wg-easy` project, therefore the configuration files and the way you interact with the project have changed.
- If you use armv6, you unfortunately won't be able to migrate to `v15`. - If you use armv6 or armv7, you unfortunately won't be able to migrate to `v15`.
- If you are connecting to the Web UI via HTTP, you need to set the `INSECURE` environment variable to `true` in the new container. - If you are connecting to the Web UI via HTTP, you need to set the `INSECURE` environment variable to `true` in the new container.
## Migration ## Migration
@@ -8,7 +8,7 @@ title: Basic Installation
1. You need to have a host that you can manage 1. You need to have a host that you can manage
2. You need to have a domain name or a public IP address 2. You need to have a domain name or a public IP address
3. You need a supported architecture (x86_64, arm64, armv7) 3. You need a supported architecture (x86_64, arm64)
4. You need curl installed on your host 4. You need curl installed on your host
## Install Docker ## Install Docker
+16
View File
@@ -93,3 +93,19 @@ PostDown
```shell ```shell
iptables -D INPUT -p udp -m udp --dport {{port}} -j ACCEPT; iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; ip6tables -D INPUT -p udp -m udp --dport {{port}} -j ACCEPT; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -D FORWARD -o wg0 -j ACCEPT iptables -D INPUT -p udp -m udp --dport {{port}} -j ACCEPT; iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; ip6tables -D INPUT -p udp -m udp --dport {{port}} -j ACCEPT; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -D FORWARD -o wg0 -j ACCEPT
``` ```
/// warning | Important: When using nftables use the following hooks instead.
PostUp
```shell
nft add chain ip filter WG_EASY; nft add rule ip filter DOCKER-USER jump WG_EASY; nft add rule ip filter WG_EASY iifname {{device}} accept; nft add rule ip filter WG_EASY oifname {{device}} accept; nft add chain ip6 filter WG_EASY; nft add rule ip6 filter DOCKER-USER jump WG_EASY; nft add rule ip6 filter WG_EASY iifname {{device}} accept; nft add rule ip6 filter WG_EASY oifname {{device}} accept;
```
PostDown
```shell
nft delete rule ip filter DOCKER-USER handle $(nft -a list chain ip filter DOCKER-USER | awk '/jump WG_EASY/ {print $NF}'); nft flush chain ip filter WG_EASY; nft delete chain ip filter WG_EASY; nft delete rule ip6 filter DOCKER-USER handle $(nft -a list chain ip6 filter DOCKER-USER | awk '/jump WG_EASY/ {print $NF}'); nft flush chain ip6 filter WG_EASY; nft delete chain ip6 filter WG_EASY
```
///
+1 -1
View File
@@ -12,7 +12,7 @@ Before you can get started with deploying your own VPN, there are some requireme
1. You need to have a host that you can manage 1. You need to have a host that you can manage
2. You need to have a domain name or a public IP address 2. You need to have a domain name or a public IP address
3. You need a supported architecture (x86_64, arm64, armv7) 3. You need a supported architecture (x86_64, arm64)
### Host Setup ### Host Setup
+2 -2
View File
@@ -11,7 +11,7 @@
"format:check:docs": "prettier --check docs" "format:check:docs": "prettier --check docs"
}, },
"devDependencies": { "devDependencies": {
"prettier": "^3.7.3" "prettier": "^3.7.4"
}, },
"packageManager": "pnpm@10.24.0" "packageManager": "pnpm@10.28.0"
} }
+5 -5
View File
@@ -9,16 +9,16 @@ importers:
.: .:
devDependencies: devDependencies:
prettier: prettier:
specifier: ^3.7.3 specifier: ^3.7.4
version: 3.7.3 version: 3.7.4
packages: packages:
prettier@3.7.3: prettier@3.7.4:
resolution: {integrity: sha512-QgODejq9K3OzoBbuyobZlUhznP5SKwPqp+6Q6xw6o8gnhr4O85L2U915iM2IDcfF2NPXVaM9zlo9tdwipnYwzg==} resolution: {integrity: sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==}
engines: {node: '>=14'} engines: {node: '>=14'}
hasBin: true hasBin: true
snapshots: snapshots:
prettier@3.7.3: {} prettier@3.7.4: {}
+1
View File
@@ -30,6 +30,7 @@ echo "Updated package.json to version $new_version"
echo "----" echo "----"
echo "If you changed the major version, remember to update the docker-compose.yml file and docs (search for: ref: major version)" echo "If you changed the major version, remember to update the docker-compose.yml file and docs (search for: ref: major version)"
echo "Make sure to stage any changes before proceeding (e.g. Changelog updates)."
echo "----" echo "----"
echo "If you did everything press 'y' to commit the changes and create a new tag" echo "If you did everything press 'y' to commit the changes and create a new tag"
+2 -2
View File
@@ -1,14 +1,14 @@
<template> <template>
<div class="relative w-60 md:mr-2"> <div class="relative w-60 md:mr-2">
<div class="relative flex h-full items-center"> <div class="relative flex h-full items-center">
<MagnifyingGlassIcon <IconsMagnifyingGlass
class="absolute left-2.5 h-4 w-4 text-gray-400 dark:text-neutral-500" class="absolute left-2.5 h-4 w-4 text-gray-400 dark:text-neutral-500"
/> />
<input <input
v-model="searchQuery" v-model="searchQuery"
type="text" type="text"
:placeholder="$t('client.search')" :placeholder="$t('client.search')"
class="w-full rounded bg-white py-2 pr-8 text-sm text-gray-900 shadow-sm ring-1 ring-gray-300 transition-all placeholder:text-gray-400 focus:border-transparent focus:outline-none focus:ring-2 focus:ring-red-600 dark:bg-neutral-800 dark:text-white dark:ring-neutral-700 dark:placeholder:text-neutral-500 dark:focus:ring-red-700" class="w-full rounded bg-white px-8 py-2 text-sm text-gray-900 shadow-sm ring-1 ring-gray-300 transition-all placeholder:text-gray-400 focus:border-transparent focus:outline-none focus:ring-2 focus:ring-red-600 dark:bg-neutral-800 dark:text-white dark:ring-neutral-700 dark:placeholder:text-neutral-500 dark:focus:ring-red-700"
@input="updateSearch" @input="updateSearch"
/> />
<button <button
@@ -0,0 +1,7 @@
<template>
<MagnifyingGlassIcon />
</template>
<script lang="ts" setup>
import MagnifyingGlassIcon from '@heroicons/vue/24/outline/esm/MagnifyingGlassIcon';
</script>
+6 -4
View File
@@ -4,25 +4,27 @@ export default defineNuxtRouteMiddleware(async (to) => {
return; return;
} }
const event = useRequestEvent();
const authStore = useAuthStore(); const authStore = useAuthStore();
const userData = await authStore.getSession(); authStore.userData = await authStore.getSession(event);
// skip login if already logged in // skip login if already logged in
if (to.path === '/login') { if (to.path === '/login') {
if (userData?.username) { if (authStore.userData?.username) {
return navigateTo('/', { redirectCode: 302 }); return navigateTo('/', { redirectCode: 302 });
} }
return; return;
} }
// Require auth for every page other than Login // Require auth for every page other than Login
if (!userData?.username) { if (!authStore.userData?.username) {
return navigateTo('/login', { redirectCode: 302 }); return navigateTo('/login', { redirectCode: 302 });
} }
// Check for admin access // Check for admin access
if (to.path.startsWith('/admin')) { if (to.path.startsWith('/admin')) {
if (!hasPermissions(userData, 'admin', 'any')) { if (!hasPermissions(authStore.userData, 'admin', 'any')) {
return abortNavigation('Not allowed to access Admin Panel'); return abortNavigation('Not allowed to access Admin Panel');
} }
} }
-3
View File
@@ -38,9 +38,6 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
const authStore = useAuthStore();
authStore.update();
const { t } = useI18n(); const { t } = useI18n();
const route = useRoute(); const route = useRoute();
-2
View File
@@ -206,9 +206,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
const authStore = useAuthStore();
const globalStore = useGlobalStore(); const globalStore = useGlobalStore();
authStore.update();
const route = useRoute(); const route = useRoute();
const id = route.params.id as string; const id = route.params.id as string;
-3
View File
@@ -29,9 +29,6 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
const authStore = useAuthStore();
authStore.update();
const globalStore = useGlobalStore(); const globalStore = useGlobalStore();
const clientsStore = useClientsStore(); const clientsStore = useClientsStore();
-3
View File
@@ -67,9 +67,6 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
const authStore = useAuthStore();
authStore.update();
const toast = useToast(); const toast = useToast();
const { t } = useI18n(); const { t } = useI18n();
-1
View File
@@ -120,7 +120,6 @@
import { encodeQR } from 'qr'; import { encodeQR } from 'qr';
const authStore = useAuthStore(); const authStore = useAuthStore();
authStore.update();
const name = ref(authStore.userData?.name); const name = ref(authStore.userData?.name);
const email = ref(authStore.userData?.email); const email = ref(authStore.userData?.email);
+14 -7
View File
@@ -1,18 +1,25 @@
export const useAuthStore = defineStore('Auth', () => { import type { H3Event } from 'h3';
const { data: userData, refresh: update } = useFetch('/api/session', { import type { SharedPublicUser } from '~~/shared/utils/permissions';
method: 'get',
});
async function getSession() { export const useAuthStore = defineStore('Auth', () => {
const userData = useState<SharedPublicUser | null>('user-data', () => null);
async function getSession(event?: H3Event) {
const fetch = event?.$fetch || $fetch;
try { try {
const { data } = await useFetch('/api/session', { const data = await fetch('/api/session', {
method: 'get', method: 'get',
}); });
return data.value; return data;
} catch { } catch {
return null; return null;
} }
} }
async function update() {
const data = await getSession();
userData.value = data;
}
return { userData, update, getSession }; return { userData, update, getSession };
}); });
+74 -25
View File
@@ -11,12 +11,12 @@
} }
}, },
"user": { "user": {
"email": "Email" "email": "E-Mail"
}, },
"me": { "me": {
"currentPassword": "Aktuelles Passwort", "currentPassword": "Aktuelles Passwort",
"enable2fa": "Zwei-Faktor-Authentifizierunng aktivieren", "enable2fa": "Zwei-Faktor-Authentifizierung aktivieren",
"enable2faDesc": "Scannen Sie den QR-Code mit ihrer Authentifizierungs-App oder geben Sie den Schlüssel manuell ein.", "enable2faDesc": "Scannen Sie den QR-Code mit Ihrer Authentifizierungs-App oder geben Sie den Schlüssel manuell ein.",
"2faKey": "TOTP-Schlüssel", "2faKey": "TOTP-Schlüssel",
"2faCodeDesc": "Geben Sie den Code aus Ihrer Authentifizierungs-App ein.", "2faCodeDesc": "Geben Sie den Code aus Ihrer Authentifizierungs-App ein.",
"disable2fa": "Zwei-Faktor-Authentifizierung deaktivieren", "disable2fa": "Zwei-Faktor-Authentifizierung deaktivieren",
@@ -45,26 +45,26 @@
}, },
"setup": { "setup": {
"welcome": "Willkommen zur Ersteinrichtung von wg-easy", "welcome": "Willkommen zur Ersteinrichtung von wg-easy",
"welcomeDesc": "Das ist der einfachste Weg, um Wireguard auf jedem Linux-Server zu installieren und zu betreiben.", "welcomeDesc": "Sie haben den einfachsten Weg gefunden, WireGuard auf jedem Linux-Server zu installieren und zu verwalten.",
"existingSetup": "Haben Sie eine bestehende Einrichtung?", "existingSetup": "Haben Sie eine bestehende Einrichtung?",
"createAdminDesc": "Bitte geben Sie zuerst einen Admin-Benutzernamen sowie ein starkes, sicheres Passwort ein. Diese Anmeldedaten benötigen Sie, um sich im Admin-Panel anzumelden.", "createAdminDesc": "Bitte geben Sie zuerst einen Admin-Benutzernamen sowie ein starkes, sicheres Passwort ein. Diese Anmeldedaten benötigen Sie, um sich in der Admin-Konsole anzumelden.",
"setupConfigDesc": "Bitte geben Sie die Host- und Portinformationen ein. Diese werden für die Client-Konfiguration verwendet, wenn Sie WireGuard auf Ihren Geräten einrichten.", "setupConfigDesc": "Bitte geben Sie die Host- und Portinformationen ein. Diese werden für die Client-Konfiguration verwendet, wenn Sie WireGuard auf Ihren Geräten einrichten.",
"setupMigrationDesc": "Bitte halten Sie die Sicherungsdatei bereit, wenn Sie Ihre Daten von Ihrer vorherigen wg-easy Version auf ihre neue Einrichtung migrieren möchten.", "setupMigrationDesc": "Bitte halten Sie die Sicherungsdatei bereit, wenn Sie Ihre Daten von Ihrer vorherigen wg-easy Version auf ihre neue Einrichtung migrieren möchten.",
"upload": "Hochladen", "upload": "Hochladen",
"migration": "Sicherung wiederherstellen:", "migration": "Backup wiederherstellen:",
"createAccount": "Konto erstellen", "createAccount": "Konto erstellen",
"successful": "Einrichtung erfolgreich", "successful": "Einrichtung erfolgreich",
"hostDesc": "Öffentlicher Hostname mit dem sich die Clients verbinden", "hostDesc": "Öffentlicher Hostname mit dem sich die Clients verbinden",
"portDesc": "Öffentlicher UDP-Port an dem sich die Clients verbinden und auf dem Wireguard läuft" "portDesc": "Öffentlicher UDP-Port an dem sich die Clients verbinden und auf dem WireGuard läuft"
}, },
"update": { "update": {
"updateAvailable": "Es ist ein neue Aktualisierung verfügbar!", "updateAvailable": "Ein neues Update ist verfügbar!",
"update": "Aktualisieren" "update": "Aktualisieren"
}, },
"theme": { "theme": {
"dark": "Dunkles Thema", "dark": "Dunkles Thema",
"light": "Helles Thema", "light": "Helles Thema",
"system": "System-Thema" "system": "System Thema"
}, },
"layout": { "layout": {
"toggleCharts": "Statistiken ein-/ausblenden", "toggleCharts": "Statistiken ein-/ausblenden",
@@ -84,16 +84,16 @@
"sort": "Sortieren", "sort": "Sortieren",
"create": "Client erstellen", "create": "Client erstellen",
"created": "Client wurde erstellt", "created": "Client wurde erstellt",
"new": "Neuer client", "new": "Neuer Client",
"name": "Name", "name": "Name",
"expireDate": "Ablaufdatum", "expireDate": "Ablaufdatum",
"expireDateDesc": "Datum, an dem der Client deaktiviert wird. Leer lassen, damit dies nie passiert.", "expireDateDesc": "Datum, an dem der Client deaktiviert wird. Leer lassen für dauerhaft aktiv.",
"deleteClient": "Client löschen", "deleteClient": "Client löschen",
"deleteDialog1": "Sind Sie sicher, dass Sie diesen Client löschen wollen", "deleteDialog1": "Sind Sie sicher, dass Sie diesen Client löschen möchten",
"deleteDialog2": "Diese Aktion kann nicht rückgängig gemacht werden.", "deleteDialog2": "Diese Aktion kann nicht rückgängig gemacht werden.",
"enabled": "Aktiviert", "enabled": "Aktiviert",
"address": "Adresse", "address": "Adresse",
"serverAllowedIps": "serverseitig erlaubte IP-Adressen", "serverAllowedIps": "Serverseitig erlaubte IP-Adressen",
"otlDesc": "Einen kurzen Einmal-Link erzeugen", "otlDesc": "Einen kurzen Einmal-Link erzeugen",
"permanent": "Dauerhaft", "permanent": "Dauerhaft",
"createdOn": "Angelegt am ", "createdOn": "Angelegt am ",
@@ -112,8 +112,15 @@
"persistentKeepaliveDesc": "Legt das Intervall (in Sekunden) für Keepalive-Pakete fest. 0 deaktiviert es", "persistentKeepaliveDesc": "Legt das Intervall (in Sekunden) für Keepalive-Pakete fest. 0 deaktiviert es",
"hooks": "Hooks", "hooks": "Hooks",
"hooksDescription": "Hooks funktionieren nur mit wg-quick", "hooksDescription": "Hooks funktionieren nur mit wg-quick",
"hooksLeaveEmpty": "Nur für wg-quick. Sonst leer lassen", "hooksLeaveEmpty": "Nur für wg-quick. Andernfalls leer lassen",
"dnsDesc": "DNS-Server, den die Clients benutzen (überschreibt die globale Konfiguration)" "dnsDesc": "DNS-Server, den die Clients benutzen (überschreibt die globale Konfiguration)",
"delete": "Löschen",
"notConnected": "Client nicht verbunden",
"endpoint": "Endpunkt",
"endpointDesc": "IP-Adresse des Clients, von dem aus die WireGuard-Verbindung hergestellt wird",
"search": "Suche Clients...",
"config": "Konfiguration",
"viewConfig": "Konfiguration anzeigen"
}, },
"dialog": { "dialog": {
"change": "Ändern", "change": "Ändern",
@@ -150,24 +157,24 @@
"config": { "config": {
"connection": "Verbindung", "connection": "Verbindung",
"hostDesc": "Öffentlicher Hostname mit dem sich die Clients verbinden (überschreibt die Konfiguration)", "hostDesc": "Öffentlicher Hostname mit dem sich die Clients verbinden (überschreibt die Konfiguration)",
"portDesc": "Öffentlicher UDP-Port an dem sich die Clients verbinden (überschreibt die Konfiguration, vermutlich wollen Sie ebenfalls den Port der Weboberfläche ändern)", "portDesc": "Öffentlicher UDP-Port an dem sich die Clients verbinden (überschreibt die Konfiguration, vermutlich wollen Sie auch den Interface-Port ändern)",
"allowedIpsDesc": "Erlaubte IP-Adressen, die die Clients nutzen werden (Globale Konfiguration)", "allowedIpsDesc": "Erlaubte IP-Adressen, die die Clients nutzen werden (Globale Konfiguration)",
"dnsDesc": "DNS-Server, den die Clients nutzen werden (Globale Konfiguration)", "dnsDesc": "DNS-Server, den die Clients nutzen werden (Globale Konfiguration)",
"mtuDesc": "MTU, den die Clients benutzen werden (nur für neue Clients)", "mtuDesc": "MTU, den die Clients benutzen werden (nur für neue Clients)",
"persistentKeepaliveDesc": "Intervall in Sekunden, in dem Keepalive-Packete an den Server gesendet werden. 0 = deaktiviert (nur für neue Clients)", "persistentKeepaliveDesc": "Intervall in Sekunden, in dem Keepalive-Pakete an den Server gesendet werden. 0 = deaktiviert (nur für neue Clients)",
"suggest": "Vorschlagen", "suggest": "Vorschlagen",
"suggestDesc": "Wählen Sie eine IP-Adresse oder einen Hostnamen für das Host-Feld aus" "suggestDesc": "Wählen Sie eine IP-Adresse oder einen Hostnamen für das Host-Feld aus"
}, },
"interface": { "interface": {
"cidrSuccess": "CIDR wurde geändert", "cidrSuccess": "CIDR wurde geändert",
"device": "Gerät", "device": "Gerät",
"deviceDesc": "Ethernet-Gerät, durch das der Wireguard-Datenverkehr geleitet werden soll", "deviceDesc": "Ethernet-Gerät, durch das der WireGuard-Datenverkehr geleitet werden soll",
"mtuDesc": "MTU, den WireGuard benutzen wird", "mtuDesc": "MTU, den WireGuard benutzen wird",
"portDesc": "UDP Port, auf dem WireGuard lauschen wird (Sie wollen wahrscheinlich auch den Config-Port ändern)", "portDesc": "UDP-Port, auf dem WireGuard lauschen wird (Sie wollen wahrscheinlich auch den Interface-Port ändern)",
"changeCidr": "CIDR ändern", "changeCidr": "CIDR ändern",
"restart": "Interface neu starten", "restart": "Interface neu starten",
"restartDesc": "Das WireGuard-Interface neu starten", "restartDesc": "Das WireGuard-Interface neu starten",
"restartWarn": "Sind Sie sicher, dass Sie das Interface neu starten wollen? Dies wird die Verbindungen aller Clients trennen.", "restartWarn": "Sind Sie sicher, dass Sie das Interface neu starten möchten? Dies wird die Verbindungen aller Clients trennen.",
"restartSuccess": "Interface neu gestartet" "restartSuccess": "Interface neu gestartet"
}, },
"introText": "Willkommen in der Admin-Konsole.\n\nHier können Sie die allgemeinen Einstellungen, die Konfiguration, die Schnittstelleneinstellungen und die Hooks verwalten.\n\nBeginnen Sie, indem Sie einen der Bereiche in der Seitenleiste auswählen." "introText": "Willkommen in der Admin-Konsole.\n\nHier können Sie die allgemeinen Einstellungen, die Konfiguration, die Schnittstelleneinstellungen und die Hooks verwalten.\n\nBeginnen Sie, indem Sie einen der Bereiche in der Seitenleiste auswählen."
@@ -188,15 +195,15 @@
"expiresAt": "Läuft ab am", "expiresAt": "Läuft ab am",
"address4": "IPv4-Adresse", "address4": "IPv4-Adresse",
"address6": "IPv6-Adresse", "address6": "IPv6-Adresse",
"serverAllowedIps": "serverseitig erlaubte IP-Adressen" "serverAllowedIps": "Serverseitig erlaubte IP-Adressen"
}, },
"user": { "user": {
"username": "Benutzername", "username": "Benutzername",
"password": "Passwort", "password": "Passwort",
"remember": "Merken", "remember": "Merken",
"name": "Name", "name": "Name",
"email": "Email", "email": "E-Mail",
"emailInvalid": "Die Email-Adresse muss valide sein", "emailInvalid": "Die E-Mail-Adresse muss gültig sein",
"passwordMatch": "Die Passwörter müssen übereinstimmen", "passwordMatch": "Die Passwörter müssen übereinstimmen",
"totpEnable": "TOTP aktivieren", "totpEnable": "TOTP aktivieren",
"totpEnableTrue": "\"TOTP aktivieren\" muss ausgewählt sein", "totpEnableTrue": "\"TOTP aktivieren\" muss ausgewählt sein",
@@ -212,8 +219,8 @@
}, },
"interface": { "interface": {
"cidr": "CIDR", "cidr": "CIDR",
"device": "Geräte", "device": "Gerät",
"cidrValid": "CIDR muss valide sein" "cidrValid": "CIDR muss gültig sein"
}, },
"otl": "Einmal-Link", "otl": "Einmal-Link",
"stringMalformed": "Zeichenkette ist fehlerhaft", "stringMalformed": "Zeichenkette ist fehlerhaft",
@@ -233,5 +240,47 @@
"postUp": "PostUp", "postUp": "PostUp",
"preDown": "PreDown", "preDown": "PreDown",
"postDown": "PostDown" "postDown": "PostDown"
},
"copy": {
"notSupported": "Kopieren ist nicht unterstützt",
"copied": "Kopiert!",
"failed": "Kopieren fehlgeschlagen",
"copy": "Kopieren"
},
"awg": {
"jCLabel": "Anzahl der Junk-Pakete (Jc)",
"jCDescription": "Anzahl der zu sendenden Junk-Pakete (1-128, empfohlen: 4-12)",
"jMinLabel": "Minimale Junk-Paketgröße (Jmin)",
"jMinDescription": "Mindestgröße von Junk-Paketen (0-1279*, empfohlen: 8, muss < Jmax sein)",
"jMaxLabel": "Maximale Junk-Paketgröße (Jmax)",
"jMaxDescription": "Maximalgröße von Junk-Paketen (1-1280*, empfohlen: 80, muss > Jmin sein)",
"s1Label": "Junk-Paketgröße des Init-Pakets (S1)",
"s1Description": "Junk-Paketgröße des Init-Pakets (0-1132[1280* - 148 = 1132], empfohlen: 15-150, S1+56 ≠ S2)",
"s2Label": "Junk-Paketgröße des Antwort-Pakets (S2)",
"s2Description": "Junk-Paketgröße des Antwort-Pakets (0-1188[1280* - 92 = 1188], empfohlen: 15-150)",
"s3Label": "Junk-Paketgröße des Cookie-Antwort-Pakets (S3)",
"s3Description": "Junk-Paketgröße des Cookie-Antwort-Pakets",
"s4Label": "Junk-Paketgröße des Transport-Pakets (S4)",
"s4Description": "Junk-Paketgröße des Transport-Pakets",
"i1Label": "Spezial-Junk-Paket 1 (I1)",
"i1Description": "Protokoll-Nachahmungspaket im Hex-Format: <b 0x...>",
"i2Label": "Spezial-Junk-Paket 2 (I2)",
"i2Description": "Protokoll-Nachahmungspaket im Hex-Format: <b 0x...>",
"i3Label": "Spezial-Junk-Paket 3 (I3)",
"i3Description": "Protokoll-Nachahmungspaket im Hex-Format: <b 0x...>",
"i4Label": "Spezial-Junk-Paket 4 (I4)",
"i4Description": "Protokoll-Nachahmungspaket im Hex-Format: <b 0x...>",
"i5Label": "Spezial-Junk-Paket 5 (I5)",
"i5Description": "Protokoll-Nachahmungspaket im Hex-Format: <b 0x...>",
"h1Label": "Init-Magic-Header (H1)",
"h1Description": "Wert des Init-Paket-Headers (5-2147483647, muss eindeutig zu H2-H4 sein)",
"h2Label": "Antwort-Magic-Header (H2)",
"h2Description": "Wert des Antwort-Paket-Headers (5-2147483647, muss eindeutig zu H1, H3, H4 sein)",
"h3Label": "Cookie-Antwort-Magic-Header (H3)",
"h3Description": "Wert des Cookie-Antwort-Paket-Headers (5-2147483647, muss eindeutig zu H1, H2, H4 sein)",
"h4Label": "Transport-Magic-Header (H4)",
"h4Description": "Wert des Transport-Paket-Headers (5-2147483647, muss eindeutig zu H1-H3 sein)",
"mtuNote": "Werte hängen von der MTU ab",
"obfuscationParameters": "AmneziaWG Verschleierungsparameter"
} }
} }
+59 -13
View File
@@ -15,12 +15,12 @@
}, },
"me": { "me": {
"currentPassword": "Mot de passe actuel", "currentPassword": "Mot de passe actuel",
"enable2fa": "Activer l'authentification à double facteur", "enable2fa": "Activer l'authentification à deux facteurs",
"enable2faDesc": "Scannez le code QR avec votre application d'authentification ou saisissez la clé manuellement.", "enable2faDesc": "Scannez le code QR avec votre application d'authentification ou saisissez la clé manuellement.",
"2faKey": "Clé TOTP", "2faKey": "Clé TOTP",
"2faCodeDesc": "Saisissez le code de votre application d'authentification.", "2faCodeDesc": "Saisissez le code de votre application d'authentification.",
"disable2fa": "Désactiver l'authentification à double facteur", "disable2fa": "Désactiver l'authentification à deux facteurs",
"disable2faDesc": "Saisissez votre mot de passe pour désactiver l'authentification à double facteur" "disable2faDesc": "Saisissez votre mot de passe pour désactiver l'authentification à deux facteurs."
}, },
"general": { "general": {
"name": "Nom", "name": "Nom",
@@ -40,7 +40,7 @@
"no": "Non", "no": "Non",
"confirmPassword": "Confirmer le mot de passe", "confirmPassword": "Confirmer le mot de passe",
"loading": "Chargement...", "loading": "Chargement...",
"2fa": "Authentification à double facteur", "2fa": "Authentification à deux facteurs",
"2faCode": "Code TOTP" "2faCode": "Code TOTP"
}, },
"setup": { "setup": {
@@ -75,8 +75,8 @@
"rememberMe": "Se souvenir de moi", "rememberMe": "Se souvenir de moi",
"rememberMeDesc": "Rester connecté après avoir fermé le navigateur", "rememberMeDesc": "Rester connecté après avoir fermé le navigateur",
"insecure": "Vous ne pouvez pas vous connecter avec une connexion non sécurisée. Utilisez HTTPS.", "insecure": "Vous ne pouvez pas vous connecter avec une connexion non sécurisée. Utilisez HTTPS.",
"2faRequired": "Une authentification à double facteur est requise", "2faRequired": "L'authentification à deux facteurs est requise",
"2faWrong": "L'authentification à double facteur est incorrecte" "2faWrong": "Le code d'authentification à deux facteurs est incorrect"
}, },
"client": { "client": {
"empty": "Il n'y a pas encore de clients.", "empty": "Il n'y a pas encore de clients.",
@@ -108,7 +108,7 @@
"downloadConfig": "Télécharger la configuration", "downloadConfig": "Télécharger la configuration",
"allowedIpsDesc": "Quelles IPs seront acheminées par le VPN (remplace la configuration globale)", "allowedIpsDesc": "Quelles IPs seront acheminées par le VPN (remplace la configuration globale)",
"serverAllowedIpsDesc": "Les IPs que le serveur acheminera vers le client", "serverAllowedIpsDesc": "Les IPs que le serveur acheminera vers le client",
"mtuDesc": "Définit le nombre maximum d'unités de transmission (taille des paquets) pour le tunnel VPN.", "mtuDesc": "Définit l'unité de transmission maximale (taille des paquets) pour le tunnel VPN",
"persistentKeepaliveDesc": "Définit l'intervalle (en secondes) pour les paquets keep-alive. 0 le désactive", "persistentKeepaliveDesc": "Définit l'intervalle (en secondes) pour les paquets keep-alive. 0 le désactive",
"hooks": "Hooks", "hooks": "Hooks",
"hooksDescription": "Les hooks ne fonctionnent qu'avec wg-quick", "hooksDescription": "Les hooks ne fonctionnent qu'avec wg-quick",
@@ -116,7 +116,11 @@
"dnsDesc": "Serveur DNS que les clients utiliseront (remplace la configuration globale)", "dnsDesc": "Serveur DNS que les clients utiliseront (remplace la configuration globale)",
"notConnected": "Client non connecté", "notConnected": "Client non connecté",
"endpoint": "Endpoint", "endpoint": "Endpoint",
"endpointDesc": "Adresse IP du client à partir duquel la connexion WireGuard est établie" "endpointDesc": "Adresse IP du client à partir duquel la connexion WireGuard est établie",
"search": "Rechercher des clients...",
"config": "Configuration",
"viewConfig": "Voir la configuration",
"delete": "Supprimer"
}, },
"dialog": { "dialog": {
"change": "Modifier", "change": "Modifier",
@@ -146,9 +150,9 @@
"metricsPassword": "Mot de passe", "metricsPassword": "Mot de passe",
"metricsPasswordDesc": "Mot de passe Bearer pour le endpoint des métriques (mot de passe ou argon2 hash)", "metricsPasswordDesc": "Mot de passe Bearer pour le endpoint des métriques (mot de passe ou argon2 hash)",
"json": "JSON", "json": "JSON",
"jsonDesc": "Acheminement pour les métriques au format JSON", "jsonDesc": "Route pour les métriques au format JSON",
"prometheus": "Prometheus", "prometheus": "Prometheus",
"prometheusDesc": "Acheminement pour les métriques de Prometheus" "prometheusDesc": "Route pour les métriques Prometheus"
}, },
"config": { "config": {
"connection": "Connexion", "connection": "Connexion",
@@ -180,13 +184,13 @@
"required": "{0} est requis", "required": "{0} est requis",
"validNumber": "{0} doit être un nombre valide", "validNumber": "{0} doit être un nombre valide",
"validString": "{0} doit être une chaîne de caractères valide", "validString": "{0} doit être une chaîne de caractères valide",
"validBoolean": "{0} doit être une variable valide", "validBoolean": "{0} doit être un booléen valide",
"validArray": "{0} doit être un tableau valide", "validArray": "{0} doit être un tableau valide",
"stringMin": "{0} doit être d'au moins {1} Caractère", "stringMin": "{0} doit comporter au moins {1} caractère(s)",
"numberMin": "{0} doit être d'au moins {1}" "numberMin": "{0} doit être d'au moins {1}"
}, },
"client": { "client": {
"id": "Client ID", "id": "ID du client",
"name": "Nom", "name": "Nom",
"expiresAt": "Expire le", "expiresAt": "Expire le",
"address4": "Adresse IPv4", "address4": "Adresse IPv4",
@@ -236,5 +240,47 @@
"postUp": "PostUp", "postUp": "PostUp",
"preDown": "PreDown", "preDown": "PreDown",
"postDown": "PostDown" "postDown": "PostDown"
},
"copy": {
"notSupported": "La copie n'est pas prise en charge",
"copied": "Copié !",
"failed": "Échec de la copie",
"copy": "Copier"
},
"awg": {
"jCLabel": "Nombre de paquets parasites (Jc)",
"jCDescription": "Nombre de paquets parasites à envoyer (1-128, recommandé : 4-12)",
"jMinLabel": "Taille min des paquets parasites (Jmin)",
"jMinDescription": "Taille minimale des paquets parasites (0-1279*, recommandé : 8, doit être < Jmax)",
"jMaxLabel": "Taille max des paquets parasites (Jmax)",
"jMaxDescription": "Taille maximale des paquets parasites (1-1280*, recommandé : 80, doit être > Jmin)",
"s1Label": "Taille parasite du paquet init (S1)",
"s1Description": "Taille parasite du paquet d'initialisation (0-1132[1280* - 148 = 1132], recommandé : 15-150, S1+56 ≠ S2)",
"s2Label": "Taille parasite du paquet réponse (S2)",
"s2Description": "Taille parasite du paquet de réponse (0-1188[1280* - 92 = 1188], recommandé : 15-150)",
"s3Label": "Taille parasite du paquet cookie reply (S3)",
"s3Description": "Taille parasite du paquet de réponse cookie",
"s4Label": "Taille parasite du paquet transport (S4)",
"s4Description": "Taille parasite du paquet de transport",
"i1Label": "Paquet parasite spécial 1 (I1)",
"i1Description": "Paquet de simulation de protocole en format hexadécimal : <b 0x...>",
"i2Label": "Paquet parasite spécial 2 (I2)",
"i2Description": "Paquet de simulation de protocole en format hexadécimal : <b 0x...>",
"i3Label": "Paquet parasite spécial 3 (I3)",
"i3Description": "Paquet de simulation de protocole en format hexadécimal : <b 0x...>",
"i4Label": "Paquet parasite spécial 4 (I4)",
"i4Description": "Paquet de simulation de protocole en format hexadécimal : <b 0x...>",
"i5Label": "Paquet parasite spécial 5 (I5)",
"i5Description": "Paquet de simulation de protocole en format hexadécimal : <b 0x...>",
"h1Label": "En-tête magique init (H1)",
"h1Description": "Valeur d'en-tête du paquet init (5-2147483647, doit être unique par rapport à H2-H4)",
"h2Label": "En-tête magique réponse (H2)",
"h2Description": "Valeur d'en-tête du paquet réponse (5-2147483647, doit être unique par rapport à H1, H3, H4)",
"h3Label": "En-tête magique cookie reply (H3)",
"h3Description": "Valeur d'en-tête du paquet cookie reply (5-2147483647, doit être unique par rapport à H1, H2, H4)",
"h4Label": "En-tête magique transport (H4)",
"h4Description": "Valeur d'en-tête du paquet transport (5-2147483647, doit être unique par rapport à H1-H3)",
"mtuNote": "Les valeurs dépendent du MTU",
"obfuscationParameters": "Paramètres d'obfuscation AmneziaWG"
} }
} }
+117 -71
View File
@@ -3,8 +3,8 @@
"me": "Аккаунт", "me": "Аккаунт",
"clients": "Клиенты", "clients": "Клиенты",
"admin": { "admin": {
"panel": "Админ панель", "panel": "Админ-панель",
"general": "Общие", "general": "Общие настройки",
"config": "Конфигурация", "config": "Конфигурация",
"interface": "Интерфейс", "interface": "Интерфейс",
"hooks": "Хуки" "hooks": "Хуки"
@@ -16,11 +16,11 @@
"me": { "me": {
"currentPassword": "Текущий пароль", "currentPassword": "Текущий пароль",
"enable2fa": "Включить двухфакторную аутентификацию", "enable2fa": "Включить двухфакторную аутентификацию",
"enable2faDesc": "Отсканируйте QR-код приложением-аутентификатором или введите ключ вручную.", "enable2faDesc": "Отсканируйте QRкод с помощью приложения‑аутентификатора или введите ключ вручную.",
"2faKey": "TOTP-ключ", "2faKey": "Ключ TOTP",
"2faCodeDesc": "Введите код из приложения-аутентификатора.", "2faCodeDesc": "Введите код из приложенияаутентификатора.",
"disable2fa": "Отключить двухфакторную аутентификацию", "disable2fa": "Отключить двухфакторную аутентификацию",
"disable2faDesc": "Введите пароль, чтобы отключить двухфакторную аутентификацию" "disable2faDesc": "Введите пароль, чтобы отключить двухфакторную аутентификацию."
}, },
"general": { "general": {
"name": "Имя", "name": "Имя",
@@ -29,9 +29,9 @@
"newPassword": "Новый пароль", "newPassword": "Новый пароль",
"updatePassword": "Обновить пароль", "updatePassword": "Обновить пароль",
"mtu": "MTU", "mtu": "MTU",
"allowedIps": "Разрешённые IP", "allowedIps": "Разрешённые IP‑адреса",
"dns": "DNS", "dns": "DNS",
"persistentKeepalive": "Постоянный keepalive", "persistentKeepalive": "Постоянное поддержание соединения",
"logout": "Выйти", "logout": "Выйти",
"continue": "Продолжить", "continue": "Продолжить",
"host": "Хост", "host": "Хост",
@@ -41,21 +41,21 @@
"confirmPassword": "Подтвердите пароль", "confirmPassword": "Подтвердите пароль",
"loading": "Загрузка...", "loading": "Загрузка...",
"2fa": "Двухфакторная аутентификация", "2fa": "Двухфакторная аутентификация",
"2faCode": "TOTP‑код" "2faCode": "Код TOTP"
}, },
"setup": { "setup": {
"welcome": "Добро пожаловать в первичную настройку wg-easy", "welcome": "Добро пожаловать в первичную настройку wg-easy",
"welcomeDesc": "Вы нашли самый простой способ установить и управлять WireGuard на любом Linux-хосте", "welcomeDesc": "Вы нашли самый простой способ установить и управлять WireGuard на любом Linuxхосте",
"existingSetup": "У вас уже есть существующая установка?", "existingSetup": "У вас уже есть существующая настройка?",
"createAdminDesc": "Сначала введите имя администратора и надёжный пароль. Эти данные понадобятся для входа в панель управления", "createAdminDesc": "Сначала введите имя администратора и надёжный пароль. Эти данные будут использоваться для входа в Админ-панель.",
"setupConfigDesc": "Введите информацию о хосте и порте. Она будет использоваться в конфигурации клиента при установке WireGuard на устройствах", "setupConfigDesc": "Введите данные хоста и порта. Они будут использоваться для настройки клиента при установке WireGuard на устройствах.",
"setupMigrationDesc": "Укажите файл резервной копии, если хотите перенести данные из предыдущей версии wg-easy", "setupMigrationDesc": "Укажите файл резервной копии, если хотите перенести данные из предыдущей версии wg-easy.",
"upload": "Загрузить", "upload": "Загрузить",
"migration": "Восстановить из резервной копии:", "migration": "Восстановить из резервной копии:",
"createAccount": "Создать аккаунт", "createAccount": "Создать аккаунт",
"successful": "Настройка успешна", "successful": "Настройка завершена успешно",
"hostDesc": "Публичное имя хоста, к которому будут подключаться клиенты", "hostDesc": "Публичное имя хоста, к которому будут подключаться клиенты",
"portDesc": "Публичный UDP‑порт для подключения клиентов и прослушивания WireGuard" "portDesc": "Публичный UDP‑порт, к которому будут подключаться клиенты и на котором будет слушать WireGuard"
}, },
"update": { "update": {
"updateAvailable": "Доступно обновление!", "updateAvailable": "Доступно обновление!",
@@ -68,7 +68,7 @@
}, },
"layout": { "layout": {
"toggleCharts": "Показать/скрыть графики", "toggleCharts": "Показать/скрыть графики",
"donate": "Пожертвовать" "donate": "Поддержать"
}, },
"login": { "login": {
"signIn": "Войти", "signIn": "Войти",
@@ -87,18 +87,19 @@
"new": "Новый клиент", "new": "Новый клиент",
"name": "Имя", "name": "Имя",
"expireDate": "Дата отключения", "expireDate": "Дата отключения",
"expireDateDesc": "Дата, когда клиент будет отключён. Пусто — бессрочно", "expireDateDesc": "Дата, когда клиент будет отключён. Оставьте пустым для бессрочного доступа",
"delete": "Удалить",
"deleteClient": "Удалить клиента", "deleteClient": "Удалить клиента",
"deleteDialog1": "Вы уверены, что хотите удалить", "deleteDialog1": "Вы уверены, что хотите удалить",
"deleteDialog2": "Это действие необратимо.", "deleteDialog2": "Это действие нельзя отменить.",
"enabled": "Включен", "enabled": "Включён",
"address": "Адрес", "address": "Адрес",
"serverAllowedIps": "Разрешённые IP сервера", "serverAllowedIps": "Разрешённые IP‑адреса сервера",
"otlDesc": "Сгенерировать одноразовую короткую ссылку", "otlDesc": "Сгенерировать короткую одноразовую ссылку",
"permanent": "Постоянный", "permanent": "Бессрочный",
"createdOn": "Создан ", "createdOn": "Создан ",
"lastSeen": "Последнее подключение ", "lastSeen": "Последнее подключение ",
"totalDownload": "Всего загружено: ", "totalDownload": "Всего скачано: ",
"totalUpload": "Всего отправлено: ", "totalUpload": "Всего отправлено: ",
"newClient": "Новый клиент", "newClient": "Новый клиент",
"disableClient": "Отключить клиента", "disableClient": "Отключить клиента",
@@ -106,25 +107,28 @@
"noPrivKey": "У этого клиента нет приватного ключа. Невозможно создать конфигурацию.", "noPrivKey": "У этого клиента нет приватного ключа. Невозможно создать конфигурацию.",
"showQR": "Показать QR‑код", "showQR": "Показать QR‑код",
"downloadConfig": "Скачать конфигурацию", "downloadConfig": "Скачать конфигурацию",
"allowedIpsDesc": "Какие IP будут маршрутизироваться через VPN (перезаписывает общую конфигурацию)", "allowedIpsDesc": "Какие IP‑адреса будут маршрутизироваться через VPN (переопределяет глобальную конфигурацию)",
"serverAllowedIpsDesc": "Какие IP сервер будет отправлять клиенту", "serverAllowedIpsDesc": "Какие IP‑адреса сервер будет отправлять клиенту",
"mtuDesc": "Максимальный размер пакета для VPN‑туннеля", "mtuDesc": "Максимальный размер пакета (MTU) для VPN‑туннеля",
"persistentKeepaliveDesc": "Интервал пакетов для поддержания соединения (в секундах). 0 — отключено.", "persistentKeepaliveDesc": "Устанавливает интервал (в секундах) для пакетов поддержания соединения. 0 — отключить",
"hooks": "Хуки", "hooks": "Хуки",
"hooksDescription": "Хуки работают только с wg-quick", "hooksDescription": "Хуки работают только с wgquick",
"hooksLeaveEmpty": "Только для wg-quick. Иначе оставьте пустым", "hooksLeaveEmpty": "Только для wgquick. В остальных случаях оставьте пустым",
"dnsDesc": "DNS‑сервер, который будут использовать клиенты (перезаписывает общую конфигурацию)", "dnsDesc": "DNS‑сервер, который будут использовать клиенты (переопределяет глобальную конфигурацию)",
"notConnected": "Клиент не подключен", "notConnected": "Клиент не подключен",
"endpoint": "Конечная точка", "endpoint": "Точка подключения",
"endpointDesc": "IP-адрес клиента, с которого установлено соединение WireGuard" "endpointDesc": "IPадрес клиента, с которого установлено соединение WireGuard",
"search": "Поиск клиентов...",
"config": "Конфигурация",
"viewConfig": "Просмотреть конфигурацию"
}, },
"dialog": { "dialog": {
"change": "Изменить", "change": "Изменить",
"cancel": "Отмена", "cancel": "Отменить",
"create": "Создать" "create": "Создать"
}, },
"toast": { "toast": {
"success": "Успех", "success": "Успешно",
"saved": "Сохранено", "saved": "Сохранено",
"error": "Ошибка" "error": "Ошибка"
}, },
@@ -133,18 +137,18 @@
"save": "Сохранить", "save": "Сохранить",
"revert": "Отменить", "revert": "Отменить",
"sectionGeneral": "Общие", "sectionGeneral": "Общие",
"sectionAdvanced": "Дополнительно", "sectionAdvanced": "Расширенные",
"noItems": "Нет элементов", "noItems": "Нет элементов",
"nullNoItems": "Нет элементов. Используется глобальная конфигурация", "nullNoItems": "Нет элементов. Используется глобальная конфигурация",
"add": "Добавить" "add": "Добавить"
}, },
"admin": { "admin": {
"general": { "general": {
"sessionTimeout": "Тайм-аут сессии", "sessionTimeout": "Время жизни сессии",
"sessionTimeoutDesc": "Длительность сеанса для \"Запомнить меня\" (секунды)", "sessionTimeoutDesc": "Длительность сессии для «Запомнить меня» (в секундах)",
"metrics": "Метрики", "metrics": "Метрики",
"metricsPassword": "Пароль", "metricsPassword": "Пароль",
"metricsPasswordDesc": "Пароль Bearer для эндпоинта метрик (пароль или хеш argon2)", "metricsPasswordDesc": "Пароль Bearer для конечной точки метрик (пароль или хэш argon2)",
"json": "JSON", "json": "JSON",
"jsonDesc": "Путь для метрик в формате JSON", "jsonDesc": "Путь для метрик в формате JSON",
"prometheus": "Prometheus", "prometheus": "Prometheus",
@@ -152,83 +156,83 @@
}, },
"config": { "config": {
"connection": "Соединение", "connection": "Соединение",
"hostDesc": "Публичное имя хоста для подключения клиентов (сбросит конфигурацию)", "hostDesc": "Публичное имя хоста для подключения клиентов(обнуляет конфигурацию)",
"portDesc": "Публичный UDP‑порт для подключения клиентов (также стоит изменить порт интерфейса)", "portDesc": "Публичный UDP‑порт для подключения клиентов (также рекомендуется изменить порт интерфейса)",
"allowedIpsDesc": "Разрешённые IP для клиентов (общая конфигурация)", "allowedIpsDesc": "Разрешённые IP‑адреса для клиентов(глобальная конфигурация)",
"dnsDesc": "DNS‑сервер для клиентов (общая конфигурация)", "dnsDesc": "DNS‑сервер для клиентов (глобальная конфигурация)",
"mtuDesc": "MTU для клиентов (только для новых)", "mtuDesc": "MTU для клиентов (только для новых)",
"persistentKeepaliveDesc": "Интервал отправки keepalive на сервер (секунды). 0 = отключено (только для новых)", "persistentKeepaliveDesc": "Интервал в секундах для отправки пакетов поддержания соединения на сервер. 0 = отключено (только для новых клиентов)",
"suggest": "Определить", "suggest": "Предложить",
"suggestDesc": "Выберите IP‑адрес или имя хоста для поля Host" "suggestDesc": "Выберите IP‑адрес или имя хоста для поля «Хост»"
}, },
"interface": { "interface": {
"cidrSuccess": "CIDR изменён", "cidrSuccess": "CIDR изменён",
"device": "Устройство", "device": "Устройство",
"deviceDesc": "Сетевое устройство, через которое должен проходить трафик WireGuard", "deviceDesc": "Сетевое устройство Ethernet, через которое должен проходить трафик WireGuard",
"mtuDesc": "MTU, который использует WireGuard", "mtuDesc": "MTU, который будет использовать WireGuard",
"portDesc": "UDP‑порт, на котором WireGuard будет слушать (возможно, нужно изменить и порт конфигурации)", "portDesc": "UDP‑порт, на котором будет слушать WireGuard (возможно, нужно также изменить порт конфигурации)",
"changeCidr": "Изменить CIDR", "changeCidr": "Изменить CIDR",
"restart": "Перезапустить интерфейс", "restart": "Перезапустить интерфейс",
"restartDesc": "Перезапустить интерфейс WireGuard", "restartDesc": "Перезапустить интерфейс WireGuard",
"restartWarn": "Вы уверены, что хотите перезапустить интерфейс? Все клиенты будут отключены.", "restartWarn": "Вы уверены, что хотите перезапустить интерфейс? Это приведёт к отключению всех клиентов.",
"restartSuccess": "Интерфейс перезапущен" "restartSuccess": "Интерфейс перезапущен"
}, },
"introText": "Добро пожаловать в панель администратора.\n\nЗдесь вы можете управлять общими настройками, конфигурацией, параметрами интерфейса и хуками.\n\nНачните с выбора раздела в боковой панели." "introText": "Добро пожаловать в панель администратора.\n\nЗдесь вы можете управлять общими настройками, конфигурацией, настройками интерфейса и хуками.\n\nНачните с выбора одного из разделов на боковой панели."
}, },
"zod": { "zod": {
"generic": { "generic": {
"required": "{0} обязательное поле", "required": "{0} обязательно для заполнения",
"validNumber": "{0} должен быть числом", "validNumber": "{0} должно быть числом",
"validString": "{0} должна быть строкой", "validString": "{0} должно быть строкой",
"validBoolean": "{0} должен быть булевым значением", "validBoolean": "{0} должно быть логическим значением",
"validArray": "{0} должен быть массивом", "validArray": "{0} должно быть массивом",
"stringMin": "{0} должен содержать не менее {1} символов", "stringMin": "{0} должно содержать не менее {1} символа",
"numberMin": "{0} должен быть не меньше {1}" "numberMin": "{0} должно быть не менее {1}"
}, },
"client": { "client": {
"id": "ID клиента", "id": "ID клиента",
"name": "Имя", "name": "Имя",
"expiresAt": ействителен до", "expiresAt": ата окончания действия",
"address4": "IPv4 адрес", "address4": "IPv4адрес",
"address6": "IPv6 адрес", "address6": "IPv6адрес",
"serverAllowedIps": "Разрешённые IP сервера" "serverAllowedIps": "Разрешённые IP‑адреса сервера"
}, },
"user": { "user": {
"username": "Имя пользователя", "username": "Имя пользователя",
"password": "Пароль", "password": "Пароль",
"remember": "Запомнить", "remember": "Запомнить",
"name": "Имя", "name": "Имя",
"email": "Email", "email": "Электронная почта",
"emailInvalid": "Email должен быть валидным", "emailInvalid": "Адрес электронной почты должен быть корректным",
"passwordMatch": "Пароли должны совпадать", "passwordMatch": "Пароли должны совпадать",
"totpEnable": "Включить TOTP", "totpEnable": "Включить TOTP",
"totpEnableTrue": "Необходимо включить TOTP", "totpEnableTrue": "TOTP должен быть включён",
"totpCode": "TOTP‑код" "totpCode": "Код TOTP"
}, },
"userConfig": { "userConfig": {
"host": "Хост" "host": "Хост"
}, },
"general": { "general": {
"sessionTimeout": "Тайм-аут сессии", "sessionTimeout": "Время жизни сессии",
"metricsEnabled": "Метрики", "metricsEnabled": "Метрики",
"metricsPassword": "Пароль для метрик" "metricsPassword": "Пароль для метрик"
}, },
"interface": { "interface": {
"cidr": "CIDR", "cidr": "CIDR",
"device": "Устройство", "device": "Устройство",
"cidrValid": "CIDR должен быть валидным" "cidrValid": "CIDR должен быть корректным"
}, },
"otl": "Одноразовая ссылка", "otl": "Одноразовая ссылка",
"stringMalformed": "Строка имеет неверный формат", "stringMalformed": "Строка имеет неверный формат",
"body": "Тело должно быть объектом", "body": "Тело должно быть корректным объектом",
"hook": "Хук", "hook": "Хук",
"enabled": "Включено", "enabled": "Включено",
"mtu": "MTU", "mtu": "MTU",
"port": "Порт", "port": "Порт",
"persistentKeepalive": "Поддерживать соединение", "persistentKeepalive": "Постоянное поддержание соединения",
"address": "IP‑адрес", "address": "IP‑адрес",
"dns": "DNS", "dns": "DNS",
"allowedIps": "Разрешённые IP", "allowedIps": "Разрешённые IP‑адреса",
"file": "Файл" "file": "Файл"
}, },
"hooks": { "hooks": {
@@ -236,5 +240,47 @@
"postUp": "PostUp", "postUp": "PostUp",
"preDown": "PreDown", "preDown": "PreDown",
"postDown": "PostDown" "postDown": "PostDown"
},
"copy": {
"notSupported": "Копирование не поддерживается",
"copied": "Скопировано!",
"failed": "Ошибка копирования",
"copy": "Копировать"
},
"awg": {
"jCLabel": "Количество шумовых пакетов (Jc)",
"jCDescription": "Число шумовых пакетов для отправки (1-128, рекомендуется: 4-12)",
"jMinLabel": "Минимальный размер шумовых пакетов (Jmin)",
"jMinDescription": "Минимальный размер шумовых пакетов (0-1279*, рекомендуется: 8, должен быть < Jmax)",
"jMaxLabel": "Максимальный размер шумовых пакетов (Jmax)",
"jMaxDescription": "Максимальный размер шумовых пакетов (1-1280*, рекомендуется: 80, должен быть > Jmin)",
"s1Label": "Размер шумовых данных в init-пакете (S1)",
"s1Description": "Размер шумовых данных в init-пакете (0-1132[1280* - 148 = 1132], рекомендуется: 15-150, S1+56 ≠ S2)",
"s2Label": "Размер шумовых данных в ответном пакете (S2)",
"s2Description": "Размер шумовых данных в ответном пакете (0-1188[1280* - 92 = 1188], рекомендуется: 15-150)",
"s3Label": "Размер шумовых данных в cookie-reply пакете (S3)",
"s3Description": "Размер шумовых данных в cookie-reply пакете",
"s4Label": "Размер шумовых данных в транспортном пакете (S4)",
"s4Description": "Размер шумовых данных в транспортном пакете",
"i1Label": "Специальный шумовой пакет 1 (I1)",
"i1Description": "Пакет имитации протокола в hex формате: <b 0x...>",
"i2Label": "Специальный шумовой пакет 2 (I2)",
"i2Description": "Пакет имитации протокола в hex формате: <b 0x...>",
"i3Label": "Специальный шумовой пакет 3 (I3)",
"i3Description": "Пакет имитации протокола в hex формате: <b 0x...>",
"i4Label": "Специальный шумовой пакет 4 (I4)",
"i4Description": "Пакет имитации протокола в hex формате: <b 0x...>",
"i5Label": "Специальный шумовой пакет 5 (I5)",
"i5Description": "Пакет имитации протокола в hex формате: <b 0x...>",
"h1Label": "Init magic заголовок (H1)",
"h1Description": "Значение заголовка init-пакета (5-2147483647, должно отличаться от H2-H4)",
"h2Label": "Response magic заголовок (H2)",
"h2Description": "Значение заголовка ответного пакета (5-2147483647, должно отличаться от H1, H3, H4)",
"h3Label": "Cookie reply magic заголовок (H3)",
"h3Description": "Значение заголовка cookie-reply пакета (5-2147483647, должно отличаться от H1, H2, H4)",
"h4Label": "Transport magic заголовок (H4)",
"h4Description": "Значение заголовка транспортного пакета (5-2147483647, должно отличаться от H1-H3)",
"mtuNote": "Значения зависят от MTU",
"obfuscationParameters": "Параметры обфускации AmneziaWG"
} }
} }
+1
View File
@@ -88,6 +88,7 @@
"name": "Ім'я", "name": "Ім'я",
"expireDate": "Термін дії", "expireDate": "Термін дії",
"expireDateDesc": "Дата, коли клієнт буде відключений. Порожнє для постійного користування", "expireDateDesc": "Дата, коли клієнт буде відключений. Порожнє для постійного користування",
"delete": "Видалити",
"deleteClient": "Видалити клієнта", "deleteClient": "Видалити клієнта",
"deleteDialog1": "Ви впевнені, що бажаєте видалити", "deleteDialog1": "Ви впевнені, що бажаєте видалити",
"deleteDialog2": "Цю дію неможливо скасувати.", "deleteDialog2": "Цю дію неможливо скасувати.",
+16 -16
View File
@@ -1,6 +1,6 @@
{ {
"name": "wg-easy", "name": "wg-easy",
"version": "15.2.0-beta.3", "version": "15.2.1",
"description": "The easiest way to run WireGuard VPN + Web-based Admin UI.", "description": "The easiest way to run WireGuard VPN + Web-based Admin UI.",
"private": true, "private": true,
"type": "module", "type": "module",
@@ -22,12 +22,12 @@
"dependencies": { "dependencies": {
"@eschricht/nuxt-color-mode": "^1.2.0", "@eschricht/nuxt-color-mode": "^1.2.0",
"@heroicons/vue": "^2.2.0", "@heroicons/vue": "^2.2.0",
"@libsql/client": "^0.15.15", "@libsql/client": "^0.17.0",
"@nuxtjs/i18n": "^10.2.1", "@nuxtjs/i18n": "^10.2.1",
"@nuxtjs/tailwindcss": "^6.14.0", "@nuxtjs/tailwindcss": "^6.14.0",
"@phc/format": "^1.0.0", "@phc/format": "^1.0.0",
"@pinia/nuxt": "^0.11.3", "@pinia/nuxt": "^0.11.3",
"@tailwindcss/forms": "^0.5.10", "@tailwindcss/forms": "^0.5.11",
"@vueuse/core": "^14.1.0", "@vueuse/core": "^14.1.0",
"@vueuse/nuxt": "^14.1.0", "@vueuse/nuxt": "^14.1.0",
"apexcharts": "^5.3.6", "apexcharts": "^5.3.6",
@@ -37,37 +37,37 @@
"consola": "^3.4.2", "consola": "^3.4.2",
"crc-32": "^1.2.2", "crc-32": "^1.2.2",
"debug": "^4.4.3", "debug": "^4.4.3",
"drizzle-orm": "^0.44.7", "drizzle-orm": "^0.45.1",
"ip-bigint": "^8.2.2", "ip-bigint": "^8.2.2",
"is-cidr": "^6.0.1", "is-cidr": "^6.0.1",
"is-ip": "^5.0.1", "is-ip": "^5.0.1",
"js-sha256": "^0.11.1", "js-sha256": "^0.11.1",
"nuxt": "^3.20.1", "nuxt": "^3.20.2",
"otpauth": "^9.4.1", "otpauth": "^9.4.1",
"pinia": "^3.0.4", "pinia": "^3.0.4",
"qr": "^0.5.3", "qr": "^0.5.4",
"radix-vue": "^1.9.17", "radix-vue": "^1.9.17",
"semver": "^7.7.3", "semver": "^7.7.3",
"tailwindcss": "^3.4.18", "tailwindcss": "^3.4.19",
"timeago.js": "^4.0.2", "timeago.js": "^4.0.2",
"vue": "latest", "vue": "latest",
"vue3-apexcharts": "^1.10.0", "vue3-apexcharts": "^1.10.0",
"zod": "^4.1.13" "zod": "^4.3.5"
}, },
"devDependencies": { "devDependencies": {
"@nuxt/eslint": "^1.11.0", "@nuxt/eslint": "^1.12.1",
"@types/debug": "^4.1.12", "@types/debug": "^4.1.12",
"@types/phc__format": "^1.0.1", "@types/phc__format": "^1.0.1",
"@types/semver": "^7.7.1", "@types/semver": "^7.7.1",
"drizzle-kit": "^0.31.7", "drizzle-kit": "^0.31.8",
"esbuild": "^0.27.0", "esbuild": "^0.27.2",
"eslint": "^9.39.1", "eslint": "^9.39.2",
"eslint-config-prettier": "^10.1.8", "eslint-config-prettier": "^10.1.8",
"prettier": "^3.7.3", "prettier": "^3.7.4",
"prettier-plugin-tailwindcss": "^0.7.1", "prettier-plugin-tailwindcss": "^0.7.2",
"tsx": "^4.21.0", "tsx": "^4.21.0",
"typescript": "^5.9.3", "typescript": "^5.9.3",
"vue-tsc": "^3.1.5" "vue-tsc": "^3.2.2"
}, },
"packageManager": "pnpm@10.24.0" "packageManager": "pnpm@10.28.0"
} }
+1597 -1457
View File
File diff suppressed because it is too large Load Diff
+7 -2
View File
@@ -1,9 +1,14 @@
import type { SharedPublicUser } from '~~/shared/utils/permissions';
export default defineEventHandler(async (event) => { export default defineEventHandler(async (event) => {
const session = await useWGSession(event); const session = await useWGSession(event);
if (!session.data.userId) { if (!session.data.userId) {
// not logged in // not logged in
return null; throw createError({
statusCode: 401,
statusMessage: 'Not authenticated',
});
} }
const user = await Database.users.get(session.data.userId); const user = await Database.users.get(session.data.userId);
@@ -21,5 +26,5 @@ export default defineEventHandler(async (event) => {
name: user.name, name: user.name,
email: user.email, email: user.email,
totpVerified: user.totpVerified, totpVerified: user.totpVerified,
}; } satisfies SharedPublicUser;
}); });
@@ -16,6 +16,12 @@ function createPreparedStatement(db: DBType) {
oneTimeLink: sql.placeholder('oneTimeLink'), oneTimeLink: sql.placeholder('oneTimeLink'),
expiresAt: sql.placeholder('expiresAt'), expiresAt: sql.placeholder('expiresAt'),
}) })
.onConflictDoUpdate({
target: oneTimeLink.id,
set: {
expiresAt: sql.placeholder('expiresAt') as never as string,
},
})
.prepare(), .prepare(),
erase: db erase: db
.update(oneTimeLink) .update(oneTimeLink)
+1 -1
View File
@@ -3,7 +3,7 @@ export default defineEventHandler(async (event) => {
const url = getRequestURL(event); const url = getRequestURL(event);
// User can't be logged in, and public routes can be accessed whenever // User can't be logged in, and public routes can be accessed whenever
if (url.pathname.startsWith('/api/')) { if (url.pathname.startsWith('/api/') || url.pathname.startsWith('/_i18n/')) {
return; return;
} }
+1 -1
View File
@@ -213,7 +213,7 @@ class WireGuard {
WG_DEBUG('New Wireguard Keys generated successfully.'); WG_DEBUG('New Wireguard Keys generated successfully.');
} }
if (WG_ENV.WG_EXECUTABLE === 'awg' && wgInterface.h1 === 0) { if (wgInterface.h1 === 0) {
WG_DEBUG('Generating random AmneziaWG obfuscation parameters...'); WG_DEBUG('Generating random AmneziaWG obfuscation parameters...');
const headers = new Set<number>(); const headers = new Set<number>();
+5
View File
@@ -45,6 +45,11 @@ type SharedUserType =
| Pick<UserType, 'id' | 'role'> | Pick<UserType, 'id' | 'role'>
| (Pick<UserType, 'id'> & { role: BrandedNumber }); | (Pick<UserType, 'id'> & { role: BrandedNumber });
export type SharedPublicUser = Pick<
UserType,
'id' | 'username' | 'name' | 'email' | 'totpVerified'
> & { role: BrandedNumber };
type PermissionCheck<Key extends keyof Permissions> = type PermissionCheck<Key extends keyof Permissions> =
| boolean | boolean
| ((user: SharedUserType, data: Permissions[Key]['dataType']) => boolean); | ((user: SharedUserType, data: Permissions[Key]['dataType']) => boolean);