Browse Source

Chore: Improvments (#1697)

* update packages

* fix tab issues

* consistent imports

* use eslint module

* update date

* improve docs

* update docs

* format

* fix docs, fix cookie
pull/1700/head
Bernd Storath 5 months ago
committed by GitHub
parent
commit
378938f73a
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 13
      .github/workflows/deploy.yml
  2. 4
      docker-compose.yml
  3. 4
      docs/content/config/advanced/optional-config.md
  4. 5
      docs/content/config/advanced/podman.md
  5. 47
      docs/content/config/migrate/from-14-to-15.md
  6. 8
      docs/content/contributing/general.md
  7. 17
      docs/content/contributing/issues-and-pull-requests.md
  8. 52
      docs/content/examples/tutorials/basic-installation.md
  9. 5
      docs/content/examples/tutorials/dockerless.md
  10. 96
      docs/content/examples/tutorials/podman.md
  11. 3
      docs/content/index.md
  12. 51
      docs/content/usage.md
  13. 8
      docs/mkdocs.yml
  14. 5
      package.json
  15. 2
      src/app/components/Ui/UserMenu.vue
  16. 1
      src/app/pages/admin.vue
  17. 2
      src/app/pages/setup/1.vue
  18. 4
      src/app/pages/setup/3.vue
  19. 8
      src/app/pages/setup/4.vue
  20. 2
      src/app/pages/setup/success.vue
  21. 13
      src/eslint.config.mjs
  22. 3
      src/nuxt.config.ts
  23. 36
      src/package.json
  24. 3271
      src/pnpm-lock.yaml
  25. 4
      src/server/database/repositories/client/service.ts
  26. 2
      src/server/database/repositories/general/service.ts
  27. 2
      src/server/database/repositories/general/types.ts
  28. 2
      src/server/database/repositories/hooks/service.ts
  29. 2
      src/server/database/repositories/hooks/types.ts
  30. 4
      src/server/database/repositories/interface/service.ts
  31. 2
      src/server/database/repositories/interface/types.ts
  32. 4
      src/server/database/repositories/oneTimeLink/service.ts
  33. 2
      src/server/database/repositories/oneTimeLink/types.ts
  34. 2
      src/server/database/repositories/user/service.ts
  35. 2
      src/server/database/repositories/user/types.ts
  36. 2
      src/server/database/repositories/userConfig/service.ts
  37. 2
      src/server/database/repositories/userConfig/types.ts
  38. 13
      src/server/utils/session.ts
  39. 2
      src/server/utils/wgHelper.ts

13
.github/workflows/deploy.yml

@ -71,3 +71,16 @@ jobs:
cd docs cd docs
git fetch origin gh-pages --depth=1 git fetch origin gh-pages --depth=1
mike deploy --push --update-aliases ${{ github.ref_name }} latest mike deploy --push --update-aliases ${{ github.ref_name }} latest
# Extract version numbers (remove 'v' prefix)
DOCS_VERSION=${GITHUB_REF#refs/tags/} # e.g. v1.2.3 or v1.2.3-beta
MINOR_VERSION=$(echo $DOCS_VERSION | cut -d. -f1,2) # e.g. v1.2
# Check if it's a stable release (only numbers, no '-')
if [[ "$DOCS_VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Stable release detected: $DOCS_VERSION"
mike deploy --push --update-aliases $MINOR_VERSION latest
else
echo "Prerelease detected: $DOCS_VERSION"
mike deploy --push --update-aliases Pre-release
fi

4
docker-compose.yml

@ -3,9 +3,9 @@ volumes:
services: services:
wg-easy: wg-easy:
environment: #environment:
- PORT=51821
# Optional: # Optional:
# - PORT=51821
# - HOST=0.0.0.0 # - HOST=0.0.0.0
image: ghcr.io/wg-easy/wg-easy image: ghcr.io/wg-easy/wg-easy

4
docs/content/config/advanced/optional-config.md

@ -1,3 +1,5 @@
--- ---
title: 'Optional Configuration' title: Optional Configuration
--- ---
TODO

5
docs/content/config/advanced/podman.md

@ -1,5 +0,0 @@
---
title: Podman
---
TODO

47
docs/content/config/migrate/from-14-to-15.md

@ -0,0 +1,47 @@
---
title: Migrate from v14 to v15
---
This guide will help you migrate from `v14` to version `v15` of `wg-easy`.
## 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.
## Migration
### Backup
Before you start the migration, make sure to backup your existing configuration files.
Go into the Web Ui and click the Backup button, this should download a `wg0.json` file.
Or download the `wg0.json` file from your container volume to your pc.
You will need this file for the migration
### Remove old container
1. Stop the running container
If you are using `docker run`
```shell
docker stop wg-easy
```
If you are using `docker-compose`
```shell
docker-compose down
```
### Start new container
Follow the instructions in the [Getting Started](../../usage.md) or [Basic Installation](../../examples/tutorials/basic-installation.md) guide to start the new container.
In the setup wizard, select that you already already have a configuration file and upload the `wg0.json` file you downloaded in the backup step.
### Done
You have now successfully migrated to `v15` of `wg-easy`.

8
docs/content/contributing/general.md

@ -1,5 +1,5 @@
--- ---
title: 'General Information' title: General Information
--- ---
## Coding Style ## Coding Style
@ -14,10 +14,10 @@ When refactoring, writing or altering files, adhere to these rules:
Make sure to select `nightly` in the dropdown menu at the top. Navigate to the page you would like to edit and click the edit button in the top right. This allows you to make changes and create a pull-request. Make sure to select `nightly` in the dropdown menu at the top. Navigate to the page you would like to edit and click the edit button in the top right. This allows you to make changes and create a pull-request.
Alternatively you can make the changes locally. For that you'll need to have Docker installed. Navigate into the `docs/` directory. Then run: Alternatively you can make the changes locally. For that you'll need to have Docker installed. Run
```sh ```sh
docker run --rm -it -p 8000:8000 -v "${PWD}:/docs" squidfunk/mkdocs-material pnpm docs:serve
``` ```
This serves the documentation on your local machine on port `8000`. Each change will be hot-reloaded onto the page you view, just edit, save and look at the result. This serves the documentation on your local machine on port `8080`. Each change will be hot-reloaded onto the page you view, just edit, save and look at the result.

17
docs/content/contributing/issues-and-pull-requests.md

@ -1,20 +1,22 @@
--- ---
title: 'Issues and Pull Requests' title: Issues and Pull Requests
--- ---
This project is Open Source. That means that you can contribute on enhancements, bug fixing or improving the documentation. This project is Open Source. That means that you can contribute on enhancements, bug fixing or improving the documentation.
## Opening an Issue ## Opening an Issue
!!! attention /// note | Attention
**Before opening an issue**, read the [`README`][github-file-readme] carefully, study the docs for your version (maybe [latest][docs-latest]) and your search engine you trust. The issue tracker is not meant to be used for unrelated questions! **Before opening an issue**, read the [`README`][github-file-readme] carefully, study the docs for your version (maybe [latest][docs-latest]) and your search engine you trust. The issue tracker is not meant to be used for unrelated questions!
///
When opening an issue, please provide details use case to let the community reproduce your problem. When opening an issue, please provide details use case to let the community reproduce your problem.
!!! attention /// note | Attention
**Use the issue templates** to provide the necessary information. Issues which do not use these templates are not worked on and closed. **Use the issue templates** to provide the necessary information. Issues which do not use these templates are not worked on and closed.
///
By raising issues, I agree to these terms and I understand, that the rules set for the issue tracker will help both maintainers as well as everyone to find a solution. By raising issues, I agree to these terms and I understand, that the rules set for the issue tracker will help both maintainers as well as everyone to find a solution.
@ -34,18 +36,19 @@ When an option is marked with "not officially supported" / "unsupported", then s
## Pull Requests ## Pull Requests
!!! question "Motivation" /// question | Motivation
You want to add a feature? Feel free to start creating an issue explaining what you want to do and how you're thinking doing it. Other users may have the same need and collaboration may lead to better results. You want to add a feature? Feel free to start creating an issue explaining what you want to do and how you're thinking doing it. Other users may have the same need and collaboration may lead to better results.
///
### Submit a Pull-Request ### Submit a Pull-Request
The development workflow is the following: The development workflow is the following:
1. Fork the project and clone your fork with `git clone --recurse-submodules ...` or run `git submodule update --init --recursive` after you cloned your fork 1. Fork the project
2. Write the code that is needed :D 2. Write the code that is needed :D
5. Document your improvements if necessary 3. Document your improvements if necessary
6. [Commit][commit] (and [sign your commit][gpg]), push and create a pull-request to merge into `master`. Please **use the pull-request template** to provide a minimum of contextual information and make sure to meet the requirements of the checklist. 4. [Commit][commit] (and [sign your commit][gpg]), push and create a pull-request to merge into `master`. Please **use the pull-request template** to provide a minimum of contextual information and make sure to meet the requirements of the checklist.
Pull requests are automatically tested against the CI and will be reviewed when tests pass. When your changes are validated, your branch is merged. CI builds the new `:nightly` image every night and your changes will be includes in the next version release. Pull requests are automatically tested against the CI and will be reviewed when tests pass. When your changes are validated, your branch is merged. CI builds the new `:nightly` image every night and your changes will be includes in the next version release.

52
docs/content/examples/tutorials/basic-installation.md

@ -0,0 +1,52 @@
---
title: Basic Installation
---
<!-- TOOD: add docs for pihole, nginx, caddy, traefik -->
## Requirements
1. You need to have a host that you can manage
2. You need to have a domain name or a public IP address
3. You need a supported architecture (x86_64, arm64)
4. You need curl installed on your host
## Install Docker
Follow the Docs here: <https://docs.docker.com/engine/install/> and install Docker on your host.
## Install `wg-easy`
1. Create a directory for the configuration files (you can choose any directory you like):
```shell
DIR=/docker/wg-easy
sudo mkdir -p $DIR
```
2. Download docker compose file
```shell
sudo curl -o $URL/docker-compose.yml https://raw.githubusercontent.com/wg-easy/wg-easy/master/docker-compose.yml
```
3. Start `wg-easy`
```shell
sudo docker-compose -f $DIR/docker-compose.yml up -d
```
## Setup Firewall
If you are using a firewall, you need to open the following ports:
- UDP 51820 (WireGuard)
- TCP 51821 (Web UI)
These ports can be changed, so if you change them you have to update your firewall rules accordingly.
## Access the Web UI
Open your browser and navigate to `https://<your-domain>:51821` or `https://<your-ip>:51821`.
Follow the instructions to set up your WireGuard VPN.

5
docs/content/examples/tutorials/dockerless.md

@ -0,0 +1,5 @@
---
title: Without Docker
---
TODO

96
docs/content/examples/tutorials/podman.md

@ -0,0 +1,96 @@
---
title: Podman
---
This guide will show you how to run `wg-easy` with rootful Podman and nftables.
## Requirements
1. Podman installed with version 4.4 or higher
## Configuration
Create a Folder for the configuration files:
```shell
sudo mkdir -p /etc/containers/systemd/wg-easy
sudo mkdir -p /etc/containers/volumes/wg-easy
```
Create a file `/etc/containers/systemd/wg-easy/wg-easy.container` with the following content:
```ini
[Container]
ContainerName=wg-easy
Image=ghcr.io/wg-easy/wg-easy:latest
Volume=/etc/containers/volumes/wg-easy:/etc/wireguard:Z
Network=wg-easy.network
PublishPort=51820:51820/udp
PublishPort=51821:51821/tcp
AddCapability=NET_ADMIN
AddCapability=SYS_MODULE
AddCapability=NET_RAW
Sysctl=net.ipv4.ip_forward=1
Sysctl=net.ipv4.conf.all.src_valid_mark=1
Sysctl=net.ipv6.conf.all.disable_ipv6=0
Sysctl=net.ipv6.conf.all.forwarding=1
Sysctl=net.ipv6.conf.default.forwarding=1
[Install]
# this is used to start the container on boot
WantedBy=default.target
```
Create a file `/etc/containers/systemd/wg-easy/wg-easy.network` with the following content:
```ini
[Network]
NetworkName=wg-easy
IPv6=true
```
## Load Kernel Modules
You will need to load the following kernel modules
```txt
wireguard
nft_masq
```
Create a file `/etc/modules-load.d/wg-easy.conf` with the following content:
```txt
wireguard
nft_masq
```
## Start the Container
```shell
sudo systemctl daemon-reload
sudo systemctl start wg-easy
```
## Edit Hooks
In the Admin Panel of your WireGuard server, go to the `Hooks` tab and add the following hook:
1. PostUp
```shell
apk add nftables; nft add table inet wg_table; nft add chain inet wg_table postrouting { type nat hook postrouting priority 100 \; }; nft add rule inet wg_table postrouting ip saddr {{ipv4Cidr}} oifname {{device}} masquerade; nft add rule inet wg_table postrouting ip6 saddr {{ipv6Cidr}} oifname {{device}} masquerade; nft add chain inet wg_table input { type filter hook input priority 0 \; policy drop \; }; nft add rule inet wg_table input udp dport {{port}} accept; nft add chain inet wg_table forward { type filter hook forward priority 0 \; policy drop \; }; nft add rule inet wg_table forward iifname "wg0" accept; nft add rule inet wg_table forward oifname "wg0" accept;
```
2. PostDown
```shell
nft delete table inet wg_table
```
<!--
TODO: improve docs after better nftables support
TODO: fix accept web ui port
-->

3
docs/content/index.md

@ -6,9 +6,10 @@ hide:
# Welcome to the Documentation for `wg-easy` # Welcome to the Documentation for `wg-easy`
!!! info "This Documentation is Versioned" /// info | This Documentation is Versioned
**Make sure** to select the correct version of this documentation! It should match the version of the image you are using. The default version corresponds to the `:latest` image tag - [the most recent stable release][docs-tagging]. **Make sure** to select the correct version of this documentation! It should match the version of the image you are using. The default version corresponds to the `:latest` image tag - [the most recent stable release][docs-tagging].
///
This documentation provides you not only with the basic setup and configuration of wg-easy but also with advanced configuration, elaborate usage scenarios, detailed examples, hints and more. This documentation provides you not only with the basic setup and configuration of wg-easy but also with advanced configuration, elaborate usage scenarios, detailed examples, hints and more.

51
docs/content/usage.md

@ -4,32 +4,32 @@ hide:
- navigation - navigation
--- ---
This page explains how to get started with wg-easy. The guide uses Docker Compose as a reference. In our examples, a volume mounts the named volume [`etc_wireguard`][docs::dms-volumes-config] to `/etc/wireguard` inside the container. This page explains how to get started with wg-easy. The guide uses Docker Compose as a reference. In our examples, we mount the named volume `etc_wireguard` to `/etc/wireguard` inside the container.
[docs::dms-volumes-config]: ./config/advanced/optional-config.md#volumes-config
## Preliminary Steps ## Preliminary Steps
Before you can get started with deploying your own VPN, there are some requirements to be met: Before you can get started with deploying your own VPN, there are some requirements to be met:
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
3. You need a supported architecture (x86_64, arm64)
### Host Setup ### Host Setup
There are a few requirements for a suitable host system: There are a few requirements for a suitable host system:
TODO: Requirements 1. You need to have a container runtime installed
!!! note "About the Container Runtime" /// note | About the Container Runtime
On the host, you need to have a suitable container runtime (like _Docker_ or _Podman_) installed. We assume [_Docker Compose_][docker-compose] is [installed][docker-compose-installation]. We have aligned file names and configuration conventions with the latest [Docker Compose specification][docker-compose-specification]. On the host, you need to have a suitable container runtime (like _Docker_ or _Podman_) installed. We assume [_Docker Compose_][docker-compose] is [installed][docker-compose-installation]. We have aligned file names and configuration conventions with the latest [Docker Compose specification][docker-compose-specification].
If you're using podman, make sure to read the related [documentation][docs-podman]. If you're using podman, make sure to read the related [documentation][docs-podman].
///
[docker-compose]: https://docs.docker.com/compose/ [docker-compose]: https://docs.docker.com/compose/
[docker-compose-installation]: https://docs.docker.com/compose/install/ [docker-compose-installation]: https://docs.docker.com/compose/install/
[docker-compose-specification]: https://docs.docker.com/compose/compose-file/ [docker-compose-specification]: https://docs.docker.com/compose/compose-file/
[docs-podman]: ./config/advanced/podman.md [docs-podman]: ./examples/tutorials/podman.md
## Deploying the Actual Image ## Deploying the Actual Image
@ -37,39 +37,52 @@ TODO: Requirements
To understand which tags you should use, read this section carefully. [Our CI][github-ci] will automatically build, test and push new images to the following container registry: To understand which tags you should use, read this section carefully. [Our CI][github-ci] will automatically build, test and push new images to the following container registry:
2. GitHub Container Registry ([`ghcr.io/wg-easy/wg-easy`][ghcr-image]) 1. GitHub Container Registry ([`ghcr.io/wg-easy/wg-easy`][ghcr-image])
All workflows are using the tagging convention listed below. It is subsequently applied to all images. All workflows are using the tagging convention listed below. It is subsequently applied to all images.
| Event | Image Tags | | Event | Image Tags |
|-------------------------|-------------------------------| | ----------------------- | ----------------------------- |
| `cron` on `master` | `nightly` | | `cron` on `master` | `nightly` |
| `push` a tag (`v1.2.3`) | `1.2.3`, `1.2`, `1`, `latest` | | `push` a tag (`v1.2.3`) | `1.2.3`, `1.2`, `1`, `latest` |
When publishing a tag we follow the [Semantic Versioning][semver] specification. The `latest` tag is always pointing to the latest stable release. If you want to avoid breaking changes, use the major version tag (e.g. `15`).
[github-ci]: https://github.com/wg-easy/wg-easy/actions [github-ci]: https://github.com/wg-easy/wg-easy/actions
[ghcr-image]: https://github.com/wg-easy/wg-easy/pkgs/container/wg-easy [ghcr-image]: https://github.com/wg-easy/wg-easy/pkgs/container/wg-easy
[semver]: https://semver.org/
### Get All Files ### Get All Files
Issue the following command to acquire the necessary file: Issue the following command to acquire the necessary file:
``` BASH ```shell
wget "https://raw.githubusercontent.com/wg-easy/wg-easy/master/docker-compose.yml" wget "https://raw.githubusercontent.com/wg-easy/wg-easy/master/docker-compose.yml"
``` ```
### Configuration Steps ### Start the Container
1. First edit `docker-compose.yml` to your liking To start the container, issue the following command:
2. Then configure the everything in the UI
### Get Up and Running ```shell
sudo docker compose up -d
```
!!! danger "Using the Correct Commands For Stopping and Starting DMS" ### Configuration Steps
**Use `docker compose up / down`, not `docker compose start / stop`**. Otherwise, the container is not properly destroyed and you may experience problems during startup because of inconsistent state. Now follow the setup process in your web browser
Using `Ctrl+C` **is not supported either**! ### Stopping the Container
**That's it! It really is that easy**. To stop the container, issue the following command:
```shell
sudo docker compose down
```
/// danger | Using the Correct Commands For Stopping and Starting wg-easy
**Use `sudo docker compose up / down`, not `sudo docker compose start / stop`**. Otherwise, the container is not properly destroyed and you may experience problems during startup because of inconsistent state.
///
**That's it! It really is that easy**.

8
docs/mkdocs.yml

@ -53,7 +53,13 @@ markdown_extensions:
anchorlink: true anchorlink: true
- abbr - abbr
- attr_list - attr_list
- admonition - pymdownx.blocks.admonition:
types:
- danger
- note
- info
- question
- warning
- pymdownx.details - pymdownx.details
- pymdownx.superfences: - pymdownx.superfences:
custom_fences: custom_fences:

5
package.json

@ -3,7 +3,8 @@
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "docker compose -f docker-compose.dev.yml up --build", "dev": "docker compose -f docker-compose.dev.yml up --build",
"build": "docker build -t wg-easy ." "build": "docker build -t wg-easy .",
"docs:preview": "docker run --rm -it -p 8080:8080 -v ./docs:/docs squidfunk/mkdocs-material serve -a 0.0.0.0:8080"
}, },
"packageManager": "pnpm@10.2.0" "packageManager": "pnpm@10.5.2"
} }

2
src/app/components/Ui/UserMenu.vue

@ -17,8 +17,10 @@
class="z-10 w-44 divide-y divide-gray-100 rounded-lg bg-white text-gray-700 shadow dark:divide-neutral-800 dark:bg-neutral-700 dark:text-gray-200" class="z-10 w-44 divide-y divide-gray-100 rounded-lg bg-white text-gray-700 shadow dark:divide-neutral-800 dark:bg-neutral-700 dark:text-gray-200"
> >
<DropdownMenuItem> <DropdownMenuItem>
<div class="px-4 py-2">
<div class="truncate">{{ authStore.userData?.name }}</div> <div class="truncate">{{ authStore.userData?.name }}</div>
<div class="truncate">@{{ authStore.userData?.username }}</div> <div class="truncate">@{{ authStore.userData?.username }}</div>
</div>
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem> <DropdownMenuItem>
<NuxtLink <NuxtLink

1
src/app/pages/admin.vue

@ -15,6 +15,7 @@
:to="`/admin/${item.id}`" :to="`/admin/${item.id}`"
> >
<BaseButton <BaseButton
as="span"
class="w-full cursor-pointer rounded p-2 font-medium transition-colors duration-200 hover:bg-red-800 dark:text-neutral-200" class="w-full cursor-pointer rounded p-2 font-medium transition-colors duration-200 hover:bg-red-800 dark:text-neutral-200"
> >
{{ item.name }} {{ item.name }}

2
src/app/pages/setup/1.vue

@ -4,7 +4,7 @@
{{ $t('setup.welcomeDesc') }} {{ $t('setup.welcomeDesc') }}
</p> </p>
<NuxtLink to="/setup/2"> <NuxtLink to="/setup/2">
<BaseButton>{{ $t('general.continue') }}</BaseButton> <BaseButton as="span">{{ $t('general.continue') }}</BaseButton>
</NuxtLink> </NuxtLink>
</div> </div>
</template> </template>

4
src/app/pages/setup/3.vue

@ -5,10 +5,10 @@
</p> </p>
<div class="mb-8 flex justify-center"> <div class="mb-8 flex justify-center">
<NuxtLink to="/setup/4"> <NuxtLink to="/setup/4">
<BaseButton>{{ $t('general.no') }}</BaseButton> <BaseButton as="span">{{ $t('general.no') }}</BaseButton>
</NuxtLink> </NuxtLink>
<NuxtLink to="/setup/migrate"> <NuxtLink to="/setup/migrate">
<BaseButton>{{ $t('general.yes') }}</BaseButton> <BaseButton as="span">{{ $t('general.yes') }}</BaseButton>
</NuxtLink> </NuxtLink>
</div> </div>
</div> </div>

8
src/app/pages/setup/4.vue

@ -8,18 +8,12 @@
<FormNullTextField <FormNullTextField
id="host" id="host"
v-model="host" v-model="host"
type="text"
:label="$t('general.host')" :label="$t('general.host')"
placeholder="vpn.example.com" placeholder="vpn.example.com"
/> />
</div> </div>
<div class="flex flex-col"> <div class="flex flex-col">
<FormNumberField <FormNumberField id="port" v-model="port" :label="$t('general.port')" />
id="port"
v-model="port"
type="number"
:label="$t('general.port')"
/>
</div> </div>
<div> <div>
<BaseButton @click="submit">{{ $t('general.continue') }}</BaseButton> <BaseButton @click="submit">{{ $t('general.continue') }}</BaseButton>

2
src/app/pages/setup/success.vue

@ -2,7 +2,7 @@
<div> <div>
<p>{{ $t('setup.successful') }}</p> <p>{{ $t('setup.successful') }}</p>
<NuxtLink to="/login"> <NuxtLink to="/login">
<BaseButton>{{ $t('login.signIn') }}</BaseButton> <BaseButton as="span">{{ $t('login.signIn') }}</BaseButton>
</NuxtLink> </NuxtLink>
</div> </div>
</template> </template>

13
src/eslint.config.mjs

@ -1,6 +1,11 @@
import { createConfigForNuxt } from '@nuxt/eslint-config/flat';
import eslintConfigPrettier from 'eslint-config-prettier'; import eslintConfigPrettier from 'eslint-config-prettier';
import withNuxt from './.nuxt/eslint.config.mjs';
export default createConfigForNuxt().append(eslintConfigPrettier); export default withNuxt([
{
// TODO: add typescript-eslint, import/order, ban raw defineEventHandler rules: {
'import/order': 'warn',
},
},
eslintConfigPrettier,
]);

3
src/nuxt.config.ts

@ -5,7 +5,7 @@ export default defineNuxtConfig({
future: { future: {
compatibilityVersion: 4, compatibilityVersion: 4,
}, },
compatibilityDate: '2024-04-03', compatibilityDate: '2025-02-04',
devtools: { enabled: true }, devtools: { enabled: true },
modules: [ modules: [
'@nuxtjs/i18n', '@nuxtjs/i18n',
@ -13,6 +13,7 @@ export default defineNuxtConfig({
'@pinia/nuxt', '@pinia/nuxt',
'@eschricht/nuxt-color-mode', '@eschricht/nuxt-color-mode',
'radix-vue/nuxt', 'radix-vue/nuxt',
'@nuxt/eslint',
], ],
colorMode: { colorMode: {
preference: 'system', preference: 'system',

36
src/package.json

@ -20,45 +20,45 @@
"dependencies": { "dependencies": {
"@eschricht/nuxt-color-mode": "^1.1.5", "@eschricht/nuxt-color-mode": "^1.1.5",
"@libsql/client": "^0.14.0", "@libsql/client": "^0.14.0",
"@nuxtjs/i18n": "^9.1.5", "@nuxtjs/i18n": "^9.2.1",
"@nuxtjs/tailwindcss": "^6.13.1", "@nuxtjs/tailwindcss": "^6.13.1",
"@pinia/nuxt": "^0.9.0", "@pinia/nuxt": "^0.10.1",
"@tailwindcss/forms": "^0.5.10", "@tailwindcss/forms": "^0.5.10",
"apexcharts": "^4.4.0", "apexcharts": "^4.5.0",
"argon2": "^0.41.1", "argon2": "^0.41.1",
"basic-auth": "^2.0.1", "basic-auth": "^2.0.1",
"cidr-tools": "^11.0.2", "cidr-tools": "^11.0.3",
"crc-32": "^1.2.2", "crc-32": "^1.2.2",
"debug": "^4.4.0", "debug": "^4.4.0",
"drizzle-orm": "^0.39.1", "drizzle-orm": "^0.40.0",
"ip-bigint": "^8.2.0", "ip-bigint": "^8.2.1",
"is-cidr": "^5.1.0", "is-cidr": "^5.1.1",
"is-ip": "^5.0.1", "is-ip": "^5.0.1",
"js-sha256": "^0.11.0", "js-sha256": "^0.11.0",
"lowdb": "^7.0.1", "lowdb": "^7.0.1",
"nuxt": "^3.15.4", "nuxt": "^3.15.4",
"pinia": "^2.3.1", "pinia": "^3.0.1",
"qrcode": "^1.5.4", "qrcode": "^1.5.4",
"radix-vue": "^1.9.13", "radix-vue": "^1.9.17",
"semver": "^7.7.1", "semver": "^7.7.1",
"tailwindcss": "^3.4.17", "tailwindcss": "^3.4.17",
"timeago.js": "^4.0.2", "timeago.js": "^4.0.2",
"vue": "latest", "vue": "latest",
"vue3-apexcharts": "^1.8.0", "vue3-apexcharts": "^1.8.0",
"zod": "^3.24.1" "zod": "^3.24.2"
}, },
"devDependencies": { "devDependencies": {
"@nuxt/eslint-config": "^1.0.0", "@nuxt/eslint": "1.1.0",
"@types/debug": "^4.1.12", "@types/debug": "^4.1.12",
"@types/qrcode": "^1.5.5", "@types/qrcode": "^1.5.5",
"@types/semver": "^7.5.8", "@types/semver": "^7.5.8",
"drizzle-kit": "^0.30.4", "drizzle-kit": "^0.30.5",
"eslint": "^9.19.0", "eslint": "^9.21.0",
"eslint-config-prettier": "^10.0.1", "eslint-config-prettier": "^10.0.2",
"prettier": "^3.4.2", "prettier": "^3.5.3",
"prettier-plugin-tailwindcss": "^0.6.11", "prettier-plugin-tailwindcss": "^0.6.11",
"typescript": "^5.7.3", "typescript": "^5.8.2",
"vue-tsc": "^2.2.0" "vue-tsc": "^2.2.8"
}, },
"packageManager": "pnpm@10.2.0" "packageManager": "pnpm@10.5.2"
} }

3271
src/pnpm-lock.yaml

File diff suppressed because it is too large

4
src/server/database/repositories/client/service.ts

@ -1,13 +1,13 @@
import type { DBType } from '#db/sqlite';
import { eq, sql } from 'drizzle-orm'; import { eq, sql } from 'drizzle-orm';
import { parseCidr } from 'cidr-tools';
import { client } from './schema'; import { client } from './schema';
import type { import type {
ClientCreateFromExistingType, ClientCreateFromExistingType,
ClientCreateType, ClientCreateType,
UpdateClientType, UpdateClientType,
} from './types'; } from './types';
import type { DBType } from '#db/sqlite';
import { wgInterface, userConfig } from '#db/schema'; import { wgInterface, userConfig } from '#db/schema';
import { parseCidr } from 'cidr-tools';
function createPreparedStatement(db: DBType) { function createPreparedStatement(db: DBType) {
return { return {

2
src/server/database/repositories/general/service.ts

@ -1,7 +1,7 @@
import type { DBType } from '#db/sqlite';
import { sql } from 'drizzle-orm'; import { sql } from 'drizzle-orm';
import { general } from './schema'; import { general } from './schema';
import type { GeneralUpdateType } from './types'; import type { GeneralUpdateType } from './types';
import type { DBType } from '#db/sqlite';
function createPreparedStatement(db: DBType) { function createPreparedStatement(db: DBType) {
return { return {

2
src/server/database/repositories/general/types.ts

@ -1,6 +1,6 @@
import type { InferSelectModel } from 'drizzle-orm'; import type { InferSelectModel } from 'drizzle-orm';
import type { general } from './schema';
import z from 'zod'; import z from 'zod';
import type { general } from './schema';
export type GeneralType = InferSelectModel<typeof general>; export type GeneralType = InferSelectModel<typeof general>;

2
src/server/database/repositories/hooks/service.ts

@ -1,7 +1,7 @@
import type { DBType } from '#db/sqlite';
import { eq, sql } from 'drizzle-orm'; import { eq, sql } from 'drizzle-orm';
import { hooks } from './schema'; import { hooks } from './schema';
import type { HooksUpdateType } from './types'; import type { HooksUpdateType } from './types';
import type { DBType } from '#db/sqlite';
function createPreparedStatement(db: DBType) { function createPreparedStatement(db: DBType) {
return { return {

2
src/server/database/repositories/hooks/types.ts

@ -1,6 +1,6 @@
import type { InferSelectModel } from 'drizzle-orm'; import type { InferSelectModel } from 'drizzle-orm';
import type { hooks } from './schema';
import z from 'zod'; import z from 'zod';
import type { hooks } from './schema';
export type HooksType = InferSelectModel<typeof hooks>; export type HooksType = InferSelectModel<typeof hooks>;

4
src/server/database/repositories/interface/service.ts

@ -1,10 +1,10 @@
import type { DBType } from '#db/sqlite';
import isCidr from 'is-cidr'; import isCidr from 'is-cidr';
import { eq, sql } from 'drizzle-orm'; import { eq, sql } from 'drizzle-orm';
import { parseCidr } from 'cidr-tools';
import { wgInterface } from './schema'; import { wgInterface } from './schema';
import type { InterfaceCidrUpdateType, InterfaceUpdateType } from './types'; import type { InterfaceCidrUpdateType, InterfaceUpdateType } from './types';
import { client as clientSchema } from '#db/schema'; import { client as clientSchema } from '#db/schema';
import { parseCidr } from 'cidr-tools'; import type { DBType } from '#db/sqlite';
function createPreparedStatement(db: DBType) { function createPreparedStatement(db: DBType) {
return { return {

2
src/server/database/repositories/interface/types.ts

@ -1,6 +1,6 @@
import type { InferSelectModel } from 'drizzle-orm'; import type { InferSelectModel } from 'drizzle-orm';
import type { wgInterface } from './schema';
import z from 'zod'; import z from 'zod';
import type { wgInterface } from './schema';
export type InterfaceType = InferSelectModel<typeof wgInterface>; export type InterfaceType = InferSelectModel<typeof wgInterface>;

4
src/server/database/repositories/oneTimeLink/service.ts

@ -1,7 +1,7 @@
import type { DBType } from '#db/sqlite';
import { eq, sql } from 'drizzle-orm'; import { eq, sql } from 'drizzle-orm';
import { oneTimeLink } from './schema';
import CRC32 from 'crc-32'; import CRC32 from 'crc-32';
import { oneTimeLink } from './schema';
import type { DBType } from '#db/sqlite';
function createPreparedStatement(db: DBType) { function createPreparedStatement(db: DBType) {
return { return {

2
src/server/database/repositories/oneTimeLink/types.ts

@ -1,6 +1,6 @@
import type { InferSelectModel } from 'drizzle-orm'; import type { InferSelectModel } from 'drizzle-orm';
import type { oneTimeLink } from './schema';
import { z } from 'zod'; import { z } from 'zod';
import type { oneTimeLink } from './schema';
export type OneTimeLinkType = InferSelectModel<typeof oneTimeLink>; export type OneTimeLinkType = InferSelectModel<typeof oneTimeLink>;

2
src/server/database/repositories/user/service.ts

@ -1,6 +1,6 @@
import type { DBType } from '#db/sqlite';
import { eq, sql } from 'drizzle-orm'; import { eq, sql } from 'drizzle-orm';
import { user } from './schema'; import { user } from './schema';
import type { DBType } from '#db/sqlite';
function createPreparedStatement(db: DBType) { function createPreparedStatement(db: DBType) {
return { return {

2
src/server/database/repositories/user/types.ts

@ -1,6 +1,6 @@
import type { InferSelectModel } from 'drizzle-orm'; import type { InferSelectModel } from 'drizzle-orm';
import type { user } from './schema';
import z from 'zod'; import z from 'zod';
import type { user } from './schema';
export type UserType = InferSelectModel<typeof user>; export type UserType = InferSelectModel<typeof user>;

2
src/server/database/repositories/userConfig/service.ts

@ -1,7 +1,7 @@
import type { DBType } from '#db/sqlite';
import { eq, sql } from 'drizzle-orm'; import { eq, sql } from 'drizzle-orm';
import { userConfig } from './schema'; import { userConfig } from './schema';
import type { UserConfigUpdateType } from './types'; import type { UserConfigUpdateType } from './types';
import type { DBType } from '#db/sqlite';
function createPreparedStatement(db: DBType) { function createPreparedStatement(db: DBType) {
return { return {

2
src/server/database/repositories/userConfig/types.ts

@ -1,6 +1,6 @@
import type { InferSelectModel } from 'drizzle-orm'; import type { InferSelectModel } from 'drizzle-orm';
import type { userConfig } from './schema';
import z from 'zod'; import z from 'zod';
import type { userConfig } from './schema';
export type UserConfigType = InferSelectModel<typeof userConfig>; export type UserConfigType = InferSelectModel<typeof userConfig>;

13
src/server/utils/session.ts

@ -7,12 +7,19 @@ export type WGSession = Partial<{
const name = 'wg-easy'; const name = 'wg-easy';
// TODO: don't set secure to false by default
export async function useWGSession(event: H3Event, rememberMe = false) { export async function useWGSession(event: H3Event, rememberMe = false) {
const sessionConfig = await Database.general.getSessionConfig(); const sessionConfig = await Database.general.getSessionConfig();
return useSession<WGSession>(event, { return useSession<WGSession>(event, {
password: sessionConfig.sessionPassword, password: sessionConfig.sessionPassword,
name, name,
cookie: { maxAge: rememberMe ? sessionConfig.sessionTimeout : undefined }, // TODO: add session expiration
// maxAge: undefined
cookie: {
maxAge: rememberMe ? sessionConfig.sessionTimeout : undefined,
secure: false,
},
}); });
} }
@ -21,7 +28,9 @@ export async function getWGSession(event: H3Event) {
return getSession<WGSession>(event, { return getSession<WGSession>(event, {
password: sessionConfig.sessionPassword, password: sessionConfig.sessionPassword,
name, name,
cookie: {}, cookie: {
secure: false,
},
}); });
} }

2
src/server/utils/wgHelper.ts

@ -1,7 +1,7 @@
import { parseCidr } from 'cidr-tools'; import { parseCidr } from 'cidr-tools';
import { stringifyIp } from 'ip-bigint';
import type { ClientType } from '#db/repositories/client/types'; import type { ClientType } from '#db/repositories/client/types';
import type { InterfaceType } from '#db/repositories/interface/types'; import type { InterfaceType } from '#db/repositories/interface/types';
import { stringifyIp } from 'ip-bigint';
import type { UserConfigType } from '#db/repositories/userConfig/types'; import type { UserConfigType } from '#db/repositories/userConfig/types';
import type { HooksType } from '#db/repositories/hooks/types'; import type { HooksType } from '#db/repositories/hooks/types';

Loading…
Cancel
Save