diff --git a/.github/ISSUE_TEMPLATE/01-bug-report.yml b/.github/ISSUE_TEMPLATE/01-bug-report.yml
new file mode 100644
index 00000000..2a92e7b6
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/01-bug-report.yml
@@ -0,0 +1,38 @@
+---
+name: 🐛 Bug Report
+description: Create a report to help us improve
+title: "[Bug]: "
+labels:
+ - "bug"
+
+body:
+ - type: markdown
+ attributes:
+ value: |
+ **Thanks :heart: for taking the time to fill out this bug report!**
+ We kindly ask that you search to see if an issue [already exists](https://github.com/wg-easy/wg-easy/issues?q=is%3Aissue+sort%3Acreated-desc+) for the bug you encountered.
+
+ - type: textarea
+ id: what-happened
+ attributes:
+ label: Describe the bug
+ placeholder: Tell us what you see!
+ value: "A bug happened!"
+ validations:
+ required: true
+
+ - type: textarea
+ id: what-should-happen
+ attributes:
+ label: Expected behavior
+ placeholder: Tell us what you expected!
+ value: "Work just fine!"
+ validations:
+ required: true
+
+ - type: textarea
+ id: logs
+ attributes:
+ label: Relevant log output
+ description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
+ render: shell
diff --git a/.github/ISSUE_TEMPLATE/02-feature-request.yml b/.github/ISSUE_TEMPLATE/02-feature-request.yml
new file mode 100644
index 00000000..d23b5f6c
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/02-feature-request.yml
@@ -0,0 +1,48 @@
+---
+name: 🛠️ Feature Request
+description: Suggest an idea to help us improve
+title: "[Feat]: "
+labels:
+ - "enhancement"
+
+body:
+ - type: markdown
+ attributes:
+ value: |
+ **Thanks :heart: for taking the time to fill out this feature request report!**
+ We kindly ask that you search to see if an issue [already exists](https://github.com/wg-easy/wg-easy/issues?q=is%3Aissue+sort%3Acreated-desc+) for your feature.
+
+ We are also happy to accept contributions from our users. For more details see [here](https://github.com/wg-easy/wg-easy/blob/master/contributing.md).
+
+ - type: textarea
+ attributes:
+ label: Description
+ description: |
+ A clear and concise description of the feature you're interested in.
+ validations:
+ required: true
+
+ - type: textarea
+ attributes:
+ label: Suggested Solution
+ description: |
+ Describe the solution you'd like. A clear and concise description of what you want to happen.
+ validations:
+ required: true
+
+ - type: textarea
+ attributes:
+ label: Alternatives
+ description: |
+ Describe alternatives you've considered.
+ A clear and concise description of any alternative solutions or features you've considered.
+ validations:
+ required: false
+
+ - type: textarea
+ attributes:
+ label: Additional Context
+ description: |
+ Add any other context about the problem here.
+ validations:
+ required: false
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
deleted file mode 100644
index 89daa669..00000000
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ /dev/null
@@ -1,38 +0,0 @@
----
-name: Bug report
-about: Create a report to help us improve
-title: ''
-labels: ''
-assignees: ''
-
----
-
-**Describe the bug**
-A clear and concise description of what the bug is.
-
-**To Reproduce**
-Steps to reproduce the behavior:
-1. Go to '...'
-2. Click on '....'
-3. Scroll down to '....'
-4. See error
-
-**Expected behavior**
-A clear and concise description of what you expected to happen.
-
-**Screenshots**
-If applicable, add screenshots to help explain your problem.
-
-**Desktop (please complete the following information):**
- - OS: [e.g. macOS 12.1]
- - Browser [e.g. chrome, safari]
- - Version [e.g. 22]
-
-**Smartphone (please complete the following information):**
- - Device: [e.g. iPhone6]
- - OS: [e.g. iOS 8.1]
- - Browser [e.g. stock browser, safari]
- - Version [e.g. 22]
-
-**Additional context**
-Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 00000000..421000eb
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,5 @@
+contact_links:
+ - name: Get Help
+ url: https://github.com/wg-easy/wg-easy/discussions/new?category=q-a
+ about: If you can't get something to work the way you expect, open a question in the discussions.
+blank_issues_enabled: false
\ No newline at end of file
diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE.md
similarity index 100%
rename from .github/PULL_REQUEST_TEMPLATE/pull_request_template.md
rename to .github/PULL_REQUEST_TEMPLATE.md
diff --git a/How_to_generate_an_bcrypt_hash.md b/How_to_generate_an_bcrypt_hash.md
index d868d23c..e77e3717 100644
--- a/How_to_generate_an_bcrypt_hash.md
+++ b/How_to_generate_an_bcrypt_hash.md
@@ -16,13 +16,21 @@ docker run ghcr.io/wg-easy/wg-easy wgpw YOUR_PASSWORD
PASSWORD_HASH='$2b$12$coPqCsPtcFO.Ab99xylBNOW4.Iu7OOA2/ZIboHN6/oyxca3MWo7fW' // literally YOUR_PASSWORD
```
-*Important* : make sure to enclose your password in single quotes when you run `docker run` command :
+**Important** : make sure to enclose your password in **single quotes** when you run `docker run` command :
```bash
-$ echo $2b$12$coPqCsPtcF
+$ echo $2b$12$coPqCsPtcF <-- not correct
b2
-$ echo "$2b$12$coPqCsPtcF"
+$ echo "$2b$12$coPqCsPtcF" <-- not correct
b2
-$ echo '$2b$12$coPqCsPtcF'
+$ echo '$2b$12$coPqCsPtcF' <-- correct
$2b$12$coPqCsPtcF
```
+
+**Important** : Please note: don't wrap the generated hash password in single quotes when you use `docker-compose.yml`. Instead, replace each `$` symbol with two `$$` symbols. For example:
+
+``` yaml
+- PASSWORD_HASH=$$2y$$10$$hBCoykrB95WSzuV4fafBzOHWKu9sbyVa34GJr8VV5R/pIelfEMYyG
+```
+
+This hash is for the password 'foobar123', obtained using the command `docker run ghcr.io/wg-easy/wg-easy wgpw foobar123` and then inserted an additional `$` before each existing `$` symbal.
diff --git a/README.md b/README.md
index 3cee52cb..199ae82a 100644
--- a/README.md
+++ b/README.md
@@ -24,6 +24,7 @@ You have found the easiest way to install & manage WireGuard on any Linux host!
* Automatic Light / Dark Mode
* Multilanguage Support
* UI_TRAFFIC_STATS (default off)
+* UI_SHOW_LINKS (default off)
## Requirements
@@ -99,28 +100,29 @@ Are you enjoying this project? [Buy Emile a beer!](https://github.com/sponsors/W
These options can be configured by setting environment variables using `-e KEY="VALUE"` in the `docker run` command.
-| Env | Default | Example | Description |
-| - | - |--------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `PORT` | `51821` | `6789` | TCP port for Web UI. |
-| `WEBUI_HOST` | `0.0.0.0` | `localhost` | IP address web UI binds to. |
-| `PASSWORD_HASH` | - | `$2y$05$Ci...` | When set, requires a password when logging in to the Web UI. See [How to generate an bcrypt hash.md]("https://github.com/wg-easy/wg-easy/blob/master/How_to_generate_an_bcrypt_hash.md") for know how generate the hash. |
-| `PASSWORD` (deprecated) | - | `foobar123` | When set, requires a password when logging in to the Web UI. *(Not used if `PASSWORD_HASH` is set)* |
-| `WG_HOST` | - | `vpn.myserver.com` | The public hostname of your VPN server. |
-| `WG_DEVICE` | `eth0` | `ens6f0` | Ethernet device the wireguard traffic should be forwarded through. |
-| `WG_PORT` | `51820` | `12345` | The public UDP port of your VPN server. WireGuard will listen on that (othwise default) inside the Docker container. |
-| `WG_CONFIG_PORT`| `51820` | `12345` | The UDP port used on [Home Assistant Plugin](https://github.com/adriy-be/homeassistant-addons-jdeath/tree/main/wgeasy)
-| `WG_MTU` | `null` | `1420` | The MTU the clients will use. Server uses default WG MTU. |
-| `WG_PERSISTENT_KEEPALIVE` | `0` | `25` | Value in seconds to keep the "connection" open. If this value is 0, then connections won't be kept alive. |
-| `WG_DEFAULT_ADDRESS` | `10.8.0.x` | `10.6.0.x` | Clients IP address range. |
-| `WG_DEFAULT_DNS` | `1.1.1.1` | `8.8.8.8, 8.8.4.4` | DNS server clients will use. If set to blank value, clients will not use any DNS. |
-| `WG_ALLOWED_IPS` | `0.0.0.0/0, ::/0` | `192.168.15.0/24, 10.0.1.0/24` | Allowed IPs clients will use. |
-| `WG_PRE_UP` | `...` | - | See [config.js](https://github.com/wg-easy/wg-easy/blob/master/src/config.js#L19) for the default value. |
-| `WG_POST_UP` | `...` | `iptables ...` | See [config.js](https://github.com/wg-easy/wg-easy/blob/master/src/config.js#L20) for the default value. |
-| `WG_PRE_DOWN` | `...` | - | See [config.js](https://github.com/wg-easy/wg-easy/blob/master/src/config.js#L27) for the default value. |
-| `WG_POST_DOWN` | `...` | `iptables ...` | See [config.js](https://github.com/wg-easy/wg-easy/blob/master/src/config.js#L28) for the default value. |
-| `LANG` | `en` | `de` | Web UI language (Supports: en, ua, ru, tr, no, pl, fr, de, ca, es, ko, vi, nl, is, pt, chs, cht, it, th, hi). |
-| `UI_TRAFFIC_STATS` | `false` | `true` | Enable detailed RX / TX client stats in Web UI |
-| `UI_CHART_TYPE` | `0` | `1` | UI_CHART_TYPE=0 # Charts disabled, UI_CHART_TYPE=1 # Line chart, UI_CHART_TYPE=2 # Area chart, UI_CHART_TYPE=3 # Bar chart |
+| Env | Default | Example | Description |
+| - | - | - |------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `PORT` | `51821` | `6789` | TCP port for Web UI. |
+| `WEBUI_HOST` | `0.0.0.0` | `localhost` | IP address web UI binds to. |
+| `PASSWORD_HASH` | - | `$2y$05$Ci...` | When set, requires a password when logging in to the Web UI. See [How to generate an bcrypt hash.md]("https://github.com/wg-easy/wg-easy/blob/master/How_to_generate_an_bcrypt_hash.md") for know how generate the hash. |
+| `WG_HOST` | - | `vpn.myserver.com` | The public hostname of your VPN server. |
+| `WG_DEVICE` | `eth0` | `ens6f0` | Ethernet device the wireguard traffic should be forwarded through. |
+| `WG_PORT` | `51820` | `12345` | The public UDP port of your VPN server. WireGuard will listen on that (othwise default) inside the Docker container. |
+| `WG_CONFIG_PORT`| `51820` | `12345` | The UDP port used on [Home Assistant Plugin](https://github.com/adriy-be/homeassistant-addons-jdeath/tree/main/wgeasy)
+| `WG_MTU` | `null` | `1420` | The MTU the clients will use. Server uses default WG MTU. |
+| `WG_PERSISTENT_KEEPALIVE` | `0` | `25` | Value in seconds to keep the "connection" open. If this value is 0, then connections won't be kept alive. |
+| `WG_DEFAULT_ADDRESS` | `10.8.0.x` | `10.6.0.x` | Clients IP address range. |
+| `WG_DEFAULT_DNS` | `1.1.1.1` | `8.8.8.8, 8.8.4.4` | DNS server clients will use. If set to blank value, clients will not use any DNS. |
+| `WG_ALLOWED_IPS` | `0.0.0.0/0, ::/0` | `192.168.15.0/24, 10.0.1.0/24` | Allowed IPs clients will use. |
+| `WG_PRE_UP` | `...` | - | See [config.js](https://github.com/wg-easy/wg-easy/blob/master/src/config.js#L19) for the default value. |
+| `WG_POST_UP` | `...` | `iptables ...` | See [config.js](https://github.com/wg-easy/wg-easy/blob/master/src/config.js#L20) for the default value. |
+| `WG_PRE_DOWN` | `...` | - | See [config.js](https://github.com/wg-easy/wg-easy/blob/master/src/config.js#L27) for the default value. |
+| `WG_POST_DOWN` | `...` | `iptables ...` | See [config.js](https://github.com/wg-easy/wg-easy/blob/master/src/config.js#L28) for the default value. |
+| `LANG` | `en` | `de` | Web UI language (Supports: en, ua, ru, tr, no, pl, fr, de, ca, es, ko, vi, nl, is, pt, chs, cht, it, th, hi). |
+| `UI_TRAFFIC_STATS` | `false` | `true` | Enable detailed RX / TX client stats in Web UI |
+| `UI_CHART_TYPE` | `0` | `1` | UI_CHART_TYPE=0 # Charts disabled, UI_CHART_TYPE=1 # Line chart, UI_CHART_TYPE=2 # Area chart, UI_CHART_TYPE=3 # Bar chart |
+| `UI_SHOW_LINKS` | `false` | `true` | Enable display of a short download link in Web UI |
+| `MAX_AGE` | `0` | `1440` | The maximum age of Web UI sessions in minutes. `0` means that the session will exist until the browser is closed. |
| `UI_ENABLE_SORT_CLIENTS` | `false` | `true` | Enable UI sort clients by name |
> If you change `WG_PORT`, make sure to also change the exposed port.
diff --git a/docker-compose.yml b/docker-compose.yml
index e63bccc3..379c0d54 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -27,6 +27,7 @@ services:
# - WG_POST_DOWN=echo "Post Down" > /etc/wireguard/post-down.txt
# - UI_TRAFFIC_STATS=true
# - UI_CHART_TYPE=0 # (0 Charts disabled, 1 # Line chart, 2 # Area chart, 3 # Bar chart)
+ # - UI_SHOW_LINKS=true
# - UI_ENABLE_SORT_CLIENTS=true
image: ghcr.io/wg-easy/wg-easy
@@ -40,7 +41,7 @@ services:
cap_add:
- NET_ADMIN
- SYS_MODULE
- # - NET_RAW # ⚠️ Uncomment if using Podman
+ # - NET_RAW # ⚠️ Uncomment if using Podman
sysctls:
- net.ipv4.ip_forward=1
- net.ipv4.conf.all.src_valid_mark=1
diff --git a/src/config.js b/src/config.js
index 1517cf51..d7a7831d 100644
--- a/src/config.js
+++ b/src/config.js
@@ -6,6 +6,7 @@ module.exports.RELEASE = version;
module.exports.PORT = process.env.PORT || '51821';
module.exports.WEBUI_HOST = process.env.WEBUI_HOST || '0.0.0.0';
module.exports.PASSWORD_HASH = process.env.PASSWORD_HASH;
+module.exports.MAX_AGE = parseInt(process.env.MAX_AGE, 10) * 1000 * 60 || 0;
module.exports.WG_PATH = process.env.WG_PATH || '/etc/wireguard/';
module.exports.WG_DEVICE = process.env.WG_DEVICE || 'eth0';
module.exports.WG_HOST = process.env.WG_HOST;
@@ -37,4 +38,5 @@ iptables -D FORWARD -o wg0 -j ACCEPT;
module.exports.LANG = process.env.LANG || 'en';
module.exports.UI_TRAFFIC_STATS = process.env.UI_TRAFFIC_STATS || 'false';
module.exports.UI_CHART_TYPE = process.env.UI_CHART_TYPE || 0;
+module.exports.UI_SHOW_LINKS = process.env.UI_SHOW_LINKS || 'false';
module.exports.UI_ENABLE_SORT_CLIENTS = process.env.UI_ENABLE_SORT_CLIENTS || 'false';
diff --git a/src/lib/Server.js b/src/lib/Server.js
index 323e9b0b..df419be0 100644
--- a/src/lib/Server.js
+++ b/src/lib/Server.js
@@ -29,9 +29,11 @@ const {
WEBUI_HOST,
RELEASE,
PASSWORD_HASH,
+ MAX_AGE,
LANG,
UI_TRAFFIC_STATS,
UI_CHART_TYPE,
+ UI_SHOW_LINKS,
UI_ENABLE_SORT_CLIENTS,
} = require('../config');
@@ -83,6 +85,11 @@ module.exports = class Server {
return `"${LANG}"`;
}))
+ .get('/api/remember-me', defineEventHandler((event) => {
+ setHeader(event, 'Content-Type', 'application/json');
+ return MAX_AGE > 0;
+ }))
+
.get('/api/ui-traffic-stats', defineEventHandler((event) => {
setHeader(event, 'Content-Type', 'application/json');
return `"${UI_TRAFFIC_STATS}"`;
@@ -93,9 +100,14 @@ module.exports = class Server {
return `"${UI_CHART_TYPE}"`;
}))
+ .get('/api/ui-show-links', defineEventHandler((event) => {
+ setHeader(event, 'Content-Type', 'application/json');
+ return `${UI_SHOW_LINKS}`;
+
.get('/api/ui-sort-clients', defineEventHandler((event) => {
setHeader(event, 'Content-Type', 'application/json');
return UI_ENABLE_SORT_CLIENTS;
+
}))
// Authentication
@@ -109,8 +121,19 @@ module.exports = class Server {
authenticated,
};
}))
+ .get('/:clientHash', defineEventHandler(async (event) => {
+ const clientHash = getRouterParam(event, 'clientHash');
+ const clients = await WireGuard.getClients();
+ const client = clients.find((client) => client.hash === clientHash);
+ if (!client) return;
+ const clientId = client.id;
+ const config = await WireGuard.getClientConfiguration({ clientId });
+ setHeader(event, 'Content-Disposition', `attachment; filename="${clientHash}.conf"`);
+ setHeader(event, 'Content-Type', 'text/plain');
+ return config;
+ }))
.post('/api/session', defineEventHandler(async (event) => {
- const { password } = await readBody(event);
+ const { password, remember } = await readBody(event);
if (!requiresPassword) {
// if no password is required, the API should never be called.
@@ -128,6 +151,9 @@ module.exports = class Server {
});
}
+ if (MAX_AGE && remember) {
+ event.node.req.session.cookie.maxAge = MAX_AGE;
+ }
event.node.req.session.authenticated = true;
event.node.req.session.save();
diff --git a/src/lib/WireGuard.js b/src/lib/WireGuard.js
index adf6ca95..95b8c9d1 100644
--- a/src/lib/WireGuard.js
+++ b/src/lib/WireGuard.js
@@ -5,6 +5,7 @@ const path = require('path');
const debug = require('debug')('WireGuard');
const crypto = require('node:crypto');
const QRCode = require('qrcode');
+const CRC32 = require('crc-32');
const Util = require('./Util');
const ServerError = require('./ServerError');
@@ -147,6 +148,7 @@ ${client.preSharedKey ? `PresharedKey = ${client.preSharedKey}\n` : ''
createdAt: new Date(client.createdAt),
updatedAt: new Date(client.updatedAt),
allowedIPs: client.allowedIPs,
+ hash: Math.abs(CRC32.str(clientId)).toString(16),
downloadableConfig: 'privateKey' in client,
persistentKeepalive: null,
latestHandshakeAt: null,
diff --git a/src/package-lock.json b/src/package-lock.json
index f4c752ee..b1ff1375 100644
--- a/src/package-lock.json
+++ b/src/package-lock.json
@@ -10,15 +10,16 @@
"license": "CC BY-NC-SA 4.0",
"dependencies": {
"bcryptjs": "^2.4.3",
+ "crc-32": "^1.2.2",
"debug": "^4.3.6",
"express-session": "^1.18.0",
"h3": "^1.12.0",
- "qrcode": "^1.5.3"
+ "qrcode": "^1.5.4"
},
"devDependencies": {
"eslint-config-athom": "^3.1.3",
"nodemon": "^3.1.4",
- "tailwindcss": "^3.4.7"
+ "tailwindcss": "^3.4.10"
},
"engines": {
"node": ">=18"
@@ -1209,6 +1210,18 @@
"integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==",
"license": "MIT"
},
+ "node_modules/crc-32": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
+ "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
+ "license": "Apache-2.0",
+ "bin": {
+ "crc32": "bin/crc32.njs"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -1456,12 +1469,6 @@
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"license": "MIT"
},
- "node_modules/encode-utf8": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz",
- "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==",
- "license": "MIT"
- },
"node_modules/enquirer": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz",
@@ -2312,9 +2319,9 @@
}
},
"node_modules/foreground-child": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz",
- "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==",
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
+ "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
"dev": true,
"license": "ISC",
"dependencies": {
@@ -2664,9 +2671,9 @@
}
},
"node_modules/ignore": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
- "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
"dev": true,
"license": "MIT",
"engines": {
@@ -3769,9 +3776,9 @@
}
},
"node_modules/postcss": {
- "version": "8.4.40",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.40.tgz",
- "integrity": "sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==",
+ "version": "8.4.41",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz",
+ "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==",
"dev": true,
"funding": [
{
@@ -3911,9 +3918,9 @@
}
},
"node_modules/postcss-selector-parser": {
- "version": "6.1.1",
- "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz",
- "integrity": "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==",
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
+ "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3972,13 +3979,12 @@
}
},
"node_modules/qrcode": {
- "version": "1.5.3",
- "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz",
- "integrity": "sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==",
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz",
+ "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==",
"license": "MIT",
"dependencies": {
"dijkstrajs": "^1.0.1",
- "encode-utf8": "^1.0.3",
"pngjs": "^5.0.0",
"yargs": "^15.3.1"
},
@@ -4694,9 +4700,9 @@
"peer": true
},
"node_modules/tailwindcss": {
- "version": "3.4.7",
- "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.7.tgz",
- "integrity": "sha512-rxWZbe87YJb4OcSopb7up2Ba4U82BoiSGUdoDr3Ydrg9ckxFS/YWsvhN323GMcddgU65QRy7JndC7ahhInhvlQ==",
+ "version": "3.4.10",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.10.tgz",
+ "integrity": "sha512-KWZkVPm7yJRhdu4SRSl9d4AK2wM3a50UsvgHZO7xY77NQr2V+fIrEuoDGQcbvswWvFGbS2f6e+jC/6WJm1Dl0w==",
"dev": true,
"license": "MIT",
"dependencies": {
diff --git a/src/package.json b/src/package.json
index 6750366e..c90bbc9f 100644
--- a/src/package.json
+++ b/src/package.json
@@ -19,12 +19,13 @@
"debug": "^4.3.6",
"express-session": "^1.18.0",
"h3": "^1.12.0",
- "qrcode": "^1.5.3"
+ "qrcode": "^1.5.4",
+ "crc-32": "^1.2.2"
},
"devDependencies": {
"eslint-config-athom": "^3.1.3",
"nodemon": "^3.1.4",
- "tailwindcss": "^3.4.7"
+ "tailwindcss": "^3.4.10"
},
"nodemonConfig": {
"ignore": [
diff --git a/src/www/css/app.css b/src/www/css/app.css
index 08271631..ae3fc3c3 100644
--- a/src/www/css/app.css
+++ b/src/www/css/app.css
@@ -1,5 +1,5 @@
/*
-! tailwindcss v3.4.7 | MIT License | https://tailwindcss.com
+! tailwindcss v3.4.10 | MIT License | https://tailwindcss.com
*/
/*
diff --git a/src/www/index.html b/src/www/index.html
index f8f5ded0..3dd7030d 100644
--- a/src/www/index.html
+++ b/src/www/index.html
@@ -10,6 +10,7 @@
+