Refactor: Standardize units to GB/MB, fix Dashboard live traffic aggregation, and optimize WireGuard client layout with expanded actions.
This commit is contained in:
parent
b77da8e6de
commit
090894021a
13 changed files with 236 additions and 591 deletions
4
.dockerignore
Normal file
4
.dockerignore
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
node_modules/
|
||||
frontend/node_modules/
|
||||
backend/node_modules/
|
||||
dist/
|
||||
|
|
@ -29,9 +29,13 @@ const internalWireguard = {
|
|||
async getOrCreateInterface(knex) {
|
||||
let iface = await knex("wg_interface").first();
|
||||
if (!iface) {
|
||||
const privateKey = await wgHelpers.generatePrivateKey();
|
||||
const publicKey = await wgHelpers.getPublicKey(privateKey);
|
||||
// Seed a default config if it doesn't exist
|
||||
const insertData = {
|
||||
name: "wg0",
|
||||
private_key: privateKey,
|
||||
public_key: publicKey,
|
||||
listen_port: 51820,
|
||||
ipv4_cidr: "10.0.0.1/24",
|
||||
mtu: 1420,
|
||||
|
|
|
|||
|
|
@ -39,13 +39,9 @@ router.get("/dashboard", async (req, res, next) => {
|
|||
try {
|
||||
const knex = db();
|
||||
const access = res.locals.access;
|
||||
const accessData = await access.can("proxy_hosts:get");
|
||||
const accessData = await access.can("proxy_hosts:list");
|
||||
|
||||
const query = knex("wg_client").select("*");
|
||||
if (accessData.permission_visibility !== "all") {
|
||||
query.where("owner_user_id", access.token.getUserId(1));
|
||||
}
|
||||
const clients = await query;
|
||||
const clients = await internalWireguard.getClients(knex, access, accessData);
|
||||
|
||||
let totalStorageBytes = 0;
|
||||
let totalTransferRx = 0;
|
||||
|
|
@ -61,14 +57,20 @@ router.get("/dashboard", async (req, res, next) => {
|
|||
try {
|
||||
totalStorageBytes += await internalWireguardFs.getClientStorageUsage(client.ipv4_address);
|
||||
} catch (_) {}
|
||||
totalTransferRx += Number(client.transfer_rx || 0);
|
||||
totalTransferTx += Number(client.transfer_tx || 0);
|
||||
|
||||
totalTransferRx += parseInt(client.transfer_rx || 0, 10);
|
||||
totalTransferTx += parseInt(client.transfer_tx || 0, 10);
|
||||
|
||||
if (client.latest_handshake_at) {
|
||||
const handshake = new Date(client.latest_handshake_at).getTime();
|
||||
if (now - handshake <= DAY) online24h++;
|
||||
if (now - handshake <= 7 * DAY) online7d++;
|
||||
if (now - handshake <= 30 * DAY) online30d++;
|
||||
const handshakeStr = String(client.latest_handshake_at);
|
||||
let handshakeTime = Date.parse(handshakeStr);
|
||||
|
||||
// Handle 0 or invalid epoch
|
||||
if (handshakeTime > 0) {
|
||||
if (now - handshakeTime <= DAY) online24h++;
|
||||
if (now - handshakeTime <= 7 * DAY) online7d++;
|
||||
if (now - handshakeTime <= 30 * DAY) online30d++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,13 +2,6 @@
|
|||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@apidevtools/json-schema-ref-parser@^15.3.1":
|
||||
version "15.3.1"
|
||||
resolved "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-15.3.1.tgz"
|
||||
integrity sha512-FIweGOR9zrNuskfDXn8dfsA4eJEe8LmmGsGSDikEZvgYm36SO36yMhasXSOX7/OTGZ3b7I9iPhOxB24D8xL5uQ==
|
||||
dependencies:
|
||||
js-yaml "^4.1.1"
|
||||
|
||||
"@apidevtools/json-schema-ref-parser@14.0.1":
|
||||
version "14.0.1"
|
||||
resolved "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-14.0.1.tgz"
|
||||
|
|
@ -17,6 +10,13 @@
|
|||
"@types/json-schema" "^7.0.15"
|
||||
js-yaml "^4.1.0"
|
||||
|
||||
"@apidevtools/json-schema-ref-parser@^15.3.1":
|
||||
version "15.3.1"
|
||||
resolved "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-15.3.1.tgz"
|
||||
integrity sha512-FIweGOR9zrNuskfDXn8dfsA4eJEe8LmmGsGSDikEZvgYm36SO36yMhasXSOX7/OTGZ3b7I9iPhOxB24D8xL5uQ==
|
||||
dependencies:
|
||||
js-yaml "^4.1.1"
|
||||
|
||||
"@apidevtools/openapi-schemas@^2.1.0":
|
||||
version "2.1.0"
|
||||
resolved "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz"
|
||||
|
|
@ -53,6 +53,41 @@
|
|||
"@biomejs/cli-win32-arm64" "2.4.5"
|
||||
"@biomejs/cli-win32-x64" "2.4.5"
|
||||
|
||||
"@biomejs/cli-darwin-arm64@2.4.5":
|
||||
version "2.4.5"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.4.5.tgz#a62472ab3529a3905b16e1f3fdbbc74f2e5f0023"
|
||||
integrity sha512-lGS4Nd5O3KQJ6TeWv10mElnx1phERhBxqGP/IKq0SvZl78kcWDFMaTtVK+w3v3lusRFxJY78n07PbKplirsU5g==
|
||||
|
||||
"@biomejs/cli-darwin-x64@2.4.5":
|
||||
version "2.4.5"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.4.5.tgz#e8bb001fcf6a8c751b0971cccf53993e9ba2e6e9"
|
||||
integrity sha512-6MoH4tyISIBNkZ2Q5T1R7dLd5BsITb2yhhhrU9jHZxnNSNMWl+s2Mxu7NBF8Y3a7JJcqq9nsk8i637z4gqkJxQ==
|
||||
|
||||
"@biomejs/cli-linux-arm64-musl@2.4.5":
|
||||
version "2.4.5"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.4.5.tgz#b7ef7902237f16113061659a4c54aff5ad4513d5"
|
||||
integrity sha512-iqLDgpzobG7gpBF0fwEVS/LT8kmN7+S0E2YKFDtqliJfzNLnAiV2Nnyb+ehCDCJgAZBASkYHR2o60VQWikpqIg==
|
||||
|
||||
"@biomejs/cli-linux-arm64@2.4.5":
|
||||
version "2.4.5"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.4.5.tgz#f110af748965cb1b57624dbbbd7acba729da8780"
|
||||
integrity sha512-U1GAG6FTjhAO04MyH4xn23wRNBkT6H7NentHh+8UxD6ShXKBm5SY4RedKJzkUThANxb9rUKIPc7B8ew9Xo/cWg==
|
||||
|
||||
"@biomejs/cli-linux-x64-musl@2.4.5":
|
||||
version "2.4.5"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.4.5.tgz#c3493eba094216e735538c55354dbc8867b51909"
|
||||
integrity sha512-NlKa7GpbQmNhZf9kakQeddqZyT7itN7jjWdakELeXyTU3pg/83fTysRRDPJD0akTfKDl6vZYNT9Zqn4MYZVBOA==
|
||||
|
||||
"@biomejs/cli-linux-x64@2.4.5":
|
||||
version "2.4.5"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-x64/-/cli-linux-x64-2.4.5.tgz#15805550db4e45ffbd6c42d140d0cb5c6dbe07af"
|
||||
integrity sha512-NdODlSugMzTlENPTa4z0xB82dTUlCpsrOxc43///aNkTLblIYH4XpYflBbf5ySlQuP8AA4AZd1qXhV07IdrHdQ==
|
||||
|
||||
"@biomejs/cli-win32-arm64@2.4.5":
|
||||
version "2.4.5"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.4.5.tgz#8dae57dc8ffc1e82e00a59e623b5023c09726a4d"
|
||||
integrity sha512-EBfrTqRIWOFSd7CQb/0ttjHMR88zm3hGravnDwUA9wHAaCAYsULKDebWcN5RmrEo1KBtl/gDVJMrFjNR0pdGUw==
|
||||
|
||||
"@biomejs/cli-win32-x64@2.4.5":
|
||||
version "2.4.5"
|
||||
resolved "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.4.5.tgz"
|
||||
|
|
@ -166,13 +201,6 @@
|
|||
resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz"
|
||||
integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
|
||||
|
||||
"@types/node@>= 8":
|
||||
version "25.3.5"
|
||||
resolved "https://registry.npmjs.org/@types/node/-/node-25.3.5.tgz"
|
||||
integrity sha512-oX8xrhvpiyRCQkG1MFchB09f+cXftgIXb3a7UUa4Y3wpmZPw5tyZGTLWhlESOLq1Rq6oDlc8npVU2/9xiCuXMA==
|
||||
dependencies:
|
||||
undici-types "~7.18.0"
|
||||
|
||||
abbrev@1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz"
|
||||
|
|
@ -193,7 +221,7 @@ accepts@^2.0.0:
|
|||
mime-types "^3.0.0"
|
||||
negotiator "^1.0.0"
|
||||
|
||||
agent-base@^6.0.2, agent-base@6:
|
||||
agent-base@6, agent-base@^6.0.2:
|
||||
version "6.0.2"
|
||||
resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz"
|
||||
integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
|
||||
|
|
@ -232,7 +260,7 @@ ajv-formats@^2.1.1:
|
|||
dependencies:
|
||||
ajv "^8.0.0"
|
||||
|
||||
ajv@^8.0.0, ajv@^8.17.1, ajv@^8.18.0, ajv@^8.5.0:
|
||||
ajv@^8.0.0, ajv@^8.17.1, ajv@^8.18.0:
|
||||
version "8.18.0"
|
||||
resolved "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz"
|
||||
integrity sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==
|
||||
|
|
@ -501,7 +529,7 @@ busboy@^1.6.0:
|
|||
dependencies:
|
||||
streamsearch "^1.1.0"
|
||||
|
||||
bytes@^3.1.2, bytes@~3.1.2, bytes@3.1.2:
|
||||
bytes@3.1.2, bytes@^3.1.2, bytes@~3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz"
|
||||
integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==
|
||||
|
|
@ -556,6 +584,11 @@ camelcase@^5.0.0:
|
|||
resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz"
|
||||
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
|
||||
|
||||
chalk@5.6.2:
|
||||
version "5.6.2"
|
||||
resolved "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz"
|
||||
integrity sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==
|
||||
|
||||
chalk@^2.3.2:
|
||||
version "2.4.2"
|
||||
resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz"
|
||||
|
|
@ -565,11 +598,6 @@ chalk@^2.3.2:
|
|||
escape-string-regexp "^1.0.5"
|
||||
supports-color "^5.3.0"
|
||||
|
||||
chalk@5.6.2:
|
||||
version "5.6.2"
|
||||
resolved "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz"
|
||||
integrity sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==
|
||||
|
||||
chokidar@^3.5.2:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz"
|
||||
|
|
@ -623,16 +651,16 @@ color-convert@^2.0.1:
|
|||
dependencies:
|
||||
color-name "~1.1.4"
|
||||
|
||||
color-name@~1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
|
||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||
|
||||
color-name@1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz"
|
||||
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
|
||||
|
||||
color-name@~1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
|
||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||
|
||||
color-support@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz"
|
||||
|
|
@ -746,13 +774,6 @@ db-errors@^0.2.3:
|
|||
resolved "https://registry.npmjs.org/db-errors/-/db-errors-0.2.3.tgz"
|
||||
integrity sha512-OOgqgDuCavHXjYSJoV2yGhv6SeG8nk42aoCSoyXLZUH7VwFG27rxbavU1z+VrZbZjphw5UkDQwUlD21MwZpUng==
|
||||
|
||||
debug@^4, debug@^4.3.3, debug@^4.3.4, debug@^4.4.0, debug@^4.4.3, debug@4:
|
||||
version "4.4.3"
|
||||
resolved "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz"
|
||||
integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==
|
||||
dependencies:
|
||||
ms "^2.1.3"
|
||||
|
||||
debug@2.6.9:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz"
|
||||
|
|
@ -760,6 +781,13 @@ debug@2.6.9:
|
|||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@4, debug@^4, debug@^4.3.3, debug@^4.3.4, debug@^4.4.0, debug@^4.4.3:
|
||||
version "4.4.3"
|
||||
resolved "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz"
|
||||
integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==
|
||||
dependencies:
|
||||
ms "^2.1.3"
|
||||
|
||||
debug@4.3.4:
|
||||
version "4.3.4"
|
||||
resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz"
|
||||
|
|
@ -1117,6 +1145,11 @@ fs.realpath@^1.0.0:
|
|||
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
|
||||
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
|
||||
|
||||
fsevents@~2.3.2:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
|
||||
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
|
||||
|
||||
function-bind@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz"
|
||||
|
|
@ -1215,19 +1248,7 @@ glob@^10.0.0:
|
|||
package-json-from-dist "^1.0.0"
|
||||
path-scurry "^1.11.1"
|
||||
|
||||
glob@^7.1.3:
|
||||
version "7.2.3"
|
||||
resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz"
|
||||
integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^3.1.1"
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
glob@^7.1.4:
|
||||
glob@^7.1.3, glob@^7.1.4:
|
||||
version "7.2.3"
|
||||
resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz"
|
||||
integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
|
||||
|
|
@ -1384,7 +1405,7 @@ inflight@^1.0.4:
|
|||
once "^1.3.0"
|
||||
wrappy "1"
|
||||
|
||||
inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3, inherits@~2.0.4, inherits@2:
|
||||
inherits@2, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3, inherits@~2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
|
|
@ -1549,7 +1570,7 @@ jws@^4.0.1:
|
|||
jwa "^2.0.1"
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
knex@>=1.0.1, knex@3.1.0:
|
||||
knex@3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.npmjs.org/knex/-/knex-3.1.0.tgz"
|
||||
integrity sha512-GLoII6hR0c4ti243gMs5/1Rb3B+AjwMOfjYm97pu0FOQa7JH56hgBxYf5WK2525ceSbBY1cjeZ9yk99GPMB6Kw==
|
||||
|
|
@ -1712,7 +1733,7 @@ merge-descriptors@^2.0.0:
|
|||
resolved "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz"
|
||||
integrity sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==
|
||||
|
||||
mime-db@^1.54.0, "mime-db@>= 1.43.0 < 2":
|
||||
"mime-db@>= 1.43.0 < 2", mime-db@^1.54.0:
|
||||
version "1.54.0"
|
||||
resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz"
|
||||
integrity sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==
|
||||
|
|
@ -1801,44 +1822,23 @@ minipass-sized@^1.0.3:
|
|||
dependencies:
|
||||
minipass "^3.0.0"
|
||||
|
||||
minipass@^3.0.0:
|
||||
minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3:
|
||||
version "3.3.6"
|
||||
resolved "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz"
|
||||
integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==
|
||||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
minipass@^3.1.0:
|
||||
version "3.3.6"
|
||||
resolved "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz"
|
||||
integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==
|
||||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
minipass@^3.1.1:
|
||||
version "3.3.6"
|
||||
resolved "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz"
|
||||
integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==
|
||||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
minipass@^3.1.3:
|
||||
version "3.3.6"
|
||||
resolved "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz"
|
||||
integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==
|
||||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2:
|
||||
version "7.1.3"
|
||||
resolved "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz"
|
||||
integrity sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==
|
||||
|
||||
minipass@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz"
|
||||
integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==
|
||||
|
||||
"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2:
|
||||
version "7.1.3"
|
||||
resolved "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz"
|
||||
integrity sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==
|
||||
|
||||
minizlib@^2.0.0, minizlib@^2.1.1:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz"
|
||||
|
|
@ -1862,11 +1862,6 @@ moment@^2.30.1:
|
|||
resolved "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz"
|
||||
integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==
|
||||
|
||||
ms@^2.0.0, ms@^2.1.1, ms@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz"
|
||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||
|
||||
ms@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz"
|
||||
|
|
@ -1877,6 +1872,11 @@ ms@2.1.2:
|
|||
resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
|
||||
ms@^2.0.0, ms@^2.1.1, ms@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz"
|
||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||
|
||||
mysql2@^3.18.2:
|
||||
version "3.18.2"
|
||||
resolved "https://registry.npmjs.org/mysql2/-/mysql2-3.18.2.tgz"
|
||||
|
|
@ -2034,11 +2034,6 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0:
|
|||
dependencies:
|
||||
wrappy "1"
|
||||
|
||||
openapi-types@>=7:
|
||||
version "12.1.3"
|
||||
resolved "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz"
|
||||
integrity sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==
|
||||
|
||||
otplib@^13.3.0:
|
||||
version "13.3.0"
|
||||
resolved "https://registry.npmjs.org/otplib/-/otplib-13.3.0.tgz"
|
||||
|
|
@ -2187,16 +2182,16 @@ pg-cloudflare@^1.3.0:
|
|||
resolved "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.3.0.tgz"
|
||||
integrity sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==
|
||||
|
||||
pg-connection-string@^2.11.0:
|
||||
version "2.11.0"
|
||||
resolved "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.11.0.tgz"
|
||||
integrity sha512-kecgoJwhOpxYU21rZjULrmrBJ698U2RxXofKVzOn5UDj61BPj/qMb7diYUR1nLScCDbrztQFl1TaQZT0t1EtzQ==
|
||||
|
||||
pg-connection-string@2.6.2:
|
||||
version "2.6.2"
|
||||
resolved "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz"
|
||||
integrity sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==
|
||||
|
||||
pg-connection-string@^2.11.0:
|
||||
version "2.11.0"
|
||||
resolved "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.11.0.tgz"
|
||||
integrity sha512-kecgoJwhOpxYU21rZjULrmrBJ698U2RxXofKVzOn5UDj61BPj/qMb7diYUR1nLScCDbrztQFl1TaQZT0t1EtzQ==
|
||||
|
||||
pg-int8@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz"
|
||||
|
|
@ -2223,7 +2218,7 @@ pg-types@2.2.0:
|
|||
postgres-date "~1.0.4"
|
||||
postgres-interval "^1.1.0"
|
||||
|
||||
pg@^8.19.0, pg@>=8.0:
|
||||
pg@^8.19.0:
|
||||
version "8.19.0"
|
||||
resolved "https://registry.npmjs.org/pg/-/pg-8.19.0.tgz"
|
||||
integrity sha512-QIcLGi508BAHkQ3pJNptsFz5WQMlpGbuBGBaIaXsWK8mel2kQ/rThYI+DbgjUvZrIr7MiuEuc9LcChJoEZK1xQ==
|
||||
|
|
@ -2414,25 +2409,7 @@ readable-stream@^2.0.5:
|
|||
string_decoder "~1.1.1"
|
||||
util-deprecate "~1.0.1"
|
||||
|
||||
readable-stream@^3.1.1:
|
||||
version "3.6.2"
|
||||
resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz"
|
||||
integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
|
||||
dependencies:
|
||||
inherits "^2.0.3"
|
||||
string_decoder "^1.1.1"
|
||||
util-deprecate "^1.0.1"
|
||||
|
||||
readable-stream@^3.4.0:
|
||||
version "3.6.2"
|
||||
resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz"
|
||||
integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
|
||||
dependencies:
|
||||
inherits "^2.0.3"
|
||||
string_decoder "^1.1.1"
|
||||
util-deprecate "^1.0.1"
|
||||
|
||||
readable-stream@^3.6.0:
|
||||
readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0:
|
||||
version "3.6.2"
|
||||
resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz"
|
||||
integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
|
||||
|
|
@ -2525,7 +2502,7 @@ router@^2.2.0:
|
|||
parseurl "^1.3.3"
|
||||
path-to-regexp "^8.0.0"
|
||||
|
||||
safe-buffer@^5.0.1, safe-buffer@~5.2.0, safe-buffer@5.2.1:
|
||||
safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@~5.2.0:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz"
|
||||
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||
|
|
@ -2758,20 +2735,6 @@ streamx@^2.15.0:
|
|||
fast-fifo "^1.3.2"
|
||||
text-decoder "^1.1.0"
|
||||
|
||||
string_decoder@^1.1.1, string_decoder@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz"
|
||||
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
|
||||
dependencies:
|
||||
safe-buffer "~5.2.0"
|
||||
|
||||
string_decoder@~1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz"
|
||||
integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
|
||||
dependencies:
|
||||
safe-buffer "~5.1.0"
|
||||
|
||||
"string-width-cjs@npm:string-width@^4.2.0":
|
||||
version "4.2.3"
|
||||
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
|
||||
|
|
@ -2781,25 +2744,7 @@ string_decoder@~1.1.1:
|
|||
is-fullwidth-code-point "^3.0.0"
|
||||
strip-ansi "^6.0.1"
|
||||
|
||||
"string-width@^1.0.2 || 2 || 3 || 4":
|
||||
version "4.2.3"
|
||||
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
|
||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||
dependencies:
|
||||
emoji-regex "^8.0.0"
|
||||
is-fullwidth-code-point "^3.0.0"
|
||||
strip-ansi "^6.0.1"
|
||||
|
||||
string-width@^4.1.0, string-width@^4.2.0:
|
||||
version "4.2.3"
|
||||
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
|
||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||
dependencies:
|
||||
emoji-regex "^8.0.0"
|
||||
is-fullwidth-code-point "^3.0.0"
|
||||
strip-ansi "^6.0.1"
|
||||
|
||||
string-width@^4.2.3:
|
||||
"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
|
||||
version "4.2.3"
|
||||
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
|
||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||
|
|
@ -2817,6 +2762,20 @@ string-width@^5.0.1, string-width@^5.1.2:
|
|||
emoji-regex "^9.2.2"
|
||||
strip-ansi "^7.0.1"
|
||||
|
||||
string_decoder@^1.1.1, string_decoder@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz"
|
||||
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
|
||||
dependencies:
|
||||
safe-buffer "~5.2.0"
|
||||
|
||||
string_decoder@~1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz"
|
||||
integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
|
||||
dependencies:
|
||||
safe-buffer "~5.1.0"
|
||||
|
||||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
|
||||
version "6.0.1"
|
||||
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
|
||||
|
|
@ -2981,11 +2940,6 @@ undefsafe@^2.0.5:
|
|||
resolved "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz"
|
||||
integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==
|
||||
|
||||
undici-types@~7.18.0:
|
||||
version "7.18.2"
|
||||
resolved "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz"
|
||||
integrity sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==
|
||||
|
||||
unique-filename@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz"
|
||||
|
|
|
|||
|
|
@ -1,255 +1 @@
|
|||
/*
|
||||
|
||||
How this was generated:
|
||||
1. bring up an empty pdns stack
|
||||
2. use api to create a zone ...
|
||||
|
||||
curl -X POST \
|
||||
'http://npm.dev:8081/api/v1/servers/localhost/zones' \
|
||||
--header 'X-API-Key: npm' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data-raw '{
|
||||
"name": "example.com.",
|
||||
"kind": "Native",
|
||||
"masters": [],
|
||||
"nameservers": [
|
||||
"ns1.pdns.",
|
||||
"ns2.pdns."
|
||||
]
|
||||
}'
|
||||
|
||||
3. Dump sql:
|
||||
|
||||
docker exec -ti npm.pdns.db mysqldump -u pdns -p pdns
|
||||
|
||||
*/
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||
/*!40101 SET NAMES utf8mb4 */;
|
||||
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
|
||||
/*!40103 SET TIME_ZONE='+00:00' */;
|
||||
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
|
||||
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
||||
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
|
||||
|
||||
--
|
||||
-- Table structure for table `comments`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `comments`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `comments` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`domain_id` int(11) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`type` varchar(10) NOT NULL,
|
||||
`modified_at` int(11) NOT NULL,
|
||||
`account` varchar(40) CHARACTER SET utf8mb3 DEFAULT NULL,
|
||||
`comment` text CHARACTER SET utf8mb3 NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `comments_name_type_idx` (`name`,`type`),
|
||||
KEY `comments_order_idx` (`domain_id`,`modified_at`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `comments`
|
||||
--
|
||||
|
||||
LOCK TABLES `comments` WRITE;
|
||||
/*!40000 ALTER TABLE `comments` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `comments` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `cryptokeys`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `cryptokeys`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `cryptokeys` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`domain_id` int(11) NOT NULL,
|
||||
`flags` int(11) NOT NULL,
|
||||
`active` tinyint(1) DEFAULT NULL,
|
||||
`published` tinyint(1) DEFAULT 1,
|
||||
`content` text DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `domainidindex` (`domain_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `cryptokeys`
|
||||
--
|
||||
|
||||
LOCK TABLES `cryptokeys` WRITE;
|
||||
/*!40000 ALTER TABLE `cryptokeys` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `cryptokeys` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `domainmetadata`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `domainmetadata`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `domainmetadata` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`domain_id` int(11) NOT NULL,
|
||||
`kind` varchar(32) DEFAULT NULL,
|
||||
`content` text DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `domainmetadata_idx` (`domain_id`,`kind`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `domainmetadata`
|
||||
--
|
||||
|
||||
LOCK TABLES `domainmetadata` WRITE;
|
||||
/*!40000 ALTER TABLE `domainmetadata` DISABLE KEYS */;
|
||||
INSERT INTO `domainmetadata` VALUES
|
||||
(1,1,'SOA-EDIT-API','DEFAULT');
|
||||
/*!40000 ALTER TABLE `domainmetadata` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `domains`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `domains`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `domains` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`master` varchar(128) DEFAULT NULL,
|
||||
`last_check` int(11) DEFAULT NULL,
|
||||
`type` varchar(8) NOT NULL,
|
||||
`notified_serial` int(10) unsigned DEFAULT NULL,
|
||||
`account` varchar(40) CHARACTER SET utf8mb3 DEFAULT NULL,
|
||||
`options` varchar(64000) DEFAULT NULL,
|
||||
`catalog` varchar(255) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `name_index` (`name`),
|
||||
KEY `catalog_idx` (`catalog`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `domains`
|
||||
--
|
||||
|
||||
LOCK TABLES `domains` WRITE;
|
||||
/*!40000 ALTER TABLE `domains` DISABLE KEYS */;
|
||||
INSERT INTO `domains` VALUES
|
||||
(1,'example.com','',NULL,'NATIVE',NULL,'',NULL,NULL);
|
||||
/*!40000 ALTER TABLE `domains` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `records`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `records`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `records` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`domain_id` int(11) DEFAULT NULL,
|
||||
`name` varchar(255) DEFAULT NULL,
|
||||
`type` varchar(10) DEFAULT NULL,
|
||||
`content` varchar(64000) DEFAULT NULL,
|
||||
`ttl` int(11) DEFAULT NULL,
|
||||
`prio` int(11) DEFAULT NULL,
|
||||
`disabled` tinyint(1) DEFAULT 0,
|
||||
`ordername` varchar(255) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
|
||||
`auth` tinyint(1) DEFAULT 1,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `nametype_index` (`name`,`type`),
|
||||
KEY `domain_id` (`domain_id`),
|
||||
KEY `ordername` (`ordername`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `records`
|
||||
--
|
||||
|
||||
LOCK TABLES `records` WRITE;
|
||||
/*!40000 ALTER TABLE `records` DISABLE KEYS */;
|
||||
INSERT INTO `records` VALUES
|
||||
(1,1,'example.com','NS','ns1.pdns',1500,0,0,NULL,1),
|
||||
(2,1,'example.com','NS','ns2.pdns',1500,0,0,NULL,1),
|
||||
(3,1,'example.com','SOA','a.misconfigured.dns.server.invalid hostmaster.example.com 2023030501 10800 3600 604800 3600',1500,0,0,NULL,1);
|
||||
/*!40000 ALTER TABLE `records` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `supermasters`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `supermasters`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `supermasters` (
|
||||
`ip` varchar(64) NOT NULL,
|
||||
`nameserver` varchar(255) NOT NULL,
|
||||
`account` varchar(40) CHARACTER SET utf8mb3 NOT NULL,
|
||||
PRIMARY KEY (`ip`,`nameserver`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `supermasters`
|
||||
--
|
||||
|
||||
LOCK TABLES `supermasters` WRITE;
|
||||
/*!40000 ALTER TABLE `supermasters` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `supermasters` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `tsigkeys`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `tsigkeys`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `tsigkeys` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) DEFAULT NULL,
|
||||
`algorithm` varchar(50) DEFAULT NULL,
|
||||
`secret` varchar(255) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `namealgoindex` (`name`,`algorithm`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `tsigkeys`
|
||||
--
|
||||
|
||||
LOCK TABLES `tsigkeys` WRITE;
|
||||
/*!40000 ALTER TABLE `tsigkeys` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `tsigkeys` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
|
||||
|
||||
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
||||
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||
-- MySQL DB Init Script Mock
|
||||
|
|
|
|||
|
|
@ -1,92 +1 @@
|
|||
# WELCOME TO SQUID 6.6
|
||||
# ----------------------------
|
||||
#
|
||||
# This is the documentation for the Squid configuration file.
|
||||
# This documentation can also be found online at:
|
||||
# http://www.squid-cache.org/Doc/config/
|
||||
#
|
||||
# You may wish to look at the Squid home page and wiki for the
|
||||
# FAQ and other documentation:
|
||||
# http://www.squid-cache.org/
|
||||
# https://wiki.squid-cache.org/SquidFaq
|
||||
# https://wiki.squid-cache.org/ConfigExamples
|
||||
#
|
||||
|
||||
# Example rule allowing access from your local networks.
|
||||
# Adapt to list your (internal) IP networks from where browsing
|
||||
# should be allowed
|
||||
acl localnet src 0.0.0.1-0.255.255.255 # RFC 1122 "this" network (LAN)
|
||||
acl localnet src 10.0.0.0/8 # RFC 1918 local private network (LAN)
|
||||
acl localnet src 100.64.0.0/10 # RFC 6598 shared address space (CGN)
|
||||
acl localnet src 169.254.0.0/16 # RFC 3927 link-local (directly plugged) machines
|
||||
acl localnet src 172.0.0.0/8
|
||||
acl localnet src 192.168.0.0/16 # RFC 1918 local private network (LAN)
|
||||
acl localnet src fc00::/7 # RFC 4193 local private network range
|
||||
acl localnet src fe80::/10 # RFC 4291 link-local (directly plugged) machines
|
||||
|
||||
acl SSL_ports port 443
|
||||
acl Safe_ports port 80 # http
|
||||
acl Safe_ports port 81
|
||||
acl Safe_ports port 443 # https
|
||||
|
||||
#
|
||||
# Recommended minimum Access Permission configuration:
|
||||
#
|
||||
# Deny requests to certain unsafe ports
|
||||
http_access deny !Safe_ports
|
||||
|
||||
# Deny CONNECT to other than secure SSL ports
|
||||
http_access deny CONNECT !SSL_ports
|
||||
|
||||
# Only allow cachemgr access from localhost
|
||||
http_access allow localhost manager
|
||||
http_access deny manager
|
||||
|
||||
# This default configuration only allows localhost requests because a more
|
||||
# permissive Squid installation could introduce new attack vectors into the
|
||||
# network by proxying external TCP connections to unprotected services.
|
||||
http_access allow localhost
|
||||
|
||||
# The two deny rules below are unnecessary in this default configuration
|
||||
# because they are followed by a "deny all" rule. However, they may become
|
||||
# critically important when you start allowing external requests below them.
|
||||
|
||||
# Protect web applications running on the same server as Squid. They often
|
||||
# assume that only local users can access them at "localhost" ports.
|
||||
http_access deny to_localhost
|
||||
|
||||
# Protect cloud servers that provide local users with sensitive info about
|
||||
# their server via certain well-known link-local (a.k.a. APIPA) addresses.
|
||||
http_access deny to_linklocal
|
||||
|
||||
#
|
||||
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
|
||||
#
|
||||
include /etc/squid/conf.d/*.conf
|
||||
|
||||
# For example, to allow access from your local networks, you may uncomment the
|
||||
# following rule (and/or add rules that match your definition of "local"):
|
||||
# http_access allow localnet
|
||||
|
||||
# And finally deny all other access to this proxy
|
||||
http_access deny all
|
||||
|
||||
# Squid normally listens to port 3128
|
||||
http_port 3128
|
||||
|
||||
# Leave coredumps in the first cache dir
|
||||
coredump_dir /var/spool/squid
|
||||
|
||||
#
|
||||
# Add any of your own refresh_pattern entries above these.
|
||||
#
|
||||
refresh_pattern ^ftp: 1440 20% 10080
|
||||
refresh_pattern -i (/cgi-bin/|\?) 0 0% 0
|
||||
refresh_pattern \/(Packages|Sources)(|\.bz2|\.gz|\.xz)$ 0 0% 0 refresh-ims
|
||||
refresh_pattern \/Release(|\.gpg)$ 0 0% 0 refresh-ims
|
||||
refresh_pattern \/InRelease$ 0 0% 0 refresh-ims
|
||||
refresh_pattern \/(Translation-.*)(|\.bz2|\.gz|\.xz)$ 0 0% 0 refresh-ims
|
||||
# example pattern for deb packages
|
||||
#refresh_pattern (\.deb|\.udeb)$ 129600 100% 129600
|
||||
refresh_pattern . 0 20% 4320
|
||||
|
||||
# Squid config mock
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ const WireGuardClientEditModal = EasyModal.create(({ client }: WireGuardClientEd
|
|||
const modal = useModal<any>();
|
||||
const [name, setName] = useState(client.name);
|
||||
const [storageLimitMb, setStorageLimitMb] = useState<number>(client.storageLimitMb ?? 500);
|
||||
const [txLimit, setTxLimit] = useState<number>(client.txLimit ?? 0);
|
||||
const [rxLimit, setRxLimit] = useState<number>(client.rxLimit ?? 0);
|
||||
const [txLimit, setTxLimit] = useState<number>(client.txLimit ? client.txLimit / 125000 : 0);
|
||||
const [rxLimit, setRxLimit] = useState<number>(client.rxLimit ? client.rxLimit / 125000 : 0);
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
|
@ -21,8 +21,8 @@ const WireGuardClientEditModal = EasyModal.create(({ client }: WireGuardClientEd
|
|||
modal.resolve({
|
||||
name: name.trim(),
|
||||
storage_limit_mb: storageLimitMb,
|
||||
tx_limit: txLimit,
|
||||
rx_limit: rxLimit
|
||||
tx_limit: txLimit * 125000,
|
||||
rx_limit: rxLimit * 125000
|
||||
});
|
||||
modal.hide();
|
||||
}
|
||||
|
|
@ -81,7 +81,7 @@ const WireGuardClientEditModal = EasyModal.create(({ client }: WireGuardClientEd
|
|||
<div className="row">
|
||||
<div className="col-md-6 mb-3">
|
||||
<label htmlFor="wg-edit-tx" className="form-label">
|
||||
Upload Bandwidth Limit (Bytes)
|
||||
Upload Bandwidth Limit (Mbps)
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
|
|
@ -90,13 +90,14 @@ const WireGuardClientEditModal = EasyModal.create(({ client }: WireGuardClientEd
|
|||
value={txLimit}
|
||||
onChange={(e) => setTxLimit(Number(e.target.value))}
|
||||
min="0"
|
||||
step="1"
|
||||
required
|
||||
/>
|
||||
<div className="form-text">0 = Unlimited.</div>
|
||||
</div>
|
||||
<div className="col-md-6 mb-3">
|
||||
<label htmlFor="wg-edit-rx" className="form-label">
|
||||
Download Bandwidth Limit (Bytes)
|
||||
Download Bandwidth Limit (Mbps)
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
|
|
@ -105,6 +106,7 @@ const WireGuardClientEditModal = EasyModal.create(({ client }: WireGuardClientEd
|
|||
value={rxLimit}
|
||||
onChange={(e) => setRxLimit(Number(e.target.value))}
|
||||
min="0"
|
||||
step="1"
|
||||
required
|
||||
/>
|
||||
<div className="form-text">0 = Unlimited.</div>
|
||||
|
|
|
|||
|
|
@ -24,8 +24,22 @@ const WireGuardClientLogsModal = EasyModal.create(({ clientId, clientName }: Pro
|
|||
};
|
||||
|
||||
const formatDate = (dateString: string) => {
|
||||
const d = new Date(dateString);
|
||||
return d.toLocaleString();
|
||||
try {
|
||||
// Ensure UTC parsing from raw SQLite timestamp
|
||||
const d = new Date(dateString.endsWith('Z') ? dateString : dateString + 'Z');
|
||||
return isNaN(d.getTime()) ? dateString : d.toLocaleString();
|
||||
} catch {
|
||||
return dateString;
|
||||
}
|
||||
};
|
||||
|
||||
const parseLogMeta = (metaString: string | any) => {
|
||||
try {
|
||||
const meta = typeof metaString === 'string' ? JSON.parse(metaString) : metaString;
|
||||
return meta?.message || typeof meta === 'string' ? meta : JSON.stringify(meta);
|
||||
} catch {
|
||||
return String(metaString);
|
||||
}
|
||||
};
|
||||
|
||||
const getActionBadge = (action: string) => {
|
||||
|
|
@ -75,7 +89,7 @@ const WireGuardClientLogsModal = EasyModal.create(({ clientId, clientName }: Pro
|
|||
</td>
|
||||
<td>{getActionBadge(log.action)}</td>
|
||||
<td className="small text-muted text-wrap">
|
||||
{log.meta && log.meta.message ? log.meta.message : JSON.stringify(log.meta)}
|
||||
{parseLogMeta(log.meta)}
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ const WireGuardClientModal = EasyModal.create(({ interfaces, defaultInterfaceId
|
|||
name: name.trim(),
|
||||
interface_id: selectedInterfaceId,
|
||||
storage_limit_mb: storageLimitMb,
|
||||
tx_limit: txLimit,
|
||||
rx_limit: rxLimit
|
||||
tx_limit: txLimit * 125000,
|
||||
rx_limit: rxLimit * 125000
|
||||
});
|
||||
modal.hide();
|
||||
}
|
||||
|
|
@ -121,7 +121,7 @@ const WireGuardClientModal = EasyModal.create(({ interfaces, defaultInterfaceId
|
|||
<div className="row">
|
||||
<div className="col-md-6 mb-3">
|
||||
<label htmlFor="wg-client-tx" className="form-label">
|
||||
Upload Bandwidth Limit (Bytes)
|
||||
Upload Bandwidth Limit (Mbps)
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
|
|
@ -130,13 +130,14 @@ const WireGuardClientModal = EasyModal.create(({ interfaces, defaultInterfaceId
|
|||
value={txLimit}
|
||||
onChange={(e) => setTxLimit(Number(e.target.value))}
|
||||
min="0"
|
||||
step="1"
|
||||
required
|
||||
/>
|
||||
<div className="form-text">Optional. 0 = Unlimited.</div>
|
||||
</div>
|
||||
<div className="col-md-6 mb-3">
|
||||
<label htmlFor="wg-client-rx" className="form-label">
|
||||
Download Bandwidth Limit (Bytes)
|
||||
Download Bandwidth Limit (Mbps)
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
|
|
@ -145,6 +146,7 @@ const WireGuardClientModal = EasyModal.create(({ interfaces, defaultInterfaceId
|
|||
value={rxLimit}
|
||||
onChange={(e) => setRxLimit(Number(e.target.value))}
|
||||
min="0"
|
||||
step="1"
|
||||
required
|
||||
/>
|
||||
<div className="form-text">Optional. 0 = Unlimited.</div>
|
||||
|
|
|
|||
|
|
@ -13,11 +13,17 @@ interface Props {
|
|||
ipv4Address: string;
|
||||
}
|
||||
|
||||
function formatBytes(bytes: number | null): string {
|
||||
if (bytes === null || bytes === 0) return "0 B";
|
||||
function formatBytes(bytes: number | null, unit?: string): string {
|
||||
if (bytes === null || bytes === 0) return unit ? `0.00 ${unit}` : "0 B";
|
||||
const k = 1024;
|
||||
const sizes = ["B", "KB", "MB", "GB", "TB"];
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
let i: number;
|
||||
if (unit) {
|
||||
i = sizes.indexOf(unit.toUpperCase());
|
||||
if (i === -1) i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
} else {
|
||||
i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
}
|
||||
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,12 +21,18 @@ import {
|
|||
VIEW,
|
||||
} from "src/modules/Permissions";
|
||||
|
||||
function formatBytes(bytes: number | null): string {
|
||||
if (bytes === null || bytes === 0) return "0 B";
|
||||
function formatBytes(bytes: number | null, unit?: string): string {
|
||||
if (bytes === null || bytes === 0) return unit ? `0.00 ${unit}` : "0 B";
|
||||
const k = 1024;
|
||||
const sizes = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
return `${Number.parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
|
||||
let i: number;
|
||||
if (unit) {
|
||||
i = sizes.indexOf(unit.toUpperCase());
|
||||
if (i === -1) i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
} else {
|
||||
i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
}
|
||||
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
|
||||
}
|
||||
|
||||
const Dashboard = () => {
|
||||
|
|
@ -218,7 +224,7 @@ const Dashboard = () => {
|
|||
<div className="d-flex align-items-center">
|
||||
<div className="subheader">Total Storage Utilized</div>
|
||||
</div>
|
||||
<div className="h1 mb-3">{formatBytes(wgStats?.totalStorageBytes || 0)}</div>
|
||||
<div className="h1 mb-3">{((wgStats?.totalStorageBytes || 0) / (1024 * 1024 * 1024)).toFixed(2)} GB</div>
|
||||
<div className="d-flex mb-2">
|
||||
<div className="text-muted small"><IconFolder size={14} className="me-1"/> Encrypted Partition Capacity</div>
|
||||
</div>
|
||||
|
|
@ -231,10 +237,10 @@ const Dashboard = () => {
|
|||
<div className="d-flex align-items-center">
|
||||
<div className="subheader">Global Traffic Transfer</div>
|
||||
</div>
|
||||
<div className="h1 mb-3 text-blue">{formatBytes((wgStats?.totalTransferRx || 0) + (wgStats?.totalTransferTx || 0))}</div>
|
||||
<div className="h1 mb-3 text-blue">{formatBytes((wgStats?.totalTransferRx || 0) + (wgStats?.totalTransferTx || 0), "GB")}</div>
|
||||
<div className="d-flex mb-2">
|
||||
<div className="text-muted small">
|
||||
↓ {formatBytes(wgStats?.totalTransferRx || 0)} | ↑ {formatBytes(wgStats?.totalTransferTx || 0)}
|
||||
↓ {formatBytes(wgStats?.totalTransferRx || 0, "GB")} | ↑ {formatBytes(wgStats?.totalTransferTx || 0, "GB")}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,18 @@
|
|||
import { useState, useEffect } from "react";
|
||||
import { IconShieldLock, IconNetwork, IconApi, IconFolders } from "@tabler/icons-react";
|
||||
|
||||
function formatBytes(bytes: number | null): string {
|
||||
if (!bytes) return "0 B";
|
||||
const k = 1024;
|
||||
const sizes = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
return `${Number.parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
|
||||
function formatBytes(bytes: number | null, unit?: string): string {
|
||||
if (bytes === null || bytes === 0) return unit ? `0.00 ${unit}` : "0 B";
|
||||
const k = 1024;
|
||||
const sizes = ["B", "KB", "MB", "GB", "TB"];
|
||||
let i: number;
|
||||
if (unit) {
|
||||
i = sizes.indexOf(unit.toUpperCase());
|
||||
if (i === -1) i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
} else {
|
||||
i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
}
|
||||
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
|
||||
}
|
||||
|
||||
export default function WgPublicPortal() {
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
import {
|
||||
IconPlus,
|
||||
IconDownload,
|
||||
IconQrcode,
|
||||
IconPlayerPlay,
|
||||
IconPlayerPause,
|
||||
IconTrash,
|
||||
IconNetwork,
|
||||
IconServer,
|
||||
IconEdit,
|
||||
IconPlus,
|
||||
IconQrcode,
|
||||
IconTrash,
|
||||
IconLink,
|
||||
IconZip,
|
||||
IconServer,
|
||||
IconFolder,
|
||||
IconNotes,
|
||||
IconDownload,
|
||||
IconZip,
|
||||
IconPlayerPause,
|
||||
IconPlayerPlay,
|
||||
IconNetwork,
|
||||
} from "@tabler/icons-react";
|
||||
import EasyModal from "ez-modal-react";
|
||||
import { useState } from "react";
|
||||
|
|
@ -37,11 +37,17 @@ import WireGuardFileManagerModal from "src/modals/WireGuardFileManagerModal";
|
|||
import WireGuardClientEditModal from "src/modals/WireGuardClientEditModal";
|
||||
import WireGuardClientLogsModal from "src/modals/WireGuardClientLogsModal";
|
||||
|
||||
function formatBytes(bytes: number | null): string {
|
||||
if (bytes === null || bytes === 0) return "0 B";
|
||||
function formatBytes(bytes: number | null, unit?: string): string {
|
||||
if (bytes === null || bytes === 0) return unit ? `0.00 ${unit}` : "0 B";
|
||||
const k = 1024;
|
||||
const sizes = ["B", "KB", "MB", "GB", "TB"];
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
let i: number;
|
||||
if (unit) {
|
||||
i = sizes.indexOf(unit.toUpperCase());
|
||||
if (i === -1) i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
} else {
|
||||
i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
}
|
||||
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
|
||||
}
|
||||
|
||||
|
|
@ -271,7 +277,7 @@ function WireGuard() {
|
|||
<td>
|
||||
<div className="d-flex flex-column small">
|
||||
<span className="text-muted"><IconServer size={14} className="me-1"/> {iface.clientCount || 0} Clients</span>
|
||||
<span className="text-muted"><IconFolder size={14} className="me-1"/> {formatBytes(iface.storageUsageBytes ?? 0)}</span>
|
||||
<span className="text-muted"><IconFolder size={14} className="me-1"/> {formatBytes(iface.storageUsageBytes ?? 0, "GB")}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
|
|
@ -383,13 +389,13 @@ function WireGuard() {
|
|||
<table className="table table-vcenter table-nowrap card-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Status</th>
|
||||
<th>Name</th>
|
||||
<th>Server</th>
|
||||
<th>IP Address</th>
|
||||
<th>Last Handshake</th>
|
||||
<th>Traffic & Storage</th>
|
||||
<th className="text-end">Actions</th>
|
||||
<th className="text-muted">Status</th>
|
||||
<th className="text-muted">Name</th>
|
||||
<th className="text-muted">Server</th>
|
||||
<th className="text-muted">IP Address</th>
|
||||
<th className="text-muted">Last Handshake</th>
|
||||
<th className="text-muted">Traffic & Storage</th>
|
||||
<th className="text-muted text-end">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
|
@ -427,9 +433,9 @@ function WireGuard() {
|
|||
<td>{timeAgo(client.latestHandshakeAt)}</td>
|
||||
<td>
|
||||
<div className="d-flex flex-column text-muted small">
|
||||
<span>↓ {formatBytes(client.transferRx)} / ↑ {formatBytes(client.transferTx)}</span>
|
||||
<span className={client.storageLimitMb > 0 && ((client.storageUsageBytes||0) / (client.storageLimitMb * 1024 * 1024)) > 0.9 ? "text-danger" : ""}>
|
||||
<IconFolder size={14} className="me-1"/> {formatBytes(client.storageUsageBytes || 0)} / {client.storageLimitMb === 0 ? "∞" : formatBytes(client.storageLimitMb * 1024 * 1024)}
|
||||
<span>↓ {formatBytes(client.transferRx || 0, "GB")} / ↑ {formatBytes(client.transferTx || 0, "GB")}</span>
|
||||
<span className={client.storageLimitMb > 0 && ((client.storageUsageBytes || 0) / (client.storageLimitMb * 1024 * 1024)) > 0.9 ? "text-danger" : ""}>
|
||||
<IconFolder size={14} className="me-1"/> {formatBytes(client.storageUsageBytes || 0, "MB")} / {client.storageLimitMb > 0 ? formatBytes(client.storageLimitMb * 1024 * 1024, "MB") : "∞"}
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
|
|
@ -467,57 +473,41 @@ function WireGuard() {
|
|||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-outline-dark"
|
||||
title="View Event Logs"
|
||||
onClick={() =>
|
||||
handleLogs(client)
|
||||
}
|
||||
className="btn btn-outline-secondary"
|
||||
title="Event Logs"
|
||||
onClick={() => handleLogs(client)}
|
||||
>
|
||||
<IconNotes size={16} />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-outline-primary"
|
||||
className="btn btn-outline-success"
|
||||
title="Download Config"
|
||||
onClick={() =>
|
||||
handleDownload(client.id, client.name)
|
||||
}
|
||||
onClick={() => handleDownload(client.id, client.name)}
|
||||
>
|
||||
<IconDownload size={16} />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-outline-primary"
|
||||
title="Download Config + QR (ZIP)"
|
||||
onClick={() =>
|
||||
handleDownloadZip(client.id, client.name)
|
||||
}
|
||||
className="btn btn-outline-success"
|
||||
title="Download ZIP Archive"
|
||||
onClick={() => handleDownloadZip(client.id, client.name)}
|
||||
>
|
||||
<IconZip size={16} />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={`btn ${client.enabled ? "btn-outline-warning" : "btn-outline-success"}`}
|
||||
title={
|
||||
client.enabled ? "Disable" : "Enable"
|
||||
}
|
||||
onClick={() =>
|
||||
handleToggleClient(client.id, client.enabled)
|
||||
}
|
||||
title={client.enabled ? "Disable Client" : "Enable Client"}
|
||||
onClick={() => handleToggleClient(client.id, client.enabled)}
|
||||
>
|
||||
{client.enabled ? (
|
||||
<IconPlayerPause size={16} />
|
||||
) : (
|
||||
<IconPlayerPlay size={16} />
|
||||
)}
|
||||
{client.enabled ? <IconPlayerPause size={16} /> : <IconPlayerPlay size={16} />}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-outline-danger"
|
||||
title="Delete"
|
||||
onClick={() =>
|
||||
handleDeleteClient(client.id, client.name)
|
||||
}
|
||||
title="Delete Client"
|
||||
onClick={() => handleDeleteClient(client.id, client.name)}
|
||||
>
|
||||
<IconTrash size={16} />
|
||||
</button>
|
||||
|
|
|
|||
Loading…
Reference in a new issue