mirror of
https://github.com/NginxProxyManager/nginx-proxy-manager.git
synced 2025-12-06 08:16:51 +00:00
Compare commits
3 Commits
f2b5b19a83
...
c303b69649
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c303b69649 | ||
|
|
bb6c9c8daf | ||
|
|
5b7013b8d5 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,5 +1,6 @@
|
||||
.DS_Store
|
||||
.idea
|
||||
.qodo
|
||||
._*
|
||||
.vscode
|
||||
certbot-help.txt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# certbot-dns-plugins
|
||||
# Certbot dns-plugins
|
||||
|
||||
This file contains info about available Certbot DNS plugins.
|
||||
This only works for plugins which use the standard argument structure, so:
|
||||
@@ -1,11 +1,11 @@
|
||||
import fs from "node:fs";
|
||||
import https from "node:https";
|
||||
import path from "path";
|
||||
import archiver from "archiver";
|
||||
import _ from "lodash";
|
||||
import moment from "moment";
|
||||
import path from "path";
|
||||
import tempWrite from "temp-write";
|
||||
import dnsPlugins from "../global/certbot-dns-plugins.json" with { type: "json" };
|
||||
import dnsPlugins from "../certbot/dns-plugins.json" with { type: "json" };
|
||||
import { installPlugin } from "../lib/certbot.js";
|
||||
import { useLetsencryptServer, useLetsencryptStaging } from "../lib/config.js";
|
||||
import error from "../lib/error.js";
|
||||
@@ -26,7 +26,11 @@ const omissions = () => {
|
||||
};
|
||||
|
||||
const internalCertificate = {
|
||||
allowedSslFiles: ["certificate", "certificate_key", "intermediate_certificate"],
|
||||
allowedSslFiles: [
|
||||
"certificate",
|
||||
"certificate_key",
|
||||
"intermediate_certificate",
|
||||
],
|
||||
intervalTimeout: 1000 * 60 * 60, // 1 hour
|
||||
interval: null,
|
||||
intervalProcessing: false,
|
||||
@@ -53,7 +57,10 @@ const internalCertificate = {
|
||||
);
|
||||
|
||||
const expirationThreshold = moment()
|
||||
.add(internalCertificate.renewBeforeExpirationBy[0], internalCertificate.renewBeforeExpirationBy[1])
|
||||
.add(
|
||||
internalCertificate.renewBeforeExpirationBy[0],
|
||||
internalCertificate.renewBeforeExpirationBy[1],
|
||||
)
|
||||
.format("YYYY-MM-DD HH:mm:ss");
|
||||
|
||||
// Fetch all the letsencrypt certs from the db that will expire within the configured threshold
|
||||
@@ -119,8 +126,13 @@ const internalCertificate = {
|
||||
data.nice_name = data.domain_names.join(", ");
|
||||
}
|
||||
|
||||
const certificate = await certificateModel.query().insertAndFetch(data).then(utils.omitRow(omissions()));
|
||||
// this command really should clean up and delete the cert if it can't fully succeed
|
||||
const certificate = await certificateModel
|
||||
.query()
|
||||
.insertAndFetch(data)
|
||||
.then(utils.omitRow(omissions()));
|
||||
|
||||
try {
|
||||
if (certificate.provider === "letsencrypt") {
|
||||
// Request a new Cert from LE. Let the fun begin.
|
||||
|
||||
@@ -132,12 +144,18 @@ const internalCertificate = {
|
||||
// 6. Re-instate previously disabled hosts
|
||||
|
||||
// 1. Find out any hosts that are using any of the hostnames in this cert
|
||||
const inUseResult = await internalHost.getHostsWithDomains(certificate.domain_names);
|
||||
const inUseResult = await internalHost.getHostsWithDomains(
|
||||
certificate.domain_names,
|
||||
);
|
||||
|
||||
// 2. Disable them in nginx temporarily
|
||||
await internalCertificate.disableInUseHosts(inUseResult);
|
||||
|
||||
const user = await userModel.query().where("is_deleted", 0).andWhere("id", data.owner_user_id).first();
|
||||
const user = await userModel
|
||||
.query()
|
||||
.where("is_deleted", 0)
|
||||
.andWhere("id", data.owner_user_id)
|
||||
.first();
|
||||
if (!user || !user.email) {
|
||||
throw new error.ValidationError(
|
||||
"A valid email address must be set on your user account to use Let's Encrypt",
|
||||
@@ -149,7 +167,10 @@ const internalCertificate = {
|
||||
try {
|
||||
await internalNginx.reload();
|
||||
// 4. Request cert
|
||||
await internalCertificate.requestLetsEncryptSslWithDnsChallenge(certificate, user.email);
|
||||
await internalCertificate.requestLetsEncryptSslWithDnsChallenge(
|
||||
certificate,
|
||||
user.email,
|
||||
);
|
||||
await internalNginx.reload();
|
||||
// 6. Re-instate previously disabled hosts
|
||||
await internalCertificate.enableInUseHosts(inUseResult);
|
||||
@@ -166,7 +187,10 @@ const internalCertificate = {
|
||||
await internalNginx.reload();
|
||||
setTimeout(() => {}, 5000);
|
||||
// 4. Request cert
|
||||
await internalCertificate.requestLetsEncryptSsl(certificate, user.email);
|
||||
await internalCertificate.requestLetsEncryptSsl(
|
||||
certificate,
|
||||
user.email,
|
||||
);
|
||||
// 5. Remove LE config
|
||||
await internalNginx.deleteLetsEncryptRequestConfig(certificate);
|
||||
await internalNginx.reload();
|
||||
@@ -190,7 +214,9 @@ const internalCertificate = {
|
||||
const savedRow = await certificateModel
|
||||
.query()
|
||||
.patchAndFetchById(certificate.id, {
|
||||
expires_on: moment(certInfo.dates.to, "X").format("YYYY-MM-DD HH:mm:ss"),
|
||||
expires_on: moment(certInfo.dates.to, "X").format(
|
||||
"YYYY-MM-DD HH:mm:ss",
|
||||
),
|
||||
})
|
||||
.then(utils.omitRow(omissions()));
|
||||
|
||||
@@ -205,6 +231,11 @@ const internalCertificate = {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
// Delete the certificate here. This is a hard delete, since it never existed properly
|
||||
await certificateModel.query().deleteById(certificate.id);
|
||||
throw err;
|
||||
}
|
||||
|
||||
data.meta = _.assign({}, data.meta || {}, certificate.meta);
|
||||
|
||||
@@ -313,7 +344,9 @@ const internalCertificate = {
|
||||
if (certificate.provider === "letsencrypt") {
|
||||
const zipDirectory = internalCertificate.getLiveCertPath(data.id);
|
||||
if (!fs.existsSync(zipDirectory)) {
|
||||
throw new error.ItemNotFoundError(`Certificate ${certificate.nice_name} does not exists`);
|
||||
throw new error.ItemNotFoundError(
|
||||
`Certificate ${certificate.nice_name} does not exists`,
|
||||
);
|
||||
}
|
||||
|
||||
const certFiles = fs
|
||||
@@ -330,7 +363,9 @@ const internalCertificate = {
|
||||
fileName: opName,
|
||||
};
|
||||
}
|
||||
throw new error.ValidationError("Only Let'sEncrypt certificates can be downloaded");
|
||||
throw new error.ValidationError(
|
||||
"Only Let'sEncrypt certificates can be downloaded",
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -435,7 +470,10 @@ const internalCertificate = {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
getCount: async (userId, visibility) => {
|
||||
const query = certificateModel.query().count("id as count").where("is_deleted", 0);
|
||||
const query = certificateModel
|
||||
.query()
|
||||
.count("id as count")
|
||||
.where("is_deleted", 0);
|
||||
|
||||
if (visibility !== "all") {
|
||||
query.andWhere("owner_user_id", userId);
|
||||
@@ -483,13 +521,17 @@ const internalCertificate = {
|
||||
});
|
||||
}).then(() => {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.writeFile(`${dir}/privkey.pem`, certificate.meta.certificate_key, (err) => {
|
||||
fs.writeFile(
|
||||
`${dir}/privkey.pem`,
|
||||
certificate.meta.certificate_key,
|
||||
(err) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
},
|
||||
@@ -562,7 +604,9 @@ const internalCertificate = {
|
||||
upload: async (access, data) => {
|
||||
const row = await internalCertificate.get(access, { id: data.id });
|
||||
if (row.provider !== "other") {
|
||||
throw new error.ValidationError("Cannot upload certificates for this type of provider");
|
||||
throw new error.ValidationError(
|
||||
"Cannot upload certificates for this type of provider",
|
||||
);
|
||||
}
|
||||
|
||||
const validations = await internalCertificate.validate(data);
|
||||
@@ -578,7 +622,9 @@ const internalCertificate = {
|
||||
|
||||
const certificate = await internalCertificate.update(access, {
|
||||
id: data.id,
|
||||
expires_on: moment(validations.certificate.dates.to, "X").format("YYYY-MM-DD HH:mm:ss"),
|
||||
expires_on: moment(validations.certificate.dates.to, "X").format(
|
||||
"YYYY-MM-DD HH:mm:ss",
|
||||
),
|
||||
domain_names: [validations.certificate.cn],
|
||||
meta: _.clone(row.meta), // Prevent the update method from changing this value that we'll use later
|
||||
});
|
||||
@@ -603,7 +649,9 @@ const internalCertificate = {
|
||||
}, 10000);
|
||||
|
||||
try {
|
||||
const result = await utils.exec(`openssl pkey -in ${filepath} -check -noout 2>&1 `);
|
||||
const result = await utils.exec(
|
||||
`openssl pkey -in ${filepath} -check -noout 2>&1 `,
|
||||
);
|
||||
clearTimeout(failTimeout);
|
||||
if (!result.toLowerCase().includes("key is valid")) {
|
||||
throw new error.ValidationError(`Result Validation Error: ${result}`);
|
||||
@@ -613,7 +661,10 @@ const internalCertificate = {
|
||||
} catch (err) {
|
||||
clearTimeout(failTimeout);
|
||||
fs.unlinkSync(filepath);
|
||||
throw new error.ValidationError(`Certificate Key is not valid (${err.message})`, err);
|
||||
throw new error.ValidationError(
|
||||
`Certificate Key is not valid (${err.message})`,
|
||||
err,
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -627,7 +678,10 @@ const internalCertificate = {
|
||||
getCertificateInfo: async (certificate, throwExpired) => {
|
||||
try {
|
||||
const filepath = await tempWrite(certificate, "/tmp");
|
||||
const certData = await internalCertificate.getCertificateInfoFromFile(filepath, throwExpired);
|
||||
const certData = await internalCertificate.getCertificateInfoFromFile(
|
||||
filepath,
|
||||
throwExpired,
|
||||
);
|
||||
fs.unlinkSync(filepath);
|
||||
return certData;
|
||||
} catch (err) {
|
||||
@@ -647,7 +701,13 @@ const internalCertificate = {
|
||||
const certData = {};
|
||||
|
||||
try {
|
||||
const result = await utils.execFile("openssl", ["x509", "-in", certificateFile, "-subject", "-noout"]);
|
||||
const result = await utils.execFile("openssl", [
|
||||
"x509",
|
||||
"-in",
|
||||
certificateFile,
|
||||
"-subject",
|
||||
"-noout",
|
||||
]);
|
||||
// Examples:
|
||||
// subject=CN = *.jc21.com
|
||||
// subject=CN = something.example.com
|
||||
@@ -657,7 +717,13 @@ const internalCertificate = {
|
||||
certData.cn = match[1];
|
||||
}
|
||||
|
||||
const result2 = await utils.execFile("openssl", ["x509", "-in", certificateFile, "-issuer", "-noout"]);
|
||||
const result2 = await utils.execFile("openssl", [
|
||||
"x509",
|
||||
"-in",
|
||||
certificateFile,
|
||||
"-issuer",
|
||||
"-noout",
|
||||
]);
|
||||
// Examples:
|
||||
// issuer=C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
|
||||
// issuer=C = US, O = Let's Encrypt, CN = E5
|
||||
@@ -668,7 +734,13 @@ const internalCertificate = {
|
||||
certData.issuer = match2[1];
|
||||
}
|
||||
|
||||
const result3 = await utils.execFile("openssl", ["x509", "-in", certificateFile, "-dates", "-noout"]);
|
||||
const result3 = await utils.execFile("openssl", [
|
||||
"x509",
|
||||
"-in",
|
||||
certificateFile,
|
||||
"-dates",
|
||||
"-noout",
|
||||
]);
|
||||
// notBefore=Jul 14 04:04:29 2018 GMT
|
||||
// notAfter=Oct 12 04:04:29 2018 GMT
|
||||
let validFrom = null;
|
||||
@@ -680,7 +752,10 @@ const internalCertificate = {
|
||||
const match = regex.exec(str.trim());
|
||||
|
||||
if (match && typeof match[2] !== "undefined") {
|
||||
const date = Number.parseInt(moment(match[2], "MMM DD HH:mm:ss YYYY z").format("X"), 10);
|
||||
const date = Number.parseInt(
|
||||
moment(match[2], "MMM DD HH:mm:ss YYYY z").format("X"),
|
||||
10,
|
||||
);
|
||||
|
||||
if (match[1].toLowerCase() === "notbefore") {
|
||||
validFrom = date;
|
||||
@@ -692,10 +767,15 @@ const internalCertificate = {
|
||||
});
|
||||
|
||||
if (!validFrom || !validTo) {
|
||||
throw new error.ValidationError(`Could not determine dates from certificate: ${result}`);
|
||||
throw new error.ValidationError(
|
||||
`Could not determine dates from certificate: ${result}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (throw_expired && validTo < Number.parseInt(moment().format("X"), 10)) {
|
||||
if (
|
||||
throw_expired &&
|
||||
validTo < Number.parseInt(moment().format("X"), 10)
|
||||
) {
|
||||
throw new error.ValidationError("Certificate has expired");
|
||||
}
|
||||
|
||||
@@ -706,7 +786,10 @@ const internalCertificate = {
|
||||
|
||||
return certData;
|
||||
} catch (err) {
|
||||
throw new error.ValidationError(`Certificate is not valid (${err.message})`, err);
|
||||
throw new error.ValidationError(
|
||||
`Certificate is not valid (${err.message})`,
|
||||
err,
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -787,7 +870,11 @@ const internalCertificate = {
|
||||
|
||||
const credentialsLocation = `/etc/letsencrypt/credentials/credentials-${certificate.id}`;
|
||||
fs.mkdirSync("/etc/letsencrypt/credentials", { recursive: true });
|
||||
fs.writeFileSync(credentialsLocation, certificate.meta.dns_provider_credentials, { mode: 0o600 });
|
||||
fs.writeFileSync(
|
||||
credentialsLocation,
|
||||
certificate.meta.dns_provider_credentials,
|
||||
{ mode: 0o600 },
|
||||
);
|
||||
|
||||
// Whether the plugin has a --<name>-credentials argument
|
||||
const hasConfigArg = certificate.meta.dns_provider !== "route53";
|
||||
@@ -812,7 +899,10 @@ const internalCertificate = {
|
||||
];
|
||||
|
||||
if (hasConfigArg) {
|
||||
args.push(`--${dnsPlugin.full_plugin_name}-credentials`, credentialsLocation);
|
||||
args.push(
|
||||
`--${dnsPlugin.full_plugin_name}-credentials`,
|
||||
credentialsLocation,
|
||||
);
|
||||
}
|
||||
if (certificate.meta.propagation_seconds !== undefined) {
|
||||
args.push(
|
||||
@@ -821,7 +911,10 @@ const internalCertificate = {
|
||||
);
|
||||
}
|
||||
|
||||
const adds = internalCertificate.getAdditionalCertbotArgs(certificate.id, certificate.meta.dns_provider);
|
||||
const adds = internalCertificate.getAdditionalCertbotArgs(
|
||||
certificate.id,
|
||||
certificate.meta.dns_provider,
|
||||
);
|
||||
args.push(...adds.args);
|
||||
|
||||
logger.info(`Command: ${certbotCommand} ${args ? args.join(" ") : ""}`);
|
||||
@@ -857,8 +950,12 @@ const internalCertificate = {
|
||||
`${internalCertificate.getLiveCertPath(certificate.id)}/fullchain.pem`,
|
||||
);
|
||||
|
||||
const updatedCertificate = await certificateModel.query().patchAndFetchById(certificate.id, {
|
||||
expires_on: moment(certInfo.dates.to, "X").format("YYYY-MM-DD HH:mm:ss"),
|
||||
const updatedCertificate = await certificateModel
|
||||
.query()
|
||||
.patchAndFetchById(certificate.id, {
|
||||
expires_on: moment(certInfo.dates.to, "X").format(
|
||||
"YYYY-MM-DD HH:mm:ss",
|
||||
),
|
||||
});
|
||||
|
||||
// Add to audit log
|
||||
@@ -869,7 +966,9 @@ const internalCertificate = {
|
||||
meta: updatedCertificate,
|
||||
});
|
||||
} else {
|
||||
throw new error.ValidationError("Only Let'sEncrypt certificates can be renewed");
|
||||
throw new error.ValidationError(
|
||||
"Only Let'sEncrypt certificates can be renewed",
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -899,7 +998,10 @@ const internalCertificate = {
|
||||
"--disable-hook-validation",
|
||||
];
|
||||
|
||||
const adds = internalCertificate.getAdditionalCertbotArgs(certificate.id, certificate.meta.dns_provider);
|
||||
const adds = internalCertificate.getAdditionalCertbotArgs(
|
||||
certificate.id,
|
||||
certificate.meta.dns_provider,
|
||||
);
|
||||
args.push(...adds.args);
|
||||
|
||||
logger.info(`Command: ${certbotCommand} ${args ? args.join(" ") : ""}`);
|
||||
@@ -938,7 +1040,10 @@ const internalCertificate = {
|
||||
"--no-random-sleep-on-renew",
|
||||
];
|
||||
|
||||
const adds = internalCertificate.getAdditionalCertbotArgs(certificate.id, certificate.meta.dns_provider);
|
||||
const adds = internalCertificate.getAdditionalCertbotArgs(
|
||||
certificate.id,
|
||||
certificate.meta.dns_provider,
|
||||
);
|
||||
args.push(...adds.args);
|
||||
|
||||
logger.info(`Command: ${certbotCommand} ${args ? args.join(" ") : ""}`);
|
||||
@@ -978,7 +1083,9 @@ const internalCertificate = {
|
||||
|
||||
try {
|
||||
const result = await utils.execFile(certbotCommand, args, adds.opts);
|
||||
await utils.exec(`rm -f '/etc/letsencrypt/credentials/credentials-${certificate.id}' || true`);
|
||||
await utils.exec(
|
||||
`rm -f '/etc/letsencrypt/credentials/credentials-${certificate.id}' || true`,
|
||||
);
|
||||
logger.info(result);
|
||||
return result;
|
||||
} catch (err) {
|
||||
@@ -995,7 +1102,10 @@ const internalCertificate = {
|
||||
*/
|
||||
hasLetsEncryptSslCerts: (certificate) => {
|
||||
const letsencryptPath = internalCertificate.getLiveCertPath(certificate.id);
|
||||
return fs.existsSync(`${letsencryptPath}/fullchain.pem`) && fs.existsSync(`${letsencryptPath}/privkey.pem`);
|
||||
return (
|
||||
fs.existsSync(`${letsencryptPath}/fullchain.pem`) &&
|
||||
fs.existsSync(`${letsencryptPath}/privkey.pem`)
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -1009,15 +1119,24 @@ const internalCertificate = {
|
||||
disableInUseHosts: async (inUseResult) => {
|
||||
if (inUseResult?.total_count) {
|
||||
if (inUseResult?.proxy_hosts.length) {
|
||||
await internalNginx.bulkDeleteConfigs("proxy_host", inUseResult.proxy_hosts);
|
||||
await internalNginx.bulkDeleteConfigs(
|
||||
"proxy_host",
|
||||
inUseResult.proxy_hosts,
|
||||
);
|
||||
}
|
||||
|
||||
if (inUseResult?.redirection_hosts.length) {
|
||||
await internalNginx.bulkDeleteConfigs("redirection_host", inUseResult.redirection_hosts);
|
||||
await internalNginx.bulkDeleteConfigs(
|
||||
"redirection_host",
|
||||
inUseResult.redirection_hosts,
|
||||
);
|
||||
}
|
||||
|
||||
if (inUseResult?.dead_hosts.length) {
|
||||
await internalNginx.bulkDeleteConfigs("dead_host", inUseResult.dead_hosts);
|
||||
await internalNginx.bulkDeleteConfigs(
|
||||
"dead_host",
|
||||
inUseResult.dead_hosts,
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1033,36 +1152,56 @@ const internalCertificate = {
|
||||
enableInUseHosts: async (inUseResult) => {
|
||||
if (inUseResult.total_count) {
|
||||
if (inUseResult.proxy_hosts.length) {
|
||||
await internalNginx.bulkGenerateConfigs("proxy_host", inUseResult.proxy_hosts);
|
||||
await internalNginx.bulkGenerateConfigs(
|
||||
"proxy_host",
|
||||
inUseResult.proxy_hosts,
|
||||
);
|
||||
}
|
||||
|
||||
if (inUseResult.redirection_hosts.length) {
|
||||
await internalNginx.bulkGenerateConfigs("redirection_host", inUseResult.redirection_hosts);
|
||||
await internalNginx.bulkGenerateConfigs(
|
||||
"redirection_host",
|
||||
inUseResult.redirection_hosts,
|
||||
);
|
||||
}
|
||||
|
||||
if (inUseResult.dead_hosts.length) {
|
||||
await internalNginx.bulkGenerateConfigs("dead_host", inUseResult.dead_hosts);
|
||||
await internalNginx.bulkGenerateConfigs(
|
||||
"dead_host",
|
||||
inUseResult.dead_hosts,
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
testHttpsChallenge: async (access, domains) => {
|
||||
/**
|
||||
*
|
||||
* @param {Object} payload
|
||||
* @param {string[]} payload.domains
|
||||
* @returns
|
||||
*/
|
||||
testHttpsChallenge: async (access, payload) => {
|
||||
await access.can("certificates:list");
|
||||
|
||||
if (!isArray(domains)) {
|
||||
throw new error.InternalValidationError("Domains must be an array of strings");
|
||||
}
|
||||
if (domains.length === 0) {
|
||||
throw new error.InternalValidationError("No domains provided");
|
||||
}
|
||||
|
||||
// Create a test challenge file
|
||||
const testChallengeDir = "/data/letsencrypt-acme-challenge/.well-known/acme-challenge";
|
||||
const testChallengeDir =
|
||||
"/data/letsencrypt-acme-challenge/.well-known/acme-challenge";
|
||||
const testChallengeFile = `${testChallengeDir}/test-challenge`;
|
||||
fs.mkdirSync(testChallengeDir, { recursive: true });
|
||||
fs.writeFileSync(testChallengeFile, "Success", { encoding: "utf8" });
|
||||
|
||||
async function performTestForDomain(domain) {
|
||||
const results = {};
|
||||
for (const domain of payload.domains) {
|
||||
results[domain] = await internalCertificate.performTestForDomain(domain);
|
||||
}
|
||||
|
||||
// Remove the test challenge file
|
||||
fs.unlinkSync(testChallengeFile);
|
||||
|
||||
return results;
|
||||
},
|
||||
|
||||
performTestForDomain: async (domain) => {
|
||||
logger.info(`Testing http challenge for ${domain}`);
|
||||
const url = `http://${domain}/.well-known/acme-challenge/test-challenge`;
|
||||
const formBody = `method=G&url=${encodeURI(url)}&bodytype=T&requestbody=&headername=User-Agent&headervalue=None&locationid=1&ch=false&cc=false`;
|
||||
@@ -1076,7 +1215,10 @@ const internalCertificate = {
|
||||
};
|
||||
|
||||
const result = await new Promise((resolve) => {
|
||||
const req = https.request("https://www.site24x7.com/tools/restapi-tester", options, (res) => {
|
||||
const req = https.request(
|
||||
"https://www.site24x7.com/tools/restapi-tester",
|
||||
options,
|
||||
(res) => {
|
||||
let responseBody = "";
|
||||
|
||||
res.on("data", (chunk) => {
|
||||
@@ -1107,7 +1249,8 @@ const internalCertificate = {
|
||||
resolve(undefined);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
// Make sure to write the request body.
|
||||
req.write(formBody);
|
||||
@@ -1128,7 +1271,10 @@ const internalCertificate = {
|
||||
);
|
||||
return `other:${result.error.msg}`;
|
||||
}
|
||||
if (`${result.responsecode}` === "200" && result.htmlresponse === "Success") {
|
||||
if (
|
||||
`${result.responsecode}` === "200" &&
|
||||
result.htmlresponse === "Success"
|
||||
) {
|
||||
// Server exists and has responded with the correct data
|
||||
return "ok";
|
||||
}
|
||||
@@ -1142,15 +1288,20 @@ const internalCertificate = {
|
||||
}
|
||||
if (`${result.responsecode}` === "404") {
|
||||
// Server exists but responded with a 404
|
||||
logger.info(`HTTP challenge test failed for domain ${domain} because code 404 was returned`);
|
||||
logger.info(
|
||||
`HTTP challenge test failed for domain ${domain} because code 404 was returned`,
|
||||
);
|
||||
return "404";
|
||||
}
|
||||
if (
|
||||
`${result.responsecode}` === "0" ||
|
||||
(typeof result.reason === "string" && result.reason.toLowerCase() === "host unavailable")
|
||||
(typeof result.reason === "string" &&
|
||||
result.reason.toLowerCase() === "host unavailable")
|
||||
) {
|
||||
// Server does not exist at domain
|
||||
logger.info(`HTTP challenge test failed for domain ${domain} the host was not found`);
|
||||
logger.info(
|
||||
`HTTP challenge test failed for domain ${domain} the host was not found`,
|
||||
);
|
||||
return "no-host";
|
||||
}
|
||||
// Other errors
|
||||
@@ -1158,18 +1309,6 @@ const internalCertificate = {
|
||||
`HTTP challenge test failed for domain ${domain} because code ${result.responsecode} was returned`,
|
||||
);
|
||||
return `other:${result.responsecode}`;
|
||||
}
|
||||
|
||||
const results = {};
|
||||
|
||||
for (const domain of domains) {
|
||||
results[domain] = await performTestForDomain(domain);
|
||||
}
|
||||
|
||||
// Remove the test challenge file
|
||||
fs.unlinkSync(testChallengeFile);
|
||||
|
||||
return results;
|
||||
},
|
||||
|
||||
getAdditionalCertbotArgs: (certificate_id, dns_provider) => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import batchflow from "batchflow";
|
||||
import dnsPlugins from "../global/certbot-dns-plugins.json" with { type: "json" };
|
||||
import dnsPlugins from "../certbot/dns-plugins.json" with { type: "json" };
|
||||
import { certbot as logger } from "../logger.js";
|
||||
import errs from "./error.js";
|
||||
import utils from "./utils.js";
|
||||
@@ -8,7 +8,7 @@ const CERTBOT_VERSION_REPLACEMENT = "$(certbot --version | grep -Eo '[0-9](\\.[0
|
||||
|
||||
/**
|
||||
* Installs a cerbot plugin given the key for the object from
|
||||
* ../global/certbot-dns-plugins.json
|
||||
* ../certbot/dns-plugins.json
|
||||
*
|
||||
* @param {string} pluginKey
|
||||
* @returns {Object}
|
||||
|
||||
@@ -24,16 +24,21 @@ const apiValidator = async (schema, payload /*, description*/) => {
|
||||
throw new errs.ValidationError("Payload is undefined");
|
||||
}
|
||||
|
||||
|
||||
const validate = ajv.compile(schema);
|
||||
|
||||
const valid = validate(payload);
|
||||
|
||||
|
||||
if (valid && !validate.errors) {
|
||||
return payload;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const message = ajv.errorsText(validate.errors);
|
||||
const err = new errs.ValidationError(message);
|
||||
err.debug = [validate.errors, payload];
|
||||
err.debug = {validationErrors: validate.errors, payload};
|
||||
throw err;
|
||||
};
|
||||
|
||||
|
||||
@@ -26,19 +26,19 @@
|
||||
"knex": "2.4.2",
|
||||
"liquidjs": "10.6.1",
|
||||
"lodash": "^4.17.21",
|
||||
"moment": "^2.29.4",
|
||||
"mysql2": "^3.11.1",
|
||||
"node-rsa": "^1.0.8",
|
||||
"moment": "^2.30.1",
|
||||
"mysql2": "^3.15.3",
|
||||
"node-rsa": "^1.1.1",
|
||||
"objection": "3.0.1",
|
||||
"path": "^0.12.7",
|
||||
"pg": "^8.13.1",
|
||||
"pg": "^8.16.3",
|
||||
"signale": "1.4.0",
|
||||
"sqlite3": "5.1.6",
|
||||
"sqlite3": "^5.1.7",
|
||||
"temp-write": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@apidevtools/swagger-parser": "^10.1.0",
|
||||
"@biomejs/biome": "^2.2.4",
|
||||
"@biomejs/biome": "^2.3.0",
|
||||
"chalk": "4.1.2",
|
||||
"nodemon": "^2.0.2"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import express from "express";
|
||||
import dnsPlugins from "../../global/certbot-dns-plugins.json" with { type: "json" };
|
||||
import dnsPlugins from "../../certbot/dns-plugins.json" with { type: "json" };
|
||||
import internalCertificate from "../../internal/certificate.js";
|
||||
import errs from "../../lib/error.js";
|
||||
import jwtdecode from "../../lib/express/jwt-decode.js";
|
||||
@@ -44,11 +44,18 @@ router
|
||||
},
|
||||
},
|
||||
{
|
||||
expand: typeof req.query.expand === "string" ? req.query.expand.split(",") : null,
|
||||
expand:
|
||||
typeof req.query.expand === "string"
|
||||
? req.query.expand.split(",")
|
||||
: null,
|
||||
query: typeof req.query.query === "string" ? req.query.query : null,
|
||||
},
|
||||
);
|
||||
const rows = await internalCertificate.getAll(res.locals.access, data.expand, data.query);
|
||||
const rows = await internalCertificate.getAll(
|
||||
res.locals.access,
|
||||
data.expand,
|
||||
data.query,
|
||||
);
|
||||
res.status(200).send(rows);
|
||||
} catch (err) {
|
||||
logger.debug(`${req.method.toUpperCase()} ${req.path}: ${err}`);
|
||||
@@ -63,9 +70,15 @@ router
|
||||
*/
|
||||
.post(async (req, res, next) => {
|
||||
try {
|
||||
const payload = await apiValidator(getValidationSchema("/nginx/certificates", "post"), req.body);
|
||||
const payload = await apiValidator(
|
||||
getValidationSchema("/nginx/certificates", "post"),
|
||||
req.body,
|
||||
);
|
||||
req.setTimeout(900000); // 15 minutes timeout
|
||||
const result = await internalCertificate.create(res.locals.access, payload);
|
||||
const result = await internalCertificate.create(
|
||||
res.locals.access,
|
||||
payload,
|
||||
);
|
||||
res.status(201).send(result);
|
||||
} catch (err) {
|
||||
logger.debug(`${req.method.toUpperCase()} ${req.path}: ${err}`);
|
||||
@@ -120,20 +133,21 @@ router
|
||||
.all(jwtdecode())
|
||||
|
||||
/**
|
||||
* GET /api/nginx/certificates/test-http
|
||||
* POST /api/nginx/certificates/test-http
|
||||
*
|
||||
* Test HTTP challenge for domains
|
||||
*/
|
||||
.get(async (req, res, next) => {
|
||||
if (req.query.domains === undefined) {
|
||||
next(new errs.ValidationError("Domains are required as query parameters"));
|
||||
return;
|
||||
}
|
||||
|
||||
.post(async (req, res, next) => {
|
||||
try {
|
||||
const payload = await apiValidator(
|
||||
getValidationSchema("/nginx/certificates/test-http", "post"),
|
||||
req.body,
|
||||
);
|
||||
req.setTimeout(60000); // 1 minute timeout
|
||||
|
||||
const result = await internalCertificate.testHttpsChallenge(
|
||||
res.locals.access,
|
||||
JSON.parse(req.query.domains),
|
||||
payload,
|
||||
);
|
||||
res.status(200).send(result);
|
||||
} catch (err) {
|
||||
@@ -142,7 +156,6 @@ router
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Validate Certs before saving
|
||||
*
|
||||
@@ -211,7 +224,10 @@ router
|
||||
},
|
||||
{
|
||||
certificate_id: req.params.certificate_id,
|
||||
expand: typeof req.query.expand === "string" ? req.query.expand.split(",") : null,
|
||||
expand:
|
||||
typeof req.query.expand === "string"
|
||||
? req.query.expand.split(",")
|
||||
: null,
|
||||
},
|
||||
);
|
||||
const row = await internalCertificate.get(res.locals.access, {
|
||||
|
||||
@@ -65,7 +65,7 @@ router
|
||||
const result = await internalProxyHost.create(res.locals.access, payload);
|
||||
res.status(201).send(result);
|
||||
} catch (err) {
|
||||
logger.debug(`${req.method.toUpperCase()} ${req.path}: ${err}`);
|
||||
logger.debug(`${req.method.toUpperCase()} ${req.path}: ${err} ${JSON.stringify(err.debug, null, 2)}`);
|
||||
next(err);
|
||||
}
|
||||
});
|
||||
|
||||
23
backend/schema/components/dns-providers-list.json
Normal file
23
backend/schema/components/dns-providers-list.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"type": "array",
|
||||
"description": "DNS Providers list",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["id", "name", "credentials"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Unique identifier for the DNS provider, matching the python package"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Human-readable name of the DNS provider"
|
||||
},
|
||||
"credentials": {
|
||||
"type": "string",
|
||||
"description": "Instructions on how to format the credentials for this DNS provider"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"operationId": "getDNSProviders",
|
||||
"summary": "Get DNS Providers for Certificates",
|
||||
"tags": [
|
||||
"Certificates"
|
||||
],
|
||||
"security": [
|
||||
{
|
||||
"BearerAuth": [
|
||||
"certificates"
|
||||
]
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "200 response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"examples": {
|
||||
"default": {
|
||||
"value": [
|
||||
{
|
||||
"id": "vultr",
|
||||
"name": "Vultr",
|
||||
"credentials": "dns_vultr_key = YOUR_VULTR_API_KEY"
|
||||
},
|
||||
{
|
||||
"id": "websupport",
|
||||
"name": "Websupport.sk",
|
||||
"credentials": "dns_websupport_identifier = <api_key>\ndns_websupport_secret_key = <secret>"
|
||||
},
|
||||
{
|
||||
"id": "wedos",
|
||||
"name": "Wedos",
|
||||
"credentials": "dns_wedos_user = <wedos_registration>\ndns_wedos_auth = <wapi_password>"
|
||||
},
|
||||
{
|
||||
"id": "zoneedit",
|
||||
"name": "ZoneEdit",
|
||||
"credentials": "dns_zoneedit_user = <login-user-id>\ndns_zoneedit_token = <dyn-authentication-token>"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"schema": {
|
||||
"$ref": "../../../../components/dns-providers-list.json"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,18 +7,24 @@
|
||||
"BearerAuth": ["certificates"]
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
"name": "domains",
|
||||
"description": "Expansions",
|
||||
"requestBody": {
|
||||
"description": "Test Payload",
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"example": "[\"test.example.ord\",\"test.example.com\",\"nonexistent.example.com\"]"
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["domains"],
|
||||
"properties": {
|
||||
"domains": {
|
||||
"$ref": "../../../../common.json#/properties/domain_names"
|
||||
}
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "200 response",
|
||||
@@ -61,14 +61,19 @@
|
||||
"$ref": "./paths/nginx/certificates/post.json"
|
||||
}
|
||||
},
|
||||
"/nginx/certificates/dns-providers": {
|
||||
"get": {
|
||||
"$ref": "./paths/nginx/certificates/dns-providers/get.json"
|
||||
}
|
||||
},
|
||||
"/nginx/certificates/validate": {
|
||||
"post": {
|
||||
"$ref": "./paths/nginx/certificates/validate/post.json"
|
||||
}
|
||||
},
|
||||
"/nginx/certificates/test-http": {
|
||||
"get": {
|
||||
"$ref": "./paths/nginx/certificates/test-http/get.json"
|
||||
"post": {
|
||||
"$ref": "./paths/nginx/certificates/test-http/post.json"
|
||||
}
|
||||
},
|
||||
"/nginx/certificates/{certID}": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/node
|
||||
|
||||
// Usage:
|
||||
// Install all plugins defined in `certbot-dns-plugins.json`:
|
||||
// Install all plugins defined in `../certbot/dns-plugins.json`:
|
||||
// ./install-certbot-plugins
|
||||
// Install one or more specific plugins:
|
||||
// ./install-certbot-plugins route53 cloudflare
|
||||
@@ -10,20 +10,21 @@
|
||||
// docker exec npm_core /command/s6-setuidgid 1000:1000 bash -c "/app/scripts/install-certbot-plugins"
|
||||
//
|
||||
|
||||
import dnsPlugins from "../global/certbot-dns-plugins.json" with { type: "json" };
|
||||
import batchflow from "batchflow";
|
||||
import dnsPlugins from "../certbot/dns-plugins.json" with { type: "json" };
|
||||
import { installPlugin } from "../lib/certbot.js";
|
||||
import { certbot as logger } from "../logger.js";
|
||||
import batchflow from "batchflow";
|
||||
|
||||
let hasErrors = false;
|
||||
let failingPlugins = [];
|
||||
const failingPlugins = [];
|
||||
|
||||
let pluginKeys = Object.keys(dnsPlugins);
|
||||
if (process.argv.length > 2) {
|
||||
pluginKeys = process.argv.slice(2);
|
||||
}
|
||||
|
||||
batchflow(pluginKeys).sequential()
|
||||
batchflow(pluginKeys)
|
||||
.sequential()
|
||||
.each((i, pluginKey, next) => {
|
||||
installPlugin(pluginKey)
|
||||
.then(() => {
|
||||
@@ -40,10 +41,14 @@ batchflow(pluginKeys).sequential()
|
||||
})
|
||||
.end(() => {
|
||||
if (hasErrors) {
|
||||
logger.error('Some plugins failed to install. Please check the logs above. Failing plugins: ' + '\n - ' + failingPlugins.join('\n - '));
|
||||
logger.error(
|
||||
"Some plugins failed to install. Please check the logs above. Failing plugins: " +
|
||||
"\n - " +
|
||||
failingPlugins.join("\n - "),
|
||||
);
|
||||
process.exit(1);
|
||||
} else {
|
||||
logger.complete('Plugins installed successfully');
|
||||
logger.complete("Plugins installed successfully");
|
||||
process.exit(0);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -43,59 +43,59 @@
|
||||
ajv-draft-04 "^1.0.0"
|
||||
call-me-maybe "^1.0.2"
|
||||
|
||||
"@biomejs/biome@^2.2.4":
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/biome/-/biome-2.2.4.tgz#184e4b83f89bd0d4151682a5aa3840df37748e17"
|
||||
integrity sha512-TBHU5bUy/Ok6m8c0y3pZiuO/BZoY/OcGxoLlrfQof5s8ISVwbVBdFINPQZyFfKwil8XibYWb7JMwnT8wT4WVPg==
|
||||
"@biomejs/biome@^2.3.0":
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/biome/-/biome-2.3.0.tgz#80030b68d94bd0a0761ac2cd22cc4f2c0f23f4f9"
|
||||
integrity sha512-shdUY5H3S3tJVUWoVWo5ua+GdPW5lRHf+b0IwZ4OC1o2zOKQECZ6l2KbU6t89FNhtd3Qx5eg5N7/UsQWGQbAFw==
|
||||
optionalDependencies:
|
||||
"@biomejs/cli-darwin-arm64" "2.2.4"
|
||||
"@biomejs/cli-darwin-x64" "2.2.4"
|
||||
"@biomejs/cli-linux-arm64" "2.2.4"
|
||||
"@biomejs/cli-linux-arm64-musl" "2.2.4"
|
||||
"@biomejs/cli-linux-x64" "2.2.4"
|
||||
"@biomejs/cli-linux-x64-musl" "2.2.4"
|
||||
"@biomejs/cli-win32-arm64" "2.2.4"
|
||||
"@biomejs/cli-win32-x64" "2.2.4"
|
||||
"@biomejs/cli-darwin-arm64" "2.3.0"
|
||||
"@biomejs/cli-darwin-x64" "2.3.0"
|
||||
"@biomejs/cli-linux-arm64" "2.3.0"
|
||||
"@biomejs/cli-linux-arm64-musl" "2.3.0"
|
||||
"@biomejs/cli-linux-x64" "2.3.0"
|
||||
"@biomejs/cli-linux-x64-musl" "2.3.0"
|
||||
"@biomejs/cli-win32-arm64" "2.3.0"
|
||||
"@biomejs/cli-win32-x64" "2.3.0"
|
||||
|
||||
"@biomejs/cli-darwin-arm64@2.2.4":
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.2.4.tgz#9b50620c93501e370b7e6d5a8445f117f9946a0c"
|
||||
integrity sha512-RJe2uiyaloN4hne4d2+qVj3d3gFJFbmrr5PYtkkjei1O9c+BjGXgpUPVbi8Pl8syumhzJjFsSIYkcLt2VlVLMA==
|
||||
"@biomejs/cli-darwin-arm64@2.3.0":
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.3.0.tgz#78cef4d7415adbf0718c7854e7160e181d916652"
|
||||
integrity sha512-3cJVT0Z5pbTkoBmbjmDZTDFYxIkRcrs9sYVJbIBHU8E6qQxgXAaBfSVjjCreG56rfDuQBr43GzwzmaHPcu4vlw==
|
||||
|
||||
"@biomejs/cli-darwin-x64@2.2.4":
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.2.4.tgz#343620c884fc8141155d114430e80e4eacfddc9e"
|
||||
integrity sha512-cFsdB4ePanVWfTnPVaUX+yr8qV8ifxjBKMkZwN7gKb20qXPxd/PmwqUH8mY5wnM9+U0QwM76CxFyBRJhC9tQwg==
|
||||
"@biomejs/cli-darwin-x64@2.3.0":
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.3.0.tgz#068baf1f0f748c01658ba9bb511d8d18461d922b"
|
||||
integrity sha512-6LIkhglh3UGjuDqJXsK42qCA0XkD1Ke4K/raFOii7QQPbM8Pia7Qj2Hji4XuF2/R78hRmEx7uKJH3t/Y9UahtQ==
|
||||
|
||||
"@biomejs/cli-linux-arm64-musl@2.2.4":
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.2.4.tgz#cabcdadce2bc88b697f4063374224266c6f8b6e5"
|
||||
integrity sha512-7TNPkMQEWfjvJDaZRSkDCPT/2r5ESFPKx+TEev+I2BXDGIjfCZk2+b88FOhnJNHtksbOZv8ZWnxrA5gyTYhSsQ==
|
||||
"@biomejs/cli-linux-arm64-musl@2.3.0":
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.3.0.tgz#9a1350184abcea8092957a9519098cac7629705a"
|
||||
integrity sha512-nDksoFdwZ2YrE7NiYDhtMhL2UgFn8Kb7Y0bYvnTAakHnqEdb4lKindtBc1f+xg2Snz0JQhJUYO7r9CDBosRU5w==
|
||||
|
||||
"@biomejs/cli-linux-arm64@2.2.4":
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.2.4.tgz#55620f8f088145e62e1158eb85c568554d0c8673"
|
||||
integrity sha512-M/Iz48p4NAzMXOuH+tsn5BvG/Jb07KOMTdSVwJpicmhN309BeEyRyQX+n1XDF0JVSlu28+hiTQ2L4rZPvu7nMw==
|
||||
"@biomejs/cli-linux-arm64@2.3.0":
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.3.0.tgz#f322daebb32fe0b18f7981c8cdbe84a06852bfee"
|
||||
integrity sha512-uhAsbXySX7xsXahegDg5h3CDgfMcRsJvWLFPG0pjkylgBb9lErbK2C0UINW52zhwg0cPISB09lxHPxCau4e2xA==
|
||||
|
||||
"@biomejs/cli-linux-x64-musl@2.2.4":
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.2.4.tgz#6bfaea72505afdbda66a66c998d2d169a8b55f90"
|
||||
integrity sha512-m41nFDS0ksXK2gwXL6W6yZTYPMH0LughqbsxInSKetoH6morVj43szqKx79Iudkp8WRT5SxSh7qVb8KCUiewGg==
|
||||
"@biomejs/cli-linux-x64-musl@2.3.0":
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.3.0.tgz#ce441d5c00eda977b74e4116f9723f2edc579485"
|
||||
integrity sha512-+i9UcJwl99uAhtRQDz9jUAh+Xkb097eekxs/D9j4deWDg5/yB/jPWzISe1nBHvlzTXsdUSj0VvB4Go2DSpKIMw==
|
||||
|
||||
"@biomejs/cli-linux-x64@2.2.4":
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-x64/-/cli-linux-x64-2.2.4.tgz#8c1ed61dcafb8a5939346c714ec122651f57e1db"
|
||||
integrity sha512-orr3nnf2Dpb2ssl6aihQtvcKtLySLta4E2UcXdp7+RTa7mfJjBgIsbS0B9GC8gVu0hjOu021aU8b3/I1tn+pVQ==
|
||||
"@biomejs/cli-linux-x64@2.3.0":
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-x64/-/cli-linux-x64-2.3.0.tgz#da7ea904307b3211df62a4b42e5a022f8f583009"
|
||||
integrity sha512-uxa8reA2s1VgoH8MhbGlCmMOt3JuSE1vJBifkh1ulaPiuk0SPx8cCdpnm9NWnTe2x/LfWInWx4sZ7muaXTPGGw==
|
||||
|
||||
"@biomejs/cli-win32-arm64@2.2.4":
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.2.4.tgz#b2528f6c436e753d6083d7779f0662e08786cedb"
|
||||
integrity sha512-NXnfTeKHDFUWfxAefa57DiGmu9VyKi0cDqFpdI+1hJWQjGJhJutHPX0b5m+eXvTKOaf+brU+P0JrQAZMb5yYaQ==
|
||||
"@biomejs/cli-win32-arm64@2.3.0":
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.3.0.tgz#cdc0f8bbf025fb28c5b03b326128cce363ecffa5"
|
||||
integrity sha512-ynjmsJLIKrAjC3CCnKMMhzcnNy8dbQWjKfSU5YA0mIruTxBNMbkAJp+Pr2iV7/hFou+66ZSD/WV8hmLEmhUaXA==
|
||||
|
||||
"@biomejs/cli-win32-x64@2.2.4":
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-win32-x64/-/cli-win32-x64-2.2.4.tgz#c8e21413120fe073fa49b78fdd987022941ff66f"
|
||||
integrity sha512-3Y4V4zVRarVh/B/eSHczR4LYoSVyv3Dfuvm3cWs5w/HScccS0+Wt/lHOcDTRYeHjQmMYVC3rIRWqyN2EI52+zg==
|
||||
"@biomejs/cli-win32-x64@2.3.0":
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-win32-x64/-/cli-win32-x64-2.3.0.tgz#10e1de6222e272a1e3e395b3d845ee66cb6febd8"
|
||||
integrity sha512-zOCYmCRVkWXc9v8P7OLbLlGGMxQTKMvi+5IC4v7O8DkjLCOHRzRVK/Lno2pGZNo0lzKM60pcQOhH8HVkXMQdFg==
|
||||
|
||||
"@gar/promisify@^1.0.1":
|
||||
version "1.1.3"
|
||||
@@ -107,7 +107,7 @@
|
||||
resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796"
|
||||
integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==
|
||||
|
||||
"@mapbox/node-pre-gyp@^1.0.0", "@mapbox/node-pre-gyp@^1.0.11":
|
||||
"@mapbox/node-pre-gyp@^1.0.11":
|
||||
version "1.0.11"
|
||||
resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz#417db42b7f5323d79e93b34a6d7a2a12c0df43fa"
|
||||
integrity sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==
|
||||
@@ -346,6 +346,13 @@ binary-extensions@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522"
|
||||
integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==
|
||||
|
||||
bindings@^1.5.0:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df"
|
||||
integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==
|
||||
dependencies:
|
||||
file-uri-to-path "1.0.0"
|
||||
|
||||
bl@^4.0.3:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a"
|
||||
@@ -512,6 +519,11 @@ chokidar@^3.5.2:
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
chownr@^1.1.1:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
|
||||
integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
|
||||
|
||||
chownr@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
|
||||
@@ -693,6 +705,18 @@ decamelize@^1.2.0:
|
||||
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
|
||||
integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==
|
||||
|
||||
decompress-response@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc"
|
||||
integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==
|
||||
dependencies:
|
||||
mimic-response "^3.1.0"
|
||||
|
||||
deep-extend@^0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
|
||||
integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
|
||||
|
||||
delegates@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
|
||||
@@ -766,7 +790,7 @@ encoding@^0.1.12:
|
||||
dependencies:
|
||||
iconv-lite "^0.6.2"
|
||||
|
||||
end-of-stream@^1.4.1:
|
||||
end-of-stream@^1.1.0, end-of-stream@^1.4.1:
|
||||
version "1.4.5"
|
||||
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.5.tgz#7344d711dea40e0b74abc2ed49778743ccedb08c"
|
||||
integrity sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==
|
||||
@@ -832,6 +856,11 @@ etag@~1.8.1:
|
||||
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
|
||||
integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
|
||||
|
||||
expand-template@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c"
|
||||
integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==
|
||||
|
||||
express-fileupload@^1.1.9:
|
||||
version "1.5.2"
|
||||
resolved "https://registry.yarnpkg.com/express-fileupload/-/express-fileupload-1.5.2.tgz#4da70ba6f2ffd4c736eab0776445865a9dbd9bfa"
|
||||
@@ -893,6 +922,11 @@ figures@^2.0.0:
|
||||
dependencies:
|
||||
escape-string-regexp "^1.0.5"
|
||||
|
||||
file-uri-to-path@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
|
||||
integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
|
||||
|
||||
fill-range@^7.1.1:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
|
||||
@@ -1040,6 +1074,11 @@ getopts@2.3.0:
|
||||
resolved "https://registry.yarnpkg.com/getopts/-/getopts-2.3.0.tgz#71e5593284807e03e2427449d4f6712a268666f4"
|
||||
integrity sha512-5eDf9fuSXwxBL6q5HX+dhDj+dslFGWzU5thZ9kNKUkcPtaPdatmUFKwHFrLb/uf/WpA4BHET+AX3Scl56cAjpA==
|
||||
|
||||
github-from-package@0.0.0:
|
||||
version "0.0.0"
|
||||
resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce"
|
||||
integrity sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==
|
||||
|
||||
glob-parent@~5.1.2:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
|
||||
@@ -1210,6 +1249,11 @@ inherits@2.0.3:
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
|
||||
integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==
|
||||
|
||||
ini@~1.3.0:
|
||||
version "1.3.8"
|
||||
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
|
||||
integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
|
||||
|
||||
interpret@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9"
|
||||
@@ -1553,6 +1597,11 @@ mime@1.6.0:
|
||||
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
|
||||
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
|
||||
|
||||
mimic-response@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9"
|
||||
integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==
|
||||
|
||||
minimatch@^3.1.1, minimatch@^3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
@@ -1567,6 +1616,11 @@ minimatch@^5.1.0:
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimist@^1.2.0, minimist@^1.2.3:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
|
||||
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
|
||||
|
||||
minipass-collect@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617"
|
||||
@@ -1626,12 +1680,17 @@ minizlib@^2.0.0, minizlib@^2.1.1:
|
||||
minipass "^3.0.0"
|
||||
yallist "^4.0.0"
|
||||
|
||||
mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3:
|
||||
version "0.5.3"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
|
||||
integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
|
||||
|
||||
mkdirp@^1.0.3, mkdirp@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
|
||||
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
|
||||
|
||||
moment@^2.29.4:
|
||||
moment@^2.30.1:
|
||||
version "2.30.1"
|
||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae"
|
||||
integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==
|
||||
@@ -1651,10 +1710,10 @@ ms@2.1.3, ms@^2.0.0, ms@^2.1.1, ms@^2.1.3:
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||
|
||||
mysql2@^3.11.1:
|
||||
version "3.14.4"
|
||||
resolved "https://registry.yarnpkg.com/mysql2/-/mysql2-3.14.4.tgz#36e33a8d33820a299fb9e9221486310b1a4c8767"
|
||||
integrity sha512-Cs/jx3WZPNrYHVz+Iunp9ziahaG5uFMvD2R8Zlmc194AqXNxt9HBNu7ZsPYrUtmJsF0egETCWIdMIYAwOGjL1w==
|
||||
mysql2@^3.15.3:
|
||||
version "3.15.3"
|
||||
resolved "https://registry.yarnpkg.com/mysql2/-/mysql2-3.15.3.tgz#f0348d9c7401bb98cb1f45ffc5a773b109f70808"
|
||||
integrity sha512-FBrGau0IXmuqg4haEZRBfHNWB5mUARw6hNwPDXXGg0XzVJ50mr/9hb267lvpVMnhZ1FON3qNd4Xfcez1rbFwSg==
|
||||
dependencies:
|
||||
aws-ssl-profiles "^1.1.1"
|
||||
denque "^2.1.0"
|
||||
@@ -1673,6 +1732,11 @@ named-placeholders@^1.1.3:
|
||||
dependencies:
|
||||
lru-cache "^7.14.1"
|
||||
|
||||
napi-build-utils@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-2.0.0.tgz#13c22c0187fcfccce1461844136372a47ddc027e"
|
||||
integrity sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==
|
||||
|
||||
negotiator@0.6.3:
|
||||
version "0.6.3"
|
||||
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
|
||||
@@ -1683,16 +1747,23 @@ negotiator@^0.6.2, negotiator@~0.6.4:
|
||||
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.4.tgz#777948e2452651c570b712dd01c23e262713fff7"
|
||||
integrity sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==
|
||||
|
||||
node-addon-api@^4.2.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.3.0.tgz#52a1a0b475193e0928e98e0426a0d1254782b77f"
|
||||
integrity sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==
|
||||
node-abi@^3.3.0:
|
||||
version "3.78.0"
|
||||
resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.78.0.tgz#fd0ecbd0aa89857b98da06bd3909194abb0821ba"
|
||||
integrity sha512-E2wEyrgX/CqvicaQYU3Ze1PFGjc4QYPGsjUrlYkqAE0WjHEZwgOsGMPMzkMse4LjJbDmaEuDX3CM036j5K2DSQ==
|
||||
dependencies:
|
||||
semver "^7.3.5"
|
||||
|
||||
node-addon-api@^5.0.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.1.0.tgz#49da1ca055e109a23d537e9de43c09cca21eb762"
|
||||
integrity sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==
|
||||
|
||||
node-addon-api@^7.0.0:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.1.1.tgz#1aba6693b0f255258a049d621329329322aad558"
|
||||
integrity sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==
|
||||
|
||||
node-fetch@^2.6.7:
|
||||
version "2.7.0"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
|
||||
@@ -1716,7 +1787,7 @@ node-gyp@8.x:
|
||||
tar "^6.1.2"
|
||||
which "^2.0.2"
|
||||
|
||||
node-rsa@^1.0.8:
|
||||
node-rsa@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/node-rsa/-/node-rsa-1.1.1.tgz#efd9ad382097782f506153398496f79e4464434d"
|
||||
integrity sha512-Jd4cvbJMryN21r5HgxQOpMEqv+ooke/korixNNK3mGqfGJmy0M77WDDzo/05969+OkMy3XW1UuZsSmW9KQm7Fw==
|
||||
@@ -1801,7 +1872,7 @@ on-headers@~1.1.0:
|
||||
resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.1.0.tgz#59da4f91c45f5f989c6e4bcedc5a3b0aed70ff65"
|
||||
integrity sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==
|
||||
|
||||
once@^1.3.0, once@^1.4.0:
|
||||
once@^1.3.0, once@^1.3.1, once@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||
integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
|
||||
@@ -1940,7 +2011,7 @@ pg-types@2.2.0:
|
||||
postgres-date "~1.0.4"
|
||||
postgres-interval "^1.1.0"
|
||||
|
||||
pg@^8.13.1:
|
||||
pg@^8.16.3:
|
||||
version "8.16.3"
|
||||
resolved "https://registry.yarnpkg.com/pg/-/pg-8.16.3.tgz#160741d0b44fdf64680e45374b06d632e86c99fd"
|
||||
integrity sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw==
|
||||
@@ -2000,6 +2071,24 @@ postgres-interval@^1.1.0:
|
||||
dependencies:
|
||||
xtend "^4.0.0"
|
||||
|
||||
prebuild-install@^7.1.1:
|
||||
version "7.1.3"
|
||||
resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.3.tgz#d630abad2b147443f20a212917beae68b8092eec"
|
||||
integrity sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==
|
||||
dependencies:
|
||||
detect-libc "^2.0.0"
|
||||
expand-template "^2.0.3"
|
||||
github-from-package "0.0.0"
|
||||
minimist "^1.2.3"
|
||||
mkdirp-classic "^0.5.3"
|
||||
napi-build-utils "^2.0.0"
|
||||
node-abi "^3.3.0"
|
||||
pump "^3.0.0"
|
||||
rc "^1.2.7"
|
||||
simple-get "^4.0.0"
|
||||
tar-fs "^2.0.0"
|
||||
tunnel-agent "^0.6.0"
|
||||
|
||||
process-nextick-args@~2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
||||
@@ -2036,6 +2125,14 @@ pstree.remy@^1.1.8:
|
||||
resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a"
|
||||
integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==
|
||||
|
||||
pump@^3.0.0:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.3.tgz#151d979f1a29668dc0025ec589a455b53282268d"
|
||||
integrity sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==
|
||||
dependencies:
|
||||
end-of-stream "^1.1.0"
|
||||
once "^1.3.1"
|
||||
|
||||
qs@6.13.0:
|
||||
version "6.13.0"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906"
|
||||
@@ -2063,6 +2160,16 @@ raw-body@2.5.2:
|
||||
iconv-lite "0.4.24"
|
||||
unpipe "1.0.0"
|
||||
|
||||
rc@^1.2.7:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
|
||||
integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
|
||||
dependencies:
|
||||
deep-extend "^0.6.0"
|
||||
ini "~1.3.0"
|
||||
minimist "^1.2.0"
|
||||
strip-json-comments "~2.0.1"
|
||||
|
||||
readable-stream@^2.0.0, readable-stream@^2.0.5:
|
||||
version "2.3.8"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b"
|
||||
@@ -2280,6 +2387,20 @@ signale@1.4.0:
|
||||
figures "^2.0.0"
|
||||
pkg-conf "^2.1.0"
|
||||
|
||||
simple-concat@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f"
|
||||
integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==
|
||||
|
||||
simple-get@^4.0.0:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.1.tgz#4a39db549287c979d352112fa03fd99fd6bc3543"
|
||||
integrity sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==
|
||||
dependencies:
|
||||
decompress-response "^6.0.0"
|
||||
once "^1.3.1"
|
||||
simple-concat "^1.0.0"
|
||||
|
||||
simple-update-notifier@^1.0.7:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz#67694c121de354af592b347cdba798463ed49c82"
|
||||
@@ -2314,13 +2435,14 @@ split2@^4.1.0:
|
||||
resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4"
|
||||
integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==
|
||||
|
||||
sqlite3@5.1.6:
|
||||
version "5.1.6"
|
||||
resolved "https://registry.yarnpkg.com/sqlite3/-/sqlite3-5.1.6.tgz#1d4fbc90fe4fbd51e952e0a90fd8f6c2b9098e97"
|
||||
integrity sha512-olYkWoKFVNSSSQNvxVUfjiVbz3YtBwTJj+mfV5zpHmqW3sELx2Cf4QCdirMelhM5Zh+KDVaKgQHqCxrqiWHybw==
|
||||
sqlite3@^5.1.7:
|
||||
version "5.1.7"
|
||||
resolved "https://registry.yarnpkg.com/sqlite3/-/sqlite3-5.1.7.tgz#59ca1053c1ab38647396586edad019b1551041b7"
|
||||
integrity sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==
|
||||
dependencies:
|
||||
"@mapbox/node-pre-gyp" "^1.0.0"
|
||||
node-addon-api "^4.2.0"
|
||||
bindings "^1.5.0"
|
||||
node-addon-api "^7.0.0"
|
||||
prebuild-install "^7.1.1"
|
||||
tar "^6.1.11"
|
||||
optionalDependencies:
|
||||
node-gyp "8.x"
|
||||
@@ -2382,6 +2504,11 @@ strip-bom@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
|
||||
integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==
|
||||
|
||||
strip-json-comments@~2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
|
||||
integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==
|
||||
|
||||
supports-color@^5.3.0, supports-color@^5.5.0:
|
||||
version "5.5.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
|
||||
@@ -2401,7 +2528,17 @@ supports-preserve-symlinks-flag@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
|
||||
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
|
||||
|
||||
tar-stream@^2.2.0:
|
||||
tar-fs@^2.0.0:
|
||||
version "2.1.4"
|
||||
resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.4.tgz#800824dbf4ef06ded9afea4acafe71c67c76b930"
|
||||
integrity sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==
|
||||
dependencies:
|
||||
chownr "^1.1.1"
|
||||
mkdirp-classic "^0.5.2"
|
||||
pump "^3.0.0"
|
||||
tar-stream "^2.1.4"
|
||||
|
||||
tar-stream@^2.1.4, tar-stream@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287"
|
||||
integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==
|
||||
@@ -2472,6 +2609,13 @@ tr46@~0.0.3:
|
||||
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
|
||||
integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
|
||||
|
||||
tunnel-agent@^0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
|
||||
integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==
|
||||
dependencies:
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
type-is@~1.6.18:
|
||||
version "1.6.18"
|
||||
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
|
||||
|
||||
@@ -39,7 +39,6 @@ EXPOSE 80 81 443
|
||||
|
||||
COPY backend /app
|
||||
COPY frontend/dist /app/frontend
|
||||
COPY global /app/global
|
||||
|
||||
WORKDIR /app
|
||||
RUN yarn install \
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
# WARNING: This is a DEVELOPMENT docker-compose file, it should not be used for production.
|
||||
services:
|
||||
|
||||
fullstack:
|
||||
image: npm2dev:core
|
||||
container_name: npm2dev.core
|
||||
@@ -23,9 +22,9 @@ services:
|
||||
PGID: 1000
|
||||
FORCE_COLOR: 1
|
||||
# specifically for dev:
|
||||
DEBUG: 'true'
|
||||
DEVELOPMENT: 'true'
|
||||
LE_STAGING: 'true'
|
||||
DEBUG: "true"
|
||||
DEVELOPMENT: "true"
|
||||
LE_STAGING: "true"
|
||||
# db:
|
||||
# DB_MYSQL_HOST: 'db'
|
||||
# DB_MYSQL_PORT: '3306'
|
||||
@@ -33,26 +32,25 @@ services:
|
||||
# DB_MYSQL_PASSWORD: 'npm'
|
||||
# DB_MYSQL_NAME: 'npm'
|
||||
# db-postgres:
|
||||
DB_POSTGRES_HOST: 'db-postgres'
|
||||
DB_POSTGRES_PORT: '5432'
|
||||
DB_POSTGRES_USER: 'npm'
|
||||
DB_POSTGRES_PASSWORD: 'npmpass'
|
||||
DB_POSTGRES_NAME: 'npm'
|
||||
DB_POSTGRES_HOST: "db-postgres"
|
||||
DB_POSTGRES_PORT: "5432"
|
||||
DB_POSTGRES_USER: "npm"
|
||||
DB_POSTGRES_PASSWORD: "npmpass"
|
||||
DB_POSTGRES_NAME: "npm"
|
||||
# DB_SQLITE_FILE: "/data/database.sqlite"
|
||||
# DISABLE_IPV6: "true"
|
||||
# Required for DNS Certificate provisioning testing:
|
||||
LE_SERVER: 'https://ca.internal/acme/acme/directory'
|
||||
REQUESTS_CA_BUNDLE: '/etc/ssl/certs/NginxProxyManager.crt'
|
||||
LE_SERVER: "https://ca.internal/acme/acme/directory"
|
||||
REQUESTS_CA_BUNDLE: "/etc/ssl/certs/NginxProxyManager.crt"
|
||||
volumes:
|
||||
- npm_data:/data
|
||||
- le_data:/etc/letsencrypt
|
||||
- './dev/resolv.conf:/etc/resolv.conf:ro'
|
||||
- "./dev/resolv.conf:/etc/resolv.conf:ro"
|
||||
- ../backend:/app
|
||||
- ../frontend:/app/frontend
|
||||
- ../global:/app/global
|
||||
- '/etc/localtime:/etc/localtime:ro'
|
||||
- ../frontend:/frontend
|
||||
- "/etc/localtime:/etc/localtime:ro"
|
||||
healthcheck:
|
||||
test: [ "CMD", "/usr/bin/check-health" ]
|
||||
test: ["CMD", "/usr/bin/check-health"]
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
depends_on:
|
||||
@@ -72,13 +70,13 @@ services:
|
||||
- nginx_proxy_manager
|
||||
environment:
|
||||
TZ: "${TZ:-Australia/Brisbane}"
|
||||
MYSQL_ROOT_PASSWORD: 'npm'
|
||||
MYSQL_DATABASE: 'npm'
|
||||
MYSQL_USER: 'npm'
|
||||
MYSQL_PASSWORD: 'npm'
|
||||
MYSQL_ROOT_PASSWORD: "npm"
|
||||
MYSQL_DATABASE: "npm"
|
||||
MYSQL_USER: "npm"
|
||||
MYSQL_PASSWORD: "npm"
|
||||
volumes:
|
||||
- db_data:/var/lib/mysql
|
||||
- '/etc/localtime:/etc/localtime:ro'
|
||||
- "/etc/localtime:/etc/localtime:ro"
|
||||
|
||||
db-postgres:
|
||||
image: postgres:latest
|
||||
@@ -86,9 +84,9 @@ services:
|
||||
networks:
|
||||
- nginx_proxy_manager
|
||||
environment:
|
||||
POSTGRES_USER: 'npm'
|
||||
POSTGRES_PASSWORD: 'npmpass'
|
||||
POSTGRES_DB: 'npm'
|
||||
POSTGRES_USER: "npm"
|
||||
POSTGRES_PASSWORD: "npmpass"
|
||||
POSTGRES_DB: "npm"
|
||||
volumes:
|
||||
- psql_data:/var/lib/postgresql/data
|
||||
- ./ci/postgres:/docker-entrypoint-initdb.d
|
||||
@@ -97,8 +95,8 @@ services:
|
||||
image: jc21/testca
|
||||
container_name: npm2dev.stepca
|
||||
volumes:
|
||||
- './dev/resolv.conf:/etc/resolv.conf:ro'
|
||||
- '/etc/localtime:/etc/localtime:ro'
|
||||
- "./dev/resolv.conf:/etc/resolv.conf:ro"
|
||||
- "/etc/localtime:/etc/localtime:ro"
|
||||
networks:
|
||||
nginx_proxy_manager:
|
||||
aliases:
|
||||
@@ -119,7 +117,7 @@ services:
|
||||
- 3082:80
|
||||
environment:
|
||||
URL: "http://npm:81/api/schema"
|
||||
PORT: '80'
|
||||
PORT: "80"
|
||||
depends_on:
|
||||
- fullstack
|
||||
|
||||
@@ -127,9 +125,9 @@ services:
|
||||
image: ubuntu/squid
|
||||
container_name: npm2dev.squid
|
||||
volumes:
|
||||
- './dev/squid.conf:/etc/squid/squid.conf:ro'
|
||||
- './dev/resolv.conf:/etc/resolv.conf:ro'
|
||||
- '/etc/localtime:/etc/localtime:ro'
|
||||
- "./dev/squid.conf:/etc/squid/squid.conf:ro"
|
||||
- "./dev/resolv.conf:/etc/resolv.conf:ro"
|
||||
- "/etc/localtime:/etc/localtime:ro"
|
||||
networks:
|
||||
- nginx_proxy_manager
|
||||
ports:
|
||||
@@ -139,18 +137,18 @@ services:
|
||||
image: pschiffe/pdns-mysql:4.8
|
||||
container_name: npm2dev.pdns
|
||||
volumes:
|
||||
- '/etc/localtime:/etc/localtime:ro'
|
||||
- "/etc/localtime:/etc/localtime:ro"
|
||||
environment:
|
||||
PDNS_master: 'yes'
|
||||
PDNS_api: 'yes'
|
||||
PDNS_api_key: 'npm'
|
||||
PDNS_webserver: 'yes'
|
||||
PDNS_webserver_address: '0.0.0.0'
|
||||
PDNS_webserver_password: 'npm'
|
||||
PDNS_webserver-allow-from: '127.0.0.0/8,192.0.0.0/8,10.0.0.0/8,172.0.0.0/8'
|
||||
PDNS_version_string: 'anonymous'
|
||||
PDNS_master: "yes"
|
||||
PDNS_api: "yes"
|
||||
PDNS_api_key: "npm"
|
||||
PDNS_webserver: "yes"
|
||||
PDNS_webserver_address: "0.0.0.0"
|
||||
PDNS_webserver_password: "npm"
|
||||
PDNS_webserver-allow-from: "127.0.0.0/8,192.0.0.0/8,10.0.0.0/8,172.0.0.0/8"
|
||||
PDNS_version_string: "anonymous"
|
||||
PDNS_default_ttl: 1500
|
||||
PDNS_allow_axfr_ips: '127.0.0.0/8,192.0.0.0/8,10.0.0.0/8,172.0.0.0/8'
|
||||
PDNS_allow_axfr_ips: "127.0.0.0/8,192.0.0.0/8,10.0.0.0/8,172.0.0.0/8"
|
||||
PDNS_gmysql_host: pdns-db
|
||||
PDNS_gmysql_port: 3306
|
||||
PDNS_gmysql_user: pdns
|
||||
@@ -168,14 +166,14 @@ services:
|
||||
image: mariadb
|
||||
container_name: npm2dev.pdns-db
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: 'pdns'
|
||||
MYSQL_DATABASE: 'pdns'
|
||||
MYSQL_USER: 'pdns'
|
||||
MYSQL_PASSWORD: 'pdns'
|
||||
MYSQL_ROOT_PASSWORD: "pdns"
|
||||
MYSQL_DATABASE: "pdns"
|
||||
MYSQL_USER: "pdns"
|
||||
MYSQL_PASSWORD: "pdns"
|
||||
volumes:
|
||||
- 'pdns_mysql:/var/lib/mysql'
|
||||
- '/etc/localtime:/etc/localtime:ro'
|
||||
- './dev/pdns-db.sql:/docker-entrypoint-initdb.d/01_init.sql:ro'
|
||||
- "pdns_mysql:/var/lib/mysql"
|
||||
- "/etc/localtime:/etc/localtime:ro"
|
||||
- "./dev/pdns-db.sql:/docker-entrypoint-initdb.d/01_init.sql:ro"
|
||||
networks:
|
||||
- nginx_proxy_manager
|
||||
|
||||
@@ -186,25 +184,25 @@ services:
|
||||
context: ../
|
||||
dockerfile: test/cypress/Dockerfile
|
||||
environment:
|
||||
HTTP_PROXY: 'squid:3128'
|
||||
HTTPS_PROXY: 'squid:3128'
|
||||
HTTP_PROXY: "squid:3128"
|
||||
HTTPS_PROXY: "squid:3128"
|
||||
volumes:
|
||||
- '../test/results:/results'
|
||||
- './dev/resolv.conf:/etc/resolv.conf:ro'
|
||||
- '/etc/localtime:/etc/localtime:ro'
|
||||
- "../test/results:/results"
|
||||
- "./dev/resolv.conf:/etc/resolv.conf:ro"
|
||||
- "/etc/localtime:/etc/localtime:ro"
|
||||
command: cypress run --browser chrome --config-file=cypress/config/ci.js
|
||||
networks:
|
||||
- nginx_proxy_manager
|
||||
|
||||
authentik-redis:
|
||||
image: 'redis:alpine'
|
||||
image: "redis:alpine"
|
||||
container_name: npm2dev.authentik-redis
|
||||
command: --save 60 1 --loglevel warning
|
||||
networks:
|
||||
- nginx_proxy_manager
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: [ 'CMD-SHELL', 'redis-cli ping | grep PONG' ]
|
||||
test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
|
||||
start_period: 20s
|
||||
interval: 30s
|
||||
retries: 5
|
||||
@@ -246,9 +244,9 @@ services:
|
||||
networks:
|
||||
- nginx_proxy_manager
|
||||
environment:
|
||||
AUTHENTIK_HOST: 'http://authentik:9000'
|
||||
AUTHENTIK_INSECURE: 'true'
|
||||
AUTHENTIK_TOKEN: 'wKYZuRcI0ETtb8vWzMCr04oNbhrQUUICy89hSpDln1OEKLjiNEuQ51044Vkp'
|
||||
AUTHENTIK_HOST: "http://authentik:9000"
|
||||
AUTHENTIK_INSECURE: "true"
|
||||
AUTHENTIK_TOKEN: "wKYZuRcI0ETtb8vWzMCr04oNbhrQUUICy89hSpDln1OEKLjiNEuQ51044Vkp"
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- authentik
|
||||
|
||||
@@ -7,11 +7,11 @@ set -e
|
||||
|
||||
if [ "$DEVELOPMENT" = 'true' ]; then
|
||||
. /usr/bin/common.sh
|
||||
cd /app/frontend || exit 1
|
||||
cd /frontend || exit 1
|
||||
HOME=$NPMHOME
|
||||
export HOME
|
||||
mkdir -p /app/frontend/dist
|
||||
chown -R "$PUID:$PGID" /app/frontend/dist
|
||||
mkdir -p /frontend/dist
|
||||
chown -R "$PUID:$PGID" /frontend/dist
|
||||
|
||||
log_info 'Starting frontend ...'
|
||||
s6-setuidgid "$PUID:$PGID" yarn install
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
"dependencies": {
|
||||
"@tabler/core": "^1.4.0",
|
||||
"@tabler/icons-react": "^3.35.0",
|
||||
"@tanstack/react-query": "^5.90.3",
|
||||
"@tanstack/react-query": "^5.90.5",
|
||||
"@tanstack/react-table": "^8.21.3",
|
||||
"@uiw/react-textarea-code-editor": "^3.1.1",
|
||||
"classnames": "^2.5.1",
|
||||
@@ -39,7 +39,7 @@
|
||||
"rooks": "^9.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "^2.2.6",
|
||||
"@biomejs/biome": "^2.3.0",
|
||||
"@formatjs/cli": "^6.7.4",
|
||||
"@tanstack/react-query-devtools": "^5.90.2",
|
||||
"@testing-library/dom": "^10.4.1",
|
||||
@@ -50,16 +50,16 @@
|
||||
"@types/react": "^19.2.2",
|
||||
"@types/react-dom": "^19.2.2",
|
||||
"@types/react-table": "^7.7.20",
|
||||
"@vitejs/plugin-react": "^5.0.4",
|
||||
"happy-dom": "^20.0.2",
|
||||
"@vitejs/plugin-react": "^5.1.0",
|
||||
"happy-dom": "^20.0.8",
|
||||
"postcss": "^8.5.6",
|
||||
"postcss-simple-vars": "^7.0.1",
|
||||
"sass": "^1.93.2",
|
||||
"tmp": "^0.2.5",
|
||||
"typescript": "5.9.3",
|
||||
"vite": "^7.1.10",
|
||||
"vite": "^7.1.12",
|
||||
"vite-plugin-checker": "^0.11.0",
|
||||
"vite-tsconfig-paths": "^5.1.4",
|
||||
"vitest": "^3.2.4"
|
||||
"vitest": "^4.0.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import type { Certificate } from "./models";
|
||||
export async function createCertificate(item: Certificate): Promise<Certificate> {
|
||||
return await api.post({
|
||||
url: "/nginx/certificates",
|
||||
// todo: only use whitelist of fields for this data
|
||||
data: item,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import * as api from "./base";
|
||||
|
||||
export async function testHttpCertificate(domains: string[]): Promise<Record<string, string>> {
|
||||
return await api.get({
|
||||
return await api.post({
|
||||
url: "/nginx/certificates/test-http",
|
||||
params: {
|
||||
domains: domains.join(","),
|
||||
data: {
|
||||
domains,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ export function AccessField({ name = "accessListId", label = "access-list", id =
|
||||
options?.unshift({
|
||||
value: 0,
|
||||
label: intl.formatMessage({ id: "access-list.public" }),
|
||||
subLabel: "No basic auth required",
|
||||
subLabel: intl.formatMessage({ id: "access-list.public.subtitle" }),
|
||||
icon: <IconLockOpen2 size={14} className="text-red" />,
|
||||
});
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { IconAlertTriangle } from "@tabler/icons-react";
|
||||
import { Field, useFormikContext } from "formik";
|
||||
import { useState } from "react";
|
||||
import Select, { type ActionMeta } from "react-select";
|
||||
import type { DNSProvider } from "src/api/backend";
|
||||
import { useDnsProviders } from "src/hooks";
|
||||
import { T } from "src/locale";
|
||||
import styles from "./DNSProviderFields.module.css";
|
||||
|
||||
interface DNSProviderOption {
|
||||
@@ -10,7 +12,11 @@ interface DNSProviderOption {
|
||||
readonly label: string;
|
||||
readonly credentials: string;
|
||||
}
|
||||
export function DNSProviderFields() {
|
||||
|
||||
interface Props {
|
||||
showBoundaryBox?: boolean;
|
||||
}
|
||||
export function DNSProviderFields({ showBoundaryBox = false }: Props) {
|
||||
const { values, setFieldValue } = useFormikContext();
|
||||
const { data: dnsProviders, isLoading } = useDnsProviders();
|
||||
const [dnsProviderId, setDnsProviderId] = useState<string | null>(null);
|
||||
@@ -31,17 +37,17 @@ export function DNSProviderFields() {
|
||||
})) || [];
|
||||
|
||||
return (
|
||||
<div className={styles.dnsChallengeWarning}>
|
||||
<p className="text-info">
|
||||
This section requires some knowledge about Certbot and DNS plugins. Please consult the respective
|
||||
plugins documentation.
|
||||
<div className={showBoundaryBox ? styles.dnsChallengeWarning : undefined}>
|
||||
<p className="text-warning">
|
||||
<IconAlertTriangle size={16} className="me-1" />
|
||||
<T id="certificates.dns.warning" />
|
||||
</p>
|
||||
|
||||
<Field name="meta.dnsProvider">
|
||||
{({ field }: any) => (
|
||||
<div className="row">
|
||||
<label htmlFor="dnsProvider" className="form-label">
|
||||
DNS Provider
|
||||
<T id="certificates.dns.provider" />
|
||||
</label>
|
||||
<Select
|
||||
className="react-select-container"
|
||||
@@ -66,7 +72,7 @@ export function DNSProviderFields() {
|
||||
{({ field }: any) => (
|
||||
<div className="mt-3">
|
||||
<label htmlFor="dnsProviderCredentials" className="form-label">
|
||||
Credentials File Content
|
||||
<T id="certificates.dns.credentials" />
|
||||
</label>
|
||||
<textarea
|
||||
id="dnsProviderCredentials"
|
||||
@@ -78,13 +84,12 @@ export function DNSProviderFields() {
|
||||
/>
|
||||
<div>
|
||||
<small className="text-muted">
|
||||
This plugin requires a configuration file containing an API token or other
|
||||
credentials to your provider
|
||||
<T id="certificates.dns.credentials-note" />
|
||||
</small>
|
||||
</div>
|
||||
<div>
|
||||
<small className="text-danger">
|
||||
This data will be stored as plaintext in the database and in a file!
|
||||
<T id="certificates.dns.credentials-warning" />
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
@@ -94,20 +99,18 @@ export function DNSProviderFields() {
|
||||
{({ field }: any) => (
|
||||
<div className="mt-3">
|
||||
<label htmlFor="propagationSeconds" className="form-label">
|
||||
Propagation Seconds
|
||||
<T id="certificates.dns.propagation-seconds" />
|
||||
</label>
|
||||
<input
|
||||
id="propagationSeconds"
|
||||
type="number"
|
||||
x
|
||||
className="form-control"
|
||||
min={0}
|
||||
max={600}
|
||||
{...field}
|
||||
/>
|
||||
<small className="text-muted">
|
||||
Leave empty to use the plugins default value. Number of seconds to wait for DNS
|
||||
propagation.
|
||||
<T id="certificates.dns.propagation-seconds-note" />
|
||||
</small>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -18,14 +18,16 @@ interface Props {
|
||||
dnsProviderWildcardSupported?: boolean;
|
||||
name?: string;
|
||||
label?: string;
|
||||
onChange?: (domains: string[]) => void;
|
||||
}
|
||||
export function DomainNamesField({
|
||||
name = "domainNames",
|
||||
label = "domain-names",
|
||||
id = "domainNames",
|
||||
maxDomains,
|
||||
isWildcardPermitted = true,
|
||||
dnsProviderWildcardSupported = true,
|
||||
isWildcardPermitted = false,
|
||||
dnsProviderWildcardSupported = false,
|
||||
onChange,
|
||||
}: Props) {
|
||||
const { setFieldValue } = useFormikContext();
|
||||
|
||||
@@ -34,6 +36,7 @@ export function DomainNamesField({
|
||||
return i.value;
|
||||
});
|
||||
setFieldValue(name, doms);
|
||||
onChange?.(doms);
|
||||
};
|
||||
|
||||
const helperTexts: ReactNode[] = [];
|
||||
|
||||
@@ -11,7 +11,7 @@ interface Props {
|
||||
initialValues: ProxyLocation[];
|
||||
name?: string;
|
||||
}
|
||||
export function LocationsFields({ initialValues, name = "items" }: Props) {
|
||||
export function LocationsFields({ initialValues, name = "locations" }: Props) {
|
||||
const [values, setValues] = useState<ProxyLocation[]>(initialValues || []);
|
||||
const { setFieldValue } = useFormikContext();
|
||||
const [advVisible, setAdvVisible] = useState<number[]>([]);
|
||||
|
||||
@@ -30,6 +30,7 @@ export function NginxConfigField({
|
||||
fontFamily: "ui-monospace,SFMono-Regular,SF Mono,Consolas,Liberation Mono,Menlo,monospace",
|
||||
borderRadius: "0.3rem",
|
||||
minHeight: "200px",
|
||||
backgroundColor: "var(--tblr-bg-surface-dark)",
|
||||
}}
|
||||
{...field}
|
||||
/>
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Field, useFormikContext } from "formik";
|
||||
import Select, { type ActionMeta, components, type OptionProps } from "react-select";
|
||||
import type { Certificate } from "src/api/backend";
|
||||
import { useCertificates } from "src/hooks";
|
||||
import { DateTimeFormat, T } from "src/locale";
|
||||
import { DateTimeFormat, intl, T } from "src/locale";
|
||||
|
||||
interface CertOption {
|
||||
readonly value: number | "new";
|
||||
@@ -75,9 +75,7 @@ export function SSLCertificateField({
|
||||
data?.map((cert: Certificate) => ({
|
||||
value: cert.id,
|
||||
label: cert.niceName,
|
||||
subLabel: `${cert.provider === "letsencrypt" ? "Let's Encrypt" : cert.provider} — Expires: ${
|
||||
cert.expiresOn ? DateTimeFormat(cert.expiresOn) : "N/A"
|
||||
}`,
|
||||
subLabel: `${cert.provider === "letsencrypt" ? intl.formatMessage({ id: "lets-encrypt" }) : cert.provider} — ${intl.formatMessage({ id: "expires.on" }, { date: cert.expiresOn ? DateTimeFormat(cert.expiresOn) : "N/A" })}`,
|
||||
icon: <IconShield size={14} className="text-pink" />,
|
||||
})) || [];
|
||||
|
||||
@@ -85,8 +83,8 @@ export function SSLCertificateField({
|
||||
if (allowNew) {
|
||||
options?.unshift({
|
||||
value: "new",
|
||||
label: "Request a new Certificate",
|
||||
subLabel: "with Let's Encrypt",
|
||||
label: intl.formatMessage({ id: "certificates.request.title" }),
|
||||
subLabel: intl.formatMessage({ id: "certificates.request.subtitle" }),
|
||||
icon: <IconShield size={14} className="text-lime" />,
|
||||
});
|
||||
}
|
||||
@@ -95,8 +93,10 @@ export function SSLCertificateField({
|
||||
if (!required) {
|
||||
options?.unshift({
|
||||
value: 0,
|
||||
label: "None",
|
||||
subLabel: forHttp ? "This host will not use HTTPS" : "No certificate assigned",
|
||||
label: intl.formatMessage({ id: "certificate.none.title" }),
|
||||
subLabel: forHttp
|
||||
? intl.formatMessage({ id: "certificate.none.subtitle.for-http" })
|
||||
: intl.formatMessage({ id: "certificate.none.subtitle" }),
|
||||
icon: <IconShield size={14} className="text-red" />,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -136,8 +136,8 @@ export function SSLOptionsFields({ forHttp = true, forceDNSForNew, requireDomain
|
||||
</label>
|
||||
)}
|
||||
</Field>
|
||||
{requireDomainNames ? <DomainNamesField /> : null}
|
||||
{dnsChallenge ? <DNSProviderFields /> : null}
|
||||
{requireDomainNames ? <DomainNamesField isWildcardPermitted dnsProviderWildcardSupported /> : null}
|
||||
{dnsChallenge ? <DNSProviderFields showBoundaryBox /> : null}
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
@@ -64,7 +64,7 @@ export function EventFormatter({ row }: Props) {
|
||||
<div className="flex-fill">
|
||||
<div className="font-weight-medium">
|
||||
{getIcon(row)}
|
||||
<T id={`event.${row.action}-${row.objectType}`} />
|
||||
<T id={`object.event.${row.action}`} tData={{ object: row.objectType }} />
|
||||
— <span className="badge">{getEventValue(row)}</span>
|
||||
</div>
|
||||
<div className="text-secondary mt-1">{DateTimeFormat(row.createdOn)}</div>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"access-list.help.rules-order": "Note that the allow and deny directives will be applied in the order they are defined.",
|
||||
"access-list.pass-auth": "Pass Auth to Upstream",
|
||||
"access-list.public": "Publicly Accessible",
|
||||
"access-list.public.subtitle": "No basic auth required",
|
||||
"access-list.satisfy-any": "Satisfy Any",
|
||||
"access-list.subtitle": "{users} {users, plural, one {User} other {Users}}, {rules} {rules, plural, one {Rule} other {Rules}} - Created: {date}",
|
||||
"access-lists": "Access Lists",
|
||||
@@ -21,8 +22,28 @@
|
||||
"auditlogs": "Audit Logs",
|
||||
"cancel": "Cancel",
|
||||
"certificate": "Certificate",
|
||||
"certificate.none.subtitle": "No certificate assigned",
|
||||
"certificate.none.subtitle.for-http": "This host will not use HTTPS",
|
||||
"certificate.none.title": "None",
|
||||
"certificates": "Certificates",
|
||||
"certificates.custom": "Custom Certificate",
|
||||
"certificates.dns.credentials": "Credentials File Content",
|
||||
"certificates.dns.credentials-note": "This plugin requires a configuration file containing an API token or other credentials for your provider",
|
||||
"certificates.dns.credentials-warning": "This data will be stored as plaintext in the database and in a file!",
|
||||
"certificates.dns.propagation-seconds": "Propagation Seconds",
|
||||
"certificates.dns.propagation-seconds-note": "Leave empty to use the plugins default value. Number of seconds to wait for DNS propagation.",
|
||||
"certificates.dns.provider": "DNS Provider",
|
||||
"certificates.dns.warning": "This section requires some knowledge about Certbot and its DNS plugins. Please consult the respective plugins documentation.",
|
||||
"certificates.http.reachability-404": "There is a server found at this domain but it does not seem to be Nginx Proxy Manager. Please make sure your domain points to the IP where your NPM instance is running.",
|
||||
"certificates.http.reachability-failed-to-check": "Failed to check the reachability due to a communication error with site24x7.com.",
|
||||
"certificates.http.reachability-not-resolved": "There is no server available at this domain. Please make sure your domain exists and points to the IP where your NPM instance is running and if necessary port 80 is forwarded in your router.",
|
||||
"certificates.http.reachability-ok": "Your server is reachable and creating certificates should be possible.",
|
||||
"certificates.http.reachability-other": "There is a server found at this domain but it returned an unexpected status code {code}. Is it the NPM server? Please make sure your domain points to the IP where your NPM instance is running.",
|
||||
"certificates.http.reachability-wrong-data": "There is a server found at this domain but it returned an unexpected data. Is it the NPM server? Please make sure your domain points to the IP where your NPM instance is running.",
|
||||
"certificates.http.test-results": "Test Results",
|
||||
"certificates.http.warning": "These domains must be already configured to point to this installation.",
|
||||
"certificates.request.subtitle": "with Let's Encrypt",
|
||||
"certificates.request.title": "Request a new Certificate",
|
||||
"column.access": "Access",
|
||||
"column.authorization": "Authorization",
|
||||
"column.authorizations": "Authorizations",
|
||||
@@ -74,22 +95,7 @@
|
||||
"error.max-domains": "Too many domains, max is {max}",
|
||||
"error.passwords-must-match": "Passwords must match",
|
||||
"error.required": "This is required",
|
||||
"event.created-access-list": "Created Access List",
|
||||
"event.created-dead-host": "Created 404 Host",
|
||||
"event.created-redirection-host": "Created Redirection Host",
|
||||
"event.created-stream": "Created Stream",
|
||||
"event.created-user": "Created User",
|
||||
"event.deleted-dead-host": "Deleted 404 Host",
|
||||
"event.deleted-stream": "Deleted Stream",
|
||||
"event.deleted-user": "Deleted User",
|
||||
"event.disabled-dead-host": "Disabled 404 Host",
|
||||
"event.disabled-redirection-host": "Disabled Redirection Host",
|
||||
"event.disabled-stream": "Disabled Stream",
|
||||
"event.enabled-dead-host": "Enabled 404 Host",
|
||||
"event.enabled-redirection-host": "Enabled Redirection Host",
|
||||
"event.enabled-stream": "Enabled Stream",
|
||||
"event.updated-redirection-host": "Updated Redirection Host",
|
||||
"event.updated-user": "Updated User",
|
||||
"expires.on": "Expires: {date}",
|
||||
"footer.github-fork": "Fork me on Github",
|
||||
"host.flags.block-exploits": "Block Common Exploits",
|
||||
"host.flags.cache-assets": "Cache Assets",
|
||||
@@ -101,6 +107,8 @@
|
||||
"hosts": "Hosts",
|
||||
"http-only": "HTTP Only",
|
||||
"lets-encrypt": "Let's Encrypt",
|
||||
"lets-encrypt-via-dns": "Let's Encrypt via DNS",
|
||||
"lets-encrypt-via-http": "Let's Encrypt via HTTP",
|
||||
"loading": "Loading…",
|
||||
"login.title": "Login to your account",
|
||||
"nginx-config.label": "Custom Nginx Configuration",
|
||||
@@ -121,6 +129,11 @@
|
||||
"object.delete.content": "Are you sure you want to delete this {object}?",
|
||||
"object.edit": "Edit {object}",
|
||||
"object.empty": "There are no {objects}",
|
||||
"object.event.created": "Created {object}",
|
||||
"object.event.deleted": "Deleted {object}",
|
||||
"object.event.disabled": "Disabled {object}",
|
||||
"object.event.enabled": "Enabled {object}",
|
||||
"object.event.updated": "Updated {object}",
|
||||
"offline": "Offline",
|
||||
"online": "Online",
|
||||
"options": "Options",
|
||||
@@ -158,6 +171,7 @@
|
||||
"streams.count": "{count} {count, plural, one {Stream} other {Streams}}",
|
||||
"streams.tcp": "TCP",
|
||||
"streams.udp": "UDP",
|
||||
"test": "Test",
|
||||
"user": "User",
|
||||
"user.change-password": "Change Password",
|
||||
"user.confirm-password": "Confirm Password",
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
"access-list.public": {
|
||||
"defaultMessage": "Publicly Accessible"
|
||||
},
|
||||
"access-list.public.subtitle": {
|
||||
"defaultMessage": "No basic auth required"
|
||||
},
|
||||
"access-list.satisfy-any": {
|
||||
"defaultMessage": "Satisfy Any"
|
||||
},
|
||||
@@ -65,12 +68,72 @@
|
||||
"certificate": {
|
||||
"defaultMessage": "Certificate"
|
||||
},
|
||||
"certificate.none.subtitle": {
|
||||
"defaultMessage": "No certificate assigned"
|
||||
},
|
||||
"certificate.none.subtitle.for-http": {
|
||||
"defaultMessage": "This host will not use HTTPS"
|
||||
},
|
||||
"certificate.none.title": {
|
||||
"defaultMessage": "None"
|
||||
},
|
||||
"certificates": {
|
||||
"defaultMessage": "Certificates"
|
||||
},
|
||||
"certificates.custom": {
|
||||
"defaultMessage": "Custom Certificate"
|
||||
},
|
||||
"certificates.dns.credentials": {
|
||||
"defaultMessage": "Credentials File Content"
|
||||
},
|
||||
"certificates.dns.credentials-note": {
|
||||
"defaultMessage": "This plugin requires a configuration file containing an API token or other credentials for your provider"
|
||||
},
|
||||
"certificates.dns.credentials-warning": {
|
||||
"defaultMessage": "This data will be stored as plaintext in the database and in a file!"
|
||||
},
|
||||
"certificates.dns.propagation-seconds": {
|
||||
"defaultMessage": "Propagation Seconds"
|
||||
},
|
||||
"certificates.dns.propagation-seconds-note": {
|
||||
"defaultMessage": "Leave empty to use the plugins default value. Number of seconds to wait for DNS propagation."
|
||||
},
|
||||
"certificates.dns.provider": {
|
||||
"defaultMessage": "DNS Provider"
|
||||
},
|
||||
"certificates.dns.warning": {
|
||||
"defaultMessage": "This section requires some knowledge about Certbot and its DNS plugins. Please consult the respective plugins documentation."
|
||||
},
|
||||
"certificates.http.reachability-404": {
|
||||
"defaultMessage": "There is a server found at this domain but it does not seem to be Nginx Proxy Manager. Please make sure your domain points to the IP where your NPM instance is running."
|
||||
},
|
||||
"certificates.http.reachability-failed-to-check": {
|
||||
"defaultMessage": "Failed to check the reachability due to a communication error with site24x7.com."
|
||||
},
|
||||
"certificates.http.reachability-not-resolved": {
|
||||
"defaultMessage": "There is no server available at this domain. Please make sure your domain exists and points to the IP where your NPM instance is running and if necessary port 80 is forwarded in your router."
|
||||
},
|
||||
"certificates.http.reachability-ok": {
|
||||
"defaultMessage": "Your server is reachable and creating certificates should be possible."
|
||||
},
|
||||
"certificates.http.reachability-other": {
|
||||
"defaultMessage": "There is a server found at this domain but it returned an unexpected status code {code}. Is it the NPM server? Please make sure your domain points to the IP where your NPM instance is running."
|
||||
},
|
||||
"certificates.http.reachability-wrong-data": {
|
||||
"defaultMessage": "There is a server found at this domain but it returned an unexpected data. Is it the NPM server? Please make sure your domain points to the IP where your NPM instance is running."
|
||||
},
|
||||
"certificates.http.test-results": {
|
||||
"defaultMessage": "Test Results"
|
||||
},
|
||||
"certificates.http.warning": {
|
||||
"defaultMessage": "These domains must be already configured to point to this installation."
|
||||
},
|
||||
"certificates.request.subtitle": {
|
||||
"defaultMessage": "with Let's Encrypt"
|
||||
},
|
||||
"certificates.request.title": {
|
||||
"defaultMessage": "Request a new Certificate"
|
||||
},
|
||||
"column.access": {
|
||||
"defaultMessage": "Access"
|
||||
},
|
||||
@@ -224,53 +287,8 @@
|
||||
"error.required": {
|
||||
"defaultMessage": "This is required"
|
||||
},
|
||||
"event.created-access-list": {
|
||||
"defaultMessage": "Created Access List"
|
||||
},
|
||||
"event.created-dead-host": {
|
||||
"defaultMessage": "Created 404 Host"
|
||||
},
|
||||
"event.created-redirection-host": {
|
||||
"defaultMessage": "Created Redirection Host"
|
||||
},
|
||||
"event.created-stream": {
|
||||
"defaultMessage": "Created Stream"
|
||||
},
|
||||
"event.created-user": {
|
||||
"defaultMessage": "Created User"
|
||||
},
|
||||
"event.deleted-dead-host": {
|
||||
"defaultMessage": "Deleted 404 Host"
|
||||
},
|
||||
"event.deleted-stream": {
|
||||
"defaultMessage": "Deleted Stream"
|
||||
},
|
||||
"event.deleted-user": {
|
||||
"defaultMessage": "Deleted User"
|
||||
},
|
||||
"event.disabled-dead-host": {
|
||||
"defaultMessage": "Disabled 404 Host"
|
||||
},
|
||||
"event.disabled-redirection-host": {
|
||||
"defaultMessage": "Disabled Redirection Host"
|
||||
},
|
||||
"event.disabled-stream": {
|
||||
"defaultMessage": "Disabled Stream"
|
||||
},
|
||||
"event.enabled-dead-host": {
|
||||
"defaultMessage": "Enabled 404 Host"
|
||||
},
|
||||
"event.enabled-redirection-host": {
|
||||
"defaultMessage": "Enabled Redirection Host"
|
||||
},
|
||||
"event.enabled-stream": {
|
||||
"defaultMessage": "Enabled Stream"
|
||||
},
|
||||
"event.updated-redirection-host": {
|
||||
"defaultMessage": "Updated Redirection Host"
|
||||
},
|
||||
"event.updated-user": {
|
||||
"defaultMessage": "Updated User"
|
||||
"expires.on": {
|
||||
"defaultMessage": "Expires: {date}"
|
||||
},
|
||||
"footer.github-fork": {
|
||||
"defaultMessage": "Fork me on Github"
|
||||
@@ -305,6 +323,12 @@
|
||||
"lets-encrypt": {
|
||||
"defaultMessage": "Let's Encrypt"
|
||||
},
|
||||
"lets-encrypt-via-dns": {
|
||||
"defaultMessage": "Let's Encrypt via DNS"
|
||||
},
|
||||
"lets-encrypt-via-http": {
|
||||
"defaultMessage": "Let's Encrypt via HTTP"
|
||||
},
|
||||
"loading": {
|
||||
"defaultMessage": "Loading…"
|
||||
},
|
||||
@@ -365,6 +389,21 @@
|
||||
"object.empty": {
|
||||
"defaultMessage": "There are no {objects}"
|
||||
},
|
||||
"object.event.created": {
|
||||
"defaultMessage": "Created {object}"
|
||||
},
|
||||
"object.event.deleted": {
|
||||
"defaultMessage": "Deleted {object}"
|
||||
},
|
||||
"object.event.disabled": {
|
||||
"defaultMessage": "Disabled {object}"
|
||||
},
|
||||
"object.event.enabled": {
|
||||
"defaultMessage": "Enabled {object}"
|
||||
},
|
||||
"object.event.updated": {
|
||||
"defaultMessage": "Updated {object}"
|
||||
},
|
||||
"offline": {
|
||||
"defaultMessage": "Offline"
|
||||
},
|
||||
@@ -476,6 +515,9 @@
|
||||
"streams.udp": {
|
||||
"defaultMessage": "UDP"
|
||||
},
|
||||
"test": {
|
||||
"defaultMessage": "Test"
|
||||
},
|
||||
"user": {
|
||||
"defaultMessage": "User"
|
||||
},
|
||||
|
||||
88
frontend/src/modals/CustomCertificateModal.tsx
Normal file
88
frontend/src/modals/CustomCertificateModal.tsx
Normal file
@@ -0,0 +1,88 @@
|
||||
import EasyModal, { type InnerModalProps } from "ez-modal-react";
|
||||
import { Form, Formik } from "formik";
|
||||
import { type ReactNode, useState } from "react";
|
||||
import { Alert } from "react-bootstrap";
|
||||
import Modal from "react-bootstrap/Modal";
|
||||
import { Button, DomainNamesField } from "src/components";
|
||||
import { useSetProxyHost } from "src/hooks";
|
||||
import { T } from "src/locale";
|
||||
import { showObjectSuccess } from "src/notifications";
|
||||
|
||||
const showCustomCertificateModal = () => {
|
||||
EasyModal.show(CustomCertificateModal);
|
||||
};
|
||||
|
||||
const CustomCertificateModal = EasyModal.create(({ visible, remove }: InnerModalProps) => {
|
||||
const { mutate: setProxyHost } = useSetProxyHost();
|
||||
const [errorMsg, setErrorMsg] = useState<ReactNode | null>(null);
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
|
||||
const onSubmit = async (values: any, { setSubmitting }: any) => {
|
||||
if (isSubmitting) return;
|
||||
setIsSubmitting(true);
|
||||
setErrorMsg(null);
|
||||
|
||||
setProxyHost(values, {
|
||||
onError: (err: any) => setErrorMsg(<T id={err.message} />),
|
||||
onSuccess: () => {
|
||||
showObjectSuccess("certificate", "saved");
|
||||
remove();
|
||||
},
|
||||
onSettled: () => {
|
||||
setIsSubmitting(false);
|
||||
setSubmitting(false);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal show={visible} onHide={remove}>
|
||||
<Formik
|
||||
initialValues={
|
||||
{
|
||||
domainNames: [],
|
||||
} as any
|
||||
}
|
||||
onSubmit={onSubmit}
|
||||
>
|
||||
{() => (
|
||||
<Form>
|
||||
<Modal.Header closeButton>
|
||||
<Modal.Title>
|
||||
<T id="object.add" tData={{ object: "certificate" }} />
|
||||
</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body className="p-0">
|
||||
<Alert variant="danger" show={!!errorMsg} onClose={() => setErrorMsg(null)} dismissible>
|
||||
{errorMsg}
|
||||
</Alert>
|
||||
<div className="card m-0 border-0">
|
||||
<div className="card-header">asd</div>
|
||||
<div className="card-body">
|
||||
<DomainNamesField />
|
||||
</div>
|
||||
</div>
|
||||
</Modal.Body>
|
||||
<Modal.Footer>
|
||||
<Button data-bs-dismiss="modal" onClick={remove} disabled={isSubmitting}>
|
||||
<T id="cancel" />
|
||||
</Button>
|
||||
<Button
|
||||
type="submit"
|
||||
actionType="primary"
|
||||
className="ms-auto bg-lime"
|
||||
data-bs-dismiss="modal"
|
||||
isLoading={isSubmitting}
|
||||
disabled={isSubmitting}
|
||||
>
|
||||
<T id="save" />
|
||||
</Button>
|
||||
</Modal.Footer>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
</Modal>
|
||||
);
|
||||
});
|
||||
|
||||
export { showCustomCertificateModal };
|
||||
89
frontend/src/modals/DNSCertificateModal.tsx
Normal file
89
frontend/src/modals/DNSCertificateModal.tsx
Normal file
@@ -0,0 +1,89 @@
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import EasyModal, { type InnerModalProps } from "ez-modal-react";
|
||||
import { Form, Formik } from "formik";
|
||||
import { type ReactNode, useState } from "react";
|
||||
import { Alert } from "react-bootstrap";
|
||||
import Modal from "react-bootstrap/Modal";
|
||||
import { createCertificate } from "src/api/backend";
|
||||
import { Button, DNSProviderFields, DomainNamesField } from "src/components";
|
||||
import { T } from "src/locale";
|
||||
import { showObjectSuccess } from "src/notifications";
|
||||
|
||||
const showDNSCertificateModal = () => {
|
||||
EasyModal.show(DNSCertificateModal);
|
||||
};
|
||||
|
||||
const DNSCertificateModal = EasyModal.create(({ visible, remove }: InnerModalProps) => {
|
||||
const queryClient = useQueryClient();
|
||||
const [errorMsg, setErrorMsg] = useState<ReactNode | null>(null);
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
|
||||
const onSubmit = async (values: any, { setSubmitting }: any) => {
|
||||
if (isSubmitting) return;
|
||||
setIsSubmitting(true);
|
||||
setErrorMsg(null);
|
||||
|
||||
try {
|
||||
await createCertificate(values);
|
||||
showObjectSuccess("certificate", "saved");
|
||||
remove();
|
||||
} catch (err: any) {
|
||||
setErrorMsg(<T id={err.message} />);
|
||||
}
|
||||
queryClient.invalidateQueries({ queryKey: ["certificates"] });
|
||||
setIsSubmitting(false);
|
||||
setSubmitting(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal show={visible} onHide={remove}>
|
||||
<Formik
|
||||
initialValues={
|
||||
{
|
||||
domainNames: [],
|
||||
provider: "letsencrypt",
|
||||
} as any
|
||||
}
|
||||
onSubmit={onSubmit}
|
||||
>
|
||||
{() => (
|
||||
<Form>
|
||||
<Modal.Header closeButton>
|
||||
<Modal.Title>
|
||||
<T id="object.add" tData={{ object: "lets-encrypt-via-dns" }} />
|
||||
</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body className="p-0">
|
||||
<Alert variant="danger" show={!!errorMsg} onClose={() => setErrorMsg(null)} dismissible>
|
||||
{errorMsg}
|
||||
</Alert>
|
||||
<div className="card m-0 border-0">
|
||||
<div className="card-body">
|
||||
<DomainNamesField isWildcardPermitted dnsProviderWildcardSupported />
|
||||
<DNSProviderFields />
|
||||
</div>
|
||||
</div>
|
||||
</Modal.Body>
|
||||
<Modal.Footer>
|
||||
<Button data-bs-dismiss="modal" onClick={remove} disabled={isSubmitting}>
|
||||
<T id="cancel" />
|
||||
</Button>
|
||||
<Button
|
||||
type="submit"
|
||||
actionType="primary"
|
||||
className="ms-auto bg-pink"
|
||||
data-bs-dismiss="modal"
|
||||
isLoading={isSubmitting}
|
||||
disabled={isSubmitting}
|
||||
>
|
||||
<T id="save" />
|
||||
</Button>
|
||||
</Modal.Footer>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
</Modal>
|
||||
);
|
||||
});
|
||||
|
||||
export { showDNSCertificateModal };
|
||||
@@ -131,7 +131,7 @@ const DeadHostModal = EasyModal.create(({ id, visible, remove }: Props) => {
|
||||
<div className="card-body">
|
||||
<div className="tab-content">
|
||||
<div className="tab-pane active show" id="tab-details" role="tabpanel">
|
||||
<DomainNamesField isWildcardPermitted />
|
||||
<DomainNamesField isWildcardPermitted dnsProviderWildcardSupported />
|
||||
</div>
|
||||
<div className="tab-pane" id="tab-ssl" role="tabpanel">
|
||||
<SSLCertificateField
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import CodeEditor from "@uiw/react-textarea-code-editor";
|
||||
import EasyModal, { type InnerModalProps } from "ez-modal-react";
|
||||
import { Alert } from "react-bootstrap";
|
||||
import Modal from "react-bootstrap/Modal";
|
||||
@@ -39,9 +40,22 @@ const EventDetailsModal = EasyModal.create(({ id, visible, remove }: Props) => {
|
||||
<EventFormatter row={data} />
|
||||
</div>
|
||||
<hr className="mt-4 mb-3" />
|
||||
<pre>
|
||||
<code>{JSON.stringify(data.meta, null, 2)}</code>
|
||||
</pre>
|
||||
<CodeEditor
|
||||
language="json"
|
||||
padding={15}
|
||||
data-color-mode="dark"
|
||||
minHeight={200}
|
||||
indentWidth={2}
|
||||
style={{
|
||||
fontFamily:
|
||||
"ui-monospace,SFMono-Regular,SF Mono,Consolas,Liberation Mono,Menlo,monospace",
|
||||
borderRadius: "0.3rem",
|
||||
minHeight: "200px",
|
||||
backgroundColor: "var(--tblr-bg-surface-dark)",
|
||||
}}
|
||||
readOnly
|
||||
value={JSON.stringify(data.meta, null, 2)}
|
||||
/>
|
||||
</div>
|
||||
</Modal.Body>
|
||||
<Modal.Footer>
|
||||
|
||||
188
frontend/src/modals/HTTPCertificateModal.tsx
Normal file
188
frontend/src/modals/HTTPCertificateModal.tsx
Normal file
@@ -0,0 +1,188 @@
|
||||
import { IconAlertTriangle } from "@tabler/icons-react";
|
||||
import EasyModal, { type InnerModalProps } from "ez-modal-react";
|
||||
import { Form, Formik } from "formik";
|
||||
import { type ReactNode, useState } from "react";
|
||||
import { Alert } from "react-bootstrap";
|
||||
import Modal from "react-bootstrap/Modal";
|
||||
import { createCertificate, testHttpCertificate } from "src/api/backend";
|
||||
import { Button, DomainNamesField } from "src/components";
|
||||
import { T } from "src/locale";
|
||||
import { showObjectSuccess } from "src/notifications";
|
||||
|
||||
const showHTTPCertificateModal = () => {
|
||||
EasyModal.show(HTTPCertificateModal);
|
||||
};
|
||||
|
||||
const HTTPCertificateModal = EasyModal.create(({ visible, remove }: InnerModalProps) => {
|
||||
const [errorMsg, setErrorMsg] = useState<ReactNode | null>(null);
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
const [domains, setDomains] = useState([] as string[]);
|
||||
const [isTesting, setIsTesting] = useState(false);
|
||||
const [testResults, setTestResults] = useState(null as Record<string, string> | null);
|
||||
|
||||
const onSubmit = async (values: any, { setSubmitting }: any) => {
|
||||
if (isSubmitting) return;
|
||||
setIsSubmitting(true);
|
||||
setErrorMsg(null);
|
||||
|
||||
try {
|
||||
await createCertificate(values);
|
||||
showObjectSuccess("certificate", "saved");
|
||||
remove();
|
||||
} catch (err: any) {
|
||||
setErrorMsg(<T id={err.message} />);
|
||||
}
|
||||
setIsSubmitting(false);
|
||||
setSubmitting(false);
|
||||
};
|
||||
|
||||
const handleTest = async () => {
|
||||
setIsTesting(true);
|
||||
setErrorMsg(null);
|
||||
setTestResults(null);
|
||||
try {
|
||||
const result = await testHttpCertificate(domains);
|
||||
setTestResults(result);
|
||||
} catch (err: any) {
|
||||
setErrorMsg(<T id={err.message} />);
|
||||
}
|
||||
setIsTesting(false);
|
||||
};
|
||||
|
||||
const parseTestResults = () => {
|
||||
const elms = [];
|
||||
for (const domain in testResults) {
|
||||
const status = testResults[domain];
|
||||
if (status === "ok") {
|
||||
elms.push(
|
||||
<p>
|
||||
<strong>{domain}:</strong> <T id="certificates.http.reachability-ok" />
|
||||
</p>,
|
||||
);
|
||||
} else {
|
||||
if (status === "no-host") {
|
||||
elms.push(
|
||||
<p>
|
||||
<strong>{domain}:</strong> <T id="certificates.http.reachability-not-resolved" />
|
||||
</p>,
|
||||
);
|
||||
} else if (status === "failed") {
|
||||
elms.push(
|
||||
<p>
|
||||
<strong>{domain}:</strong> <T id="certificates.http.reachability-failed-to-check" />
|
||||
</p>,
|
||||
);
|
||||
} else if (status === "404") {
|
||||
elms.push(
|
||||
<p>
|
||||
<strong>{domain}:</strong> <T id="certificates.http.reachability-404" />
|
||||
</p>,
|
||||
);
|
||||
} else if (status === "wrong-data") {
|
||||
elms.push(
|
||||
<p>
|
||||
<strong>{domain}:</strong> <T id="certificates.http.reachability-wrong-data" />
|
||||
</p>,
|
||||
);
|
||||
} else if (status.startsWith("other:")) {
|
||||
const code = status.substring(6);
|
||||
elms.push(
|
||||
<p>
|
||||
<strong>{domain}:</strong> <T id="certificates.http.reachability-other" data={{ code }} />
|
||||
</p>,
|
||||
);
|
||||
} else {
|
||||
// This should never happen
|
||||
elms.push(
|
||||
<p>
|
||||
<strong>{domain}:</strong> ?
|
||||
</p>,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return <>{elms}</>;
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal show={visible} onHide={remove}>
|
||||
<Formik
|
||||
initialValues={
|
||||
{
|
||||
domainNames: [],
|
||||
provider: "letsencrypt",
|
||||
} as any
|
||||
}
|
||||
onSubmit={onSubmit}
|
||||
>
|
||||
{() => (
|
||||
<Form>
|
||||
<Modal.Header closeButton>
|
||||
<Modal.Title>
|
||||
<T id="object.add" tData={{ object: "lets-encrypt-via-http" }} />
|
||||
</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body className="p-0">
|
||||
<Alert variant="danger" show={!!errorMsg} onClose={() => setErrorMsg(null)} dismissible>
|
||||
{errorMsg}
|
||||
</Alert>
|
||||
<div className="card m-0 border-0">
|
||||
<div className="card-body">
|
||||
<p className="text-warning">
|
||||
<IconAlertTriangle size={16} className="me-1" />
|
||||
<T id="certificates.http.warning" />
|
||||
</p>
|
||||
<DomainNamesField
|
||||
onChange={(doms) => {
|
||||
setDomains(doms);
|
||||
setTestResults(null);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{testResults ? (
|
||||
<div className="card-footer">
|
||||
<h5>
|
||||
<T id="certificates.http.test-results" />
|
||||
</h5>
|
||||
{parseTestResults()}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</Modal.Body>
|
||||
<Modal.Footer>
|
||||
<Button data-bs-dismiss="modal" onClick={remove} disabled={isSubmitting || isTesting}>
|
||||
<T id="cancel" />
|
||||
</Button>
|
||||
<div className="ms-auto">
|
||||
<Button
|
||||
type="button"
|
||||
actionType="secondary"
|
||||
className="me-3"
|
||||
data-bs-dismiss="modal"
|
||||
isLoading={isTesting}
|
||||
disabled={isSubmitting || domains.length === 0}
|
||||
onClick={handleTest}
|
||||
>
|
||||
<T id="test" />
|
||||
</Button>
|
||||
<Button
|
||||
type="submit"
|
||||
actionType="primary"
|
||||
className="bg-pink"
|
||||
data-bs-dismiss="modal"
|
||||
isLoading={isSubmitting}
|
||||
disabled={isSubmitting || isTesting}
|
||||
>
|
||||
<T id="save" />
|
||||
</Button>
|
||||
</div>
|
||||
</Modal.Footer>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
</Modal>
|
||||
);
|
||||
});
|
||||
|
||||
export { showHTTPCertificateModal };
|
||||
@@ -159,7 +159,7 @@ const ProxyHostModal = EasyModal.create(({ id, visible, remove }: Props) => {
|
||||
<div className="card-body">
|
||||
<div className="tab-content">
|
||||
<div className="tab-pane active show" id="tab-details" role="tabpanel">
|
||||
<DomainNamesField isWildcardPermitted />
|
||||
<DomainNamesField isWildcardPermitted dnsProviderWildcardSupported />
|
||||
<div className="row">
|
||||
<div className="col-md-3">
|
||||
<Field name="forwardScheme">
|
||||
|
||||
@@ -144,7 +144,7 @@ const RedirectionHostModal = EasyModal.create(({ id, visible, remove }: Props) =
|
||||
<div className="card-body">
|
||||
<div className="tab-content">
|
||||
<div className="tab-pane active show" id="tab-details" role="tabpanel">
|
||||
<DomainNamesField isWildcardPermitted />
|
||||
<DomainNamesField isWildcardPermitted dnsProviderWildcardSupported />
|
||||
<div className="row">
|
||||
<div className="col-md-4">
|
||||
<Field name="forwardScheme">
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
export * from "./AccessListModal";
|
||||
export * from "./ChangePasswordModal";
|
||||
export * from "./CustomCertificateModal";
|
||||
export * from "./DeadHostModal";
|
||||
export * from "./DeleteConfirmModal";
|
||||
export * from "./DNSCertificateModal";
|
||||
export * from "./EventDetailsModal";
|
||||
export * from "./HTTPCertificateModal";
|
||||
export * from "./PermissionsModal";
|
||||
export * from "./ProxyHostModal";
|
||||
export * from "./RedirectionHostModal";
|
||||
|
||||
@@ -5,6 +5,7 @@ import type { Certificate } from "src/api/backend";
|
||||
import { DomainsFormatter, EmptyData, GravatarFormatter } from "src/components";
|
||||
import { TableLayout } from "src/components/Table/TableLayout";
|
||||
import { intl, T } from "src/locale";
|
||||
import { showCustomCertificateModal, showDNSCertificateModal, showHTTPCertificateModal } from "src/modals";
|
||||
|
||||
interface Props {
|
||||
data: Certificate[];
|
||||
@@ -121,17 +122,28 @@ export default function Table({ data, isFetching }: Props) {
|
||||
href="#"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
// onNew();
|
||||
showHTTPCertificateModal();
|
||||
}}
|
||||
>
|
||||
<T id="lets-encrypt" />
|
||||
<T id="lets-encrypt-via-http" />
|
||||
</a>
|
||||
<a
|
||||
className="dropdown-item"
|
||||
href="#"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
// onNewCustom();
|
||||
showDNSCertificateModal();
|
||||
}}
|
||||
>
|
||||
<T id="lets-encrypt-via-dns" />
|
||||
</a>
|
||||
<div className="dropdown-divider" />
|
||||
<a
|
||||
className="dropdown-item"
|
||||
href="#"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
showCustomCertificateModal();
|
||||
}}
|
||||
>
|
||||
<T id="certificates.custom" />
|
||||
|
||||
@@ -3,6 +3,7 @@ import Alert from "react-bootstrap/Alert";
|
||||
import { LoadingPage } from "src/components";
|
||||
import { useCertificates } from "src/hooks";
|
||||
import { T } from "src/locale";
|
||||
import { showCustomCertificateModal, showDNSCertificateModal, showHTTPCertificateModal } from "src/modals";
|
||||
import Table from "./Table";
|
||||
|
||||
export default function TableWrapper() {
|
||||
@@ -54,10 +55,35 @@ export default function TableWrapper() {
|
||||
<T id="object.add" tData={{ object: "certificate" }} />
|
||||
</button>
|
||||
<div className="dropdown-menu">
|
||||
<a className="dropdown-item" href="#">
|
||||
<T id="lets-encrypt" />
|
||||
<a
|
||||
className="dropdown-item"
|
||||
href="#"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
showHTTPCertificateModal();
|
||||
}}
|
||||
>
|
||||
<T id="lets-encrypt-via-http" />
|
||||
</a>
|
||||
<a className="dropdown-item" href="#">
|
||||
<a
|
||||
className="dropdown-item"
|
||||
href="#"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
showDNSCertificateModal();
|
||||
}}
|
||||
>
|
||||
<T id="lets-encrypt-via-dns" />
|
||||
</a>
|
||||
<div className="dropdown-divider" />
|
||||
<a
|
||||
className="dropdown-item"
|
||||
href="#"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
showCustomCertificateModal();
|
||||
}}
|
||||
>
|
||||
<T id="certificates.custom" />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -118,15 +118,9 @@ const Dashboard = () => {
|
||||
- check mobile
|
||||
- add help docs for host types
|
||||
- REDO SCREENSHOTS in docs folder
|
||||
- translations for:
|
||||
- src/components/Form/AccessField.tsx
|
||||
- src/components/Form/SSLCertificateField.tsx
|
||||
- src/components/Form/DNSProviderFields.tsx
|
||||
- search codebase for "TODO"
|
||||
- update documentation to add development notes for translations
|
||||
- use syntax highligting for audit logs json output
|
||||
- double check output of access field selection on proxy host dialog, after access lists are completed
|
||||
- proxy host custom locations dialog
|
||||
- check permissions in all places
|
||||
|
||||
More for api, then implement here:
|
||||
|
||||
@@ -37,13 +37,12 @@ export default function TableWrapper() {
|
||||
|
||||
let filtered = null;
|
||||
if (search && data) {
|
||||
filtered = data?.filter((_item) => {
|
||||
return true;
|
||||
// TODO
|
||||
// item.domainNames.some((domain: string) => domain.toLowerCase().includes(search)) ||
|
||||
// item.forwardDomainName.toLowerCase().includes(search)
|
||||
// );
|
||||
});
|
||||
filtered = data?.filter(
|
||||
(item) =>
|
||||
item.domainNames.some((domain: string) => domain.toLowerCase().includes(search)) ||
|
||||
item.forwardHost.toLowerCase().includes(search) ||
|
||||
`${item.forwardPort}`.includes(search),
|
||||
);
|
||||
} else if (search !== "") {
|
||||
// this can happen if someone deletes the last item while searching
|
||||
setSearch("");
|
||||
|
||||
@@ -203,59 +203,59 @@
|
||||
"@babel/helper-string-parser" "^7.27.1"
|
||||
"@babel/helper-validator-identifier" "^7.27.1"
|
||||
|
||||
"@biomejs/biome@^2.2.6":
|
||||
version "2.2.6"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/biome/-/biome-2.2.6.tgz#76d8afbdd609a5dbace84bc982ae974a24b70b62"
|
||||
integrity sha512-yKTCNGhek0rL5OEW1jbLeZX8LHaM8yk7+3JRGv08my+gkpmtb5dDE+54r2ZjZx0ediFEn1pYBOJSmOdDP9xtFw==
|
||||
"@biomejs/biome@^2.3.0":
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/biome/-/biome-2.3.0.tgz#80030b68d94bd0a0761ac2cd22cc4f2c0f23f4f9"
|
||||
integrity sha512-shdUY5H3S3tJVUWoVWo5ua+GdPW5lRHf+b0IwZ4OC1o2zOKQECZ6l2KbU6t89FNhtd3Qx5eg5N7/UsQWGQbAFw==
|
||||
optionalDependencies:
|
||||
"@biomejs/cli-darwin-arm64" "2.2.6"
|
||||
"@biomejs/cli-darwin-x64" "2.2.6"
|
||||
"@biomejs/cli-linux-arm64" "2.2.6"
|
||||
"@biomejs/cli-linux-arm64-musl" "2.2.6"
|
||||
"@biomejs/cli-linux-x64" "2.2.6"
|
||||
"@biomejs/cli-linux-x64-musl" "2.2.6"
|
||||
"@biomejs/cli-win32-arm64" "2.2.6"
|
||||
"@biomejs/cli-win32-x64" "2.2.6"
|
||||
"@biomejs/cli-darwin-arm64" "2.3.0"
|
||||
"@biomejs/cli-darwin-x64" "2.3.0"
|
||||
"@biomejs/cli-linux-arm64" "2.3.0"
|
||||
"@biomejs/cli-linux-arm64-musl" "2.3.0"
|
||||
"@biomejs/cli-linux-x64" "2.3.0"
|
||||
"@biomejs/cli-linux-x64-musl" "2.3.0"
|
||||
"@biomejs/cli-win32-arm64" "2.3.0"
|
||||
"@biomejs/cli-win32-x64" "2.3.0"
|
||||
|
||||
"@biomejs/cli-darwin-arm64@2.2.6":
|
||||
version "2.2.6"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.2.6.tgz#b232a7d92c0b28884c1cf99d4348e1a52f95931f"
|
||||
integrity sha512-UZPmn3M45CjTYulgcrFJFZv7YmK3pTxTJDrFYlNElT2FNnkkX4fsxjExTSMeWKQYoZjvekpH5cvrYZZlWu3yfA==
|
||||
"@biomejs/cli-darwin-arm64@2.3.0":
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.3.0.tgz#78cef4d7415adbf0718c7854e7160e181d916652"
|
||||
integrity sha512-3cJVT0Z5pbTkoBmbjmDZTDFYxIkRcrs9sYVJbIBHU8E6qQxgXAaBfSVjjCreG56rfDuQBr43GzwzmaHPcu4vlw==
|
||||
|
||||
"@biomejs/cli-darwin-x64@2.2.6":
|
||||
version "2.2.6"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.2.6.tgz#3a2d1582037735f8ed5243aa6d3cc4f4082c5f42"
|
||||
integrity sha512-HOUIquhHVgh/jvxyClpwlpl/oeMqntlteL89YqjuFDiZ091P0vhHccwz+8muu3nTyHWM5FQslt+4Jdcd67+xWQ==
|
||||
"@biomejs/cli-darwin-x64@2.3.0":
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.3.0.tgz#068baf1f0f748c01658ba9bb511d8d18461d922b"
|
||||
integrity sha512-6LIkhglh3UGjuDqJXsK42qCA0XkD1Ke4K/raFOii7QQPbM8Pia7Qj2Hji4XuF2/R78hRmEx7uKJH3t/Y9UahtQ==
|
||||
|
||||
"@biomejs/cli-linux-arm64-musl@2.2.6":
|
||||
version "2.2.6"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.2.6.tgz#2bfe0859c55c840c0648f2b307efccca2527d655"
|
||||
integrity sha512-TjCenQq3N6g1C+5UT3jE1bIiJb5MWQvulpUngTIpFsL4StVAUXucWD0SL9MCW89Tm6awWfeXBbZBAhJwjyFbRQ==
|
||||
"@biomejs/cli-linux-arm64-musl@2.3.0":
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.3.0.tgz#9a1350184abcea8092957a9519098cac7629705a"
|
||||
integrity sha512-nDksoFdwZ2YrE7NiYDhtMhL2UgFn8Kb7Y0bYvnTAakHnqEdb4lKindtBc1f+xg2Snz0JQhJUYO7r9CDBosRU5w==
|
||||
|
||||
"@biomejs/cli-linux-arm64@2.2.6":
|
||||
version "2.2.6"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.2.6.tgz#aa1817296d84bda6ea972a54b139d1664580c190"
|
||||
integrity sha512-BpGtuMJGN+o8pQjvYsUKZ+4JEErxdSmcRD/JG3mXoWc6zrcA7OkuyGFN1mDggO0Q1n7qXxo/PcupHk8gzijt5g==
|
||||
"@biomejs/cli-linux-arm64@2.3.0":
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.3.0.tgz#f322daebb32fe0b18f7981c8cdbe84a06852bfee"
|
||||
integrity sha512-uhAsbXySX7xsXahegDg5h3CDgfMcRsJvWLFPG0pjkylgBb9lErbK2C0UINW52zhwg0cPISB09lxHPxCau4e2xA==
|
||||
|
||||
"@biomejs/cli-linux-x64-musl@2.2.6":
|
||||
version "2.2.6"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.2.6.tgz#b65f9191420e3384e287b21a8b1769795ee2c4c1"
|
||||
integrity sha512-1ZcBux8zVM3JhWN2ZCPaYf0+ogxXG316uaoXJdgoPZcdK/rmRcRY7PqHdAos2ExzvjIdvhQp72UcveI98hgOog==
|
||||
"@biomejs/cli-linux-x64-musl@2.3.0":
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.3.0.tgz#ce441d5c00eda977b74e4116f9723f2edc579485"
|
||||
integrity sha512-+i9UcJwl99uAhtRQDz9jUAh+Xkb097eekxs/D9j4deWDg5/yB/jPWzISe1nBHvlzTXsdUSj0VvB4Go2DSpKIMw==
|
||||
|
||||
"@biomejs/cli-linux-x64@2.2.6":
|
||||
version "2.2.6"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-x64/-/cli-linux-x64-2.2.6.tgz#5c5f07264bed31a436db60577c77ea9f64a62d2b"
|
||||
integrity sha512-1HaM/dpI/1Z68zp8ZdT6EiBq+/O/z97a2AiHMl+VAdv5/ELckFt9EvRb8hDHpk8hUMoz03gXkC7VPXOVtU7faA==
|
||||
"@biomejs/cli-linux-x64@2.3.0":
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-linux-x64/-/cli-linux-x64-2.3.0.tgz#da7ea904307b3211df62a4b42e5a022f8f583009"
|
||||
integrity sha512-uxa8reA2s1VgoH8MhbGlCmMOt3JuSE1vJBifkh1ulaPiuk0SPx8cCdpnm9NWnTe2x/LfWInWx4sZ7muaXTPGGw==
|
||||
|
||||
"@biomejs/cli-win32-arm64@2.2.6":
|
||||
version "2.2.6"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.2.6.tgz#a47ef2d6bec694df088ba70ffd6e89839c9c2304"
|
||||
integrity sha512-h3A88G8PGM1ryTeZyLlSdfC/gz3e95EJw9BZmA6Po412DRqwqPBa2Y9U+4ZSGUAXCsnSQE00jLV8Pyrh0d+jQw==
|
||||
"@biomejs/cli-win32-arm64@2.3.0":
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.3.0.tgz#cdc0f8bbf025fb28c5b03b326128cce363ecffa5"
|
||||
integrity sha512-ynjmsJLIKrAjC3CCnKMMhzcnNy8dbQWjKfSU5YA0mIruTxBNMbkAJp+Pr2iV7/hFou+66ZSD/WV8hmLEmhUaXA==
|
||||
|
||||
"@biomejs/cli-win32-x64@2.2.6":
|
||||
version "2.2.6"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-win32-x64/-/cli-win32-x64-2.2.6.tgz#cec00e860d9f20d820a48db4a6c7ab3b35c83ac6"
|
||||
integrity sha512-yx0CqeOhPjYQ5ZXgPfu8QYkgBhVJyvWe36as7jRuPrKPO5ylVDfwVtPQ+K/mooNTADW0IhxOZm3aPu16dP8yNQ==
|
||||
"@biomejs/cli-win32-x64@2.3.0":
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@biomejs/cli-win32-x64/-/cli-win32-x64-2.3.0.tgz#10e1de6222e272a1e3e395b3d845ee66cb6febd8"
|
||||
integrity sha512-zOCYmCRVkWXc9v8P7OLbLlGGMxQTKMvi+5IC4v7O8DkjLCOHRzRVK/Lno2pGZNo0lzKM60pcQOhH8HVkXMQdFg==
|
||||
|
||||
"@emotion/babel-plugin@^11.13.5":
|
||||
version "11.13.5"
|
||||
@@ -716,10 +716,10 @@
|
||||
uncontrollable "^8.0.4"
|
||||
warning "^4.0.3"
|
||||
|
||||
"@rolldown/pluginutils@1.0.0-beta.38":
|
||||
version "1.0.0-beta.38"
|
||||
resolved "https://registry.yarnpkg.com/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.38.tgz#95253608c4629eb2a5f3d656009ac9ba031eb292"
|
||||
integrity sha512-N/ICGKleNhA5nc9XXQG/kkKHJ7S55u0x0XUJbbkmdCnFuoRkM1Il12q9q0eX19+M7KKUEPw/daUPIRnxhcxAIw==
|
||||
"@rolldown/pluginutils@1.0.0-beta.43":
|
||||
version "1.0.0-beta.43"
|
||||
resolved "https://registry.yarnpkg.com/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.43.tgz#fa8249860113711ad3c8053bc79cb07c79b77f62"
|
||||
integrity sha512-5Uxg7fQUCmfhax7FJke2+8B6cqgeUJUD9o2uXIKXhD+mG0mL6NObmVoi9wXEU1tY89mZKgAYA6fTbftx3q2ZPQ==
|
||||
|
||||
"@rollup/rollup-android-arm-eabi@4.50.0":
|
||||
version "4.50.0"
|
||||
@@ -826,6 +826,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.50.0.tgz#d81efe6a12060c7feddf9805e2a94c3ab0679f48"
|
||||
integrity sha512-xMmiWRR8sp72Zqwjgtf3QbZfF1wdh8X2ABu3EaozvZcyHJeU0r+XAnXdKgs4cCAp6ORoYoCygipYP1mjmbjrsg==
|
||||
|
||||
"@standard-schema/spec@^1.0.0":
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@standard-schema/spec/-/spec-1.0.0.tgz#f193b73dc316c4170f2e82a881da0f550d551b9c"
|
||||
integrity sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==
|
||||
|
||||
"@swc/helpers@^0.5.0":
|
||||
version "0.5.17"
|
||||
resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.17.tgz#5a7be95ac0f0bf186e7e6e890e7a6f6cda6ce971"
|
||||
@@ -853,10 +858,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@tabler/icons/-/icons-3.35.0.tgz#6f35247e41baba2a1b0f4dff048bb1335d6c1075"
|
||||
integrity sha512-yYXe+gJ56xlZFiXwV9zVoe3FWCGuZ/D7/G4ZIlDtGxSx5CGQK110wrnT29gUj52kEZoxqF7oURTk97GQxELOFQ==
|
||||
|
||||
"@tanstack/query-core@5.90.3":
|
||||
version "5.90.3"
|
||||
resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-5.90.3.tgz#461422437d30aad0a7618122c5e7568095d79cfb"
|
||||
integrity sha512-HtPOnCwmx4dd35PfXU8jjkhwYrsHfuqgC8RCJIwWglmhIUIlzPP0ZcEkDAc+UtAWCiLm7T8rxeEfHZlz3hYMCA==
|
||||
"@tanstack/query-core@5.90.5":
|
||||
version "5.90.5"
|
||||
resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-5.90.5.tgz#0175f9f517514906db8ab379589ed3f96694ecc4"
|
||||
integrity sha512-wLamYp7FaDq6ZnNehypKI5fNvxHPfTYylE0m/ZpuuzJfJqhR5Pxg9gvGBHZx4n7J+V5Rg5mZxHHTlv25Zt5u+w==
|
||||
|
||||
"@tanstack/query-devtools@5.90.1":
|
||||
version "5.90.1"
|
||||
@@ -870,12 +875,12 @@
|
||||
dependencies:
|
||||
"@tanstack/query-devtools" "5.90.1"
|
||||
|
||||
"@tanstack/react-query@^5.90.3":
|
||||
version "5.90.3"
|
||||
resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-5.90.3.tgz#670ed97948c5d4e3c075049f8a01e84d51e0bdc4"
|
||||
integrity sha512-i/LRL6DtuhG6bjGzavIMIVuKKPWx2AnEBIsBfuMm3YoHne0a20nWmsatOCBcVSaT0/8/5YFjNkebHAPLVUSi0Q==
|
||||
"@tanstack/react-query@^5.90.5":
|
||||
version "5.90.5"
|
||||
resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-5.90.5.tgz#545e61282c787bd87ac5785da9a4943462f78ef6"
|
||||
integrity sha512-pN+8UWpxZkEJ/Rnnj2v2Sxpx1WFlaa9L6a4UO89p6tTQbeo+m0MS8oYDjbggrR8QcTyjKoYWKS3xJQGr3ExT8Q==
|
||||
dependencies:
|
||||
"@tanstack/query-core" "5.90.3"
|
||||
"@tanstack/query-core" "5.90.5"
|
||||
|
||||
"@tanstack/react-table@^8.21.3":
|
||||
version "8.21.3"
|
||||
@@ -1102,78 +1107,75 @@
|
||||
resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz#d06bbb384ebcf6c505fde1c3d0ed4ddffe0aaff8"
|
||||
integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==
|
||||
|
||||
"@vitejs/plugin-react@^5.0.4":
|
||||
version "5.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-5.0.4.tgz#d642058e89c5b712655c8cbd13482f5813519602"
|
||||
integrity sha512-La0KD0vGkVkSk6K+piWDKRUyg8Rl5iAIKRMH0vMJI0Eg47bq1eOxmoObAaQG37WMW9MSyk7Cs8EIWwJC1PtzKA==
|
||||
"@vitejs/plugin-react@^5.1.0":
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-5.1.0.tgz#1f37671a227571437d6e324b824256dac157570e"
|
||||
integrity sha512-4LuWrg7EKWgQaMJfnN+wcmbAW+VSsCmqGohftWjuct47bv8uE4n/nPpq4XjJPsxgq00GGG5J8dvBczp8uxScew==
|
||||
dependencies:
|
||||
"@babel/core" "^7.28.4"
|
||||
"@babel/plugin-transform-react-jsx-self" "^7.27.1"
|
||||
"@babel/plugin-transform-react-jsx-source" "^7.27.1"
|
||||
"@rolldown/pluginutils" "1.0.0-beta.38"
|
||||
"@rolldown/pluginutils" "1.0.0-beta.43"
|
||||
"@types/babel__core" "^7.20.5"
|
||||
react-refresh "^0.17.0"
|
||||
react-refresh "^0.18.0"
|
||||
|
||||
"@vitest/expect@3.2.4":
|
||||
version "3.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-3.2.4.tgz#8362124cd811a5ee11c5768207b9df53d34f2433"
|
||||
integrity sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==
|
||||
"@vitest/expect@4.0.3":
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-4.0.3.tgz#04a3c7f8220fb7022dbca368697f16fe008f816b"
|
||||
integrity sha512-v3eSDx/bF25pzar6aEJrrdTXJduEBU3uSGXHslIdGIpJVP8tQQHV6x1ZfzbFQ/bLIomLSbR/2ZCfnaEGkWkiVQ==
|
||||
dependencies:
|
||||
"@standard-schema/spec" "^1.0.0"
|
||||
"@types/chai" "^5.2.2"
|
||||
"@vitest/spy" "3.2.4"
|
||||
"@vitest/utils" "3.2.4"
|
||||
chai "^5.2.0"
|
||||
tinyrainbow "^2.0.0"
|
||||
"@vitest/spy" "4.0.3"
|
||||
"@vitest/utils" "4.0.3"
|
||||
chai "^6.0.1"
|
||||
tinyrainbow "^3.0.3"
|
||||
|
||||
"@vitest/mocker@3.2.4":
|
||||
version "3.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-3.2.4.tgz#4471c4efbd62db0d4fa203e65cc6b058a85cabd3"
|
||||
integrity sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==
|
||||
"@vitest/mocker@4.0.3":
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-4.0.3.tgz#2a9665dc0966584dbdda5329fc7ed815ae6d6eef"
|
||||
integrity sha512-evZcRspIPbbiJEe748zI2BRu94ThCBE+RkjCpVF8yoVYuTV7hMe+4wLF/7K86r8GwJHSmAPnPbZhpXWWrg1qbA==
|
||||
dependencies:
|
||||
"@vitest/spy" "3.2.4"
|
||||
"@vitest/spy" "4.0.3"
|
||||
estree-walker "^3.0.3"
|
||||
magic-string "^0.30.17"
|
||||
magic-string "^0.30.19"
|
||||
|
||||
"@vitest/pretty-format@3.2.4", "@vitest/pretty-format@^3.2.4":
|
||||
version "3.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-3.2.4.tgz#3c102f79e82b204a26c7a5921bf47d534919d3b4"
|
||||
integrity sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==
|
||||
"@vitest/pretty-format@4.0.3":
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-4.0.3.tgz#0f7632c5100793eb1848efa1d826709639caf485"
|
||||
integrity sha512-N7gly/DRXzxa9w9sbDXwD9QNFYP2hw90LLLGDobPNwiWgyW95GMxsCt29/COIKKh3P7XJICR38PSDePenMBtsw==
|
||||
dependencies:
|
||||
tinyrainbow "^2.0.0"
|
||||
tinyrainbow "^3.0.3"
|
||||
|
||||
"@vitest/runner@3.2.4":
|
||||
version "3.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-3.2.4.tgz#5ce0274f24a971f6500f6fc166d53d8382430766"
|
||||
integrity sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==
|
||||
"@vitest/runner@4.0.3":
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-4.0.3.tgz#77003feebb25c014c3c74748ca3647b3b90ef648"
|
||||
integrity sha512-1/aK6fPM0lYXWyGKwop2Gbvz1plyTps/HDbIIJXYtJtspHjpXIeB3If07eWpVH4HW7Rmd3Rl+IS/+zEAXrRtXA==
|
||||
dependencies:
|
||||
"@vitest/utils" "3.2.4"
|
||||
pathe "^2.0.3"
|
||||
strip-literal "^3.0.0"
|
||||
|
||||
"@vitest/snapshot@3.2.4":
|
||||
version "3.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-3.2.4.tgz#40a8bc0346ac0aee923c0eefc2dc005d90bc987c"
|
||||
integrity sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==
|
||||
dependencies:
|
||||
"@vitest/pretty-format" "3.2.4"
|
||||
magic-string "^0.30.17"
|
||||
"@vitest/utils" "4.0.3"
|
||||
pathe "^2.0.3"
|
||||
|
||||
"@vitest/spy@3.2.4":
|
||||
version "3.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-3.2.4.tgz#cc18f26f40f3f028da6620046881f4e4518c2599"
|
||||
integrity sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==
|
||||
"@vitest/snapshot@4.0.3":
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-4.0.3.tgz#242d300dabd20de95a7e137906fe15a62301786d"
|
||||
integrity sha512-amnYmvZ5MTjNCP1HZmdeczAPLRD6iOm9+2nMRUGxbe/6sQ0Ymur0NnR9LIrWS8JA3wKE71X25D6ya/3LN9YytA==
|
||||
dependencies:
|
||||
tinyspy "^4.0.3"
|
||||
"@vitest/pretty-format" "4.0.3"
|
||||
magic-string "^0.30.19"
|
||||
pathe "^2.0.3"
|
||||
|
||||
"@vitest/utils@3.2.4":
|
||||
version "3.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-3.2.4.tgz#c0813bc42d99527fb8c5b138c7a88516bca46fea"
|
||||
integrity sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==
|
||||
"@vitest/spy@4.0.3":
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-4.0.3.tgz#b29246bf8e685dafc96cb99ca389fed7a48463ec"
|
||||
integrity sha512-82vVL8Cqz7rbXaNUl35V2G7xeNMAjBdNOVaHbrzznT9BmiCiPOzhf0FhU3eP41nP1bLDm/5wWKZqkG4nyU95DQ==
|
||||
|
||||
"@vitest/utils@4.0.3":
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-4.0.3.tgz#068fa94ac39fd596102f480b50be1103a7b9ca4f"
|
||||
integrity sha512-qV6KJkq8W3piW6MDIbGOmn1xhvcW4DuA07alqaQ+vdx7YA49J85pnwnxigZVQFQw3tWnQNRKWwhz5wbP6iv/GQ==
|
||||
dependencies:
|
||||
"@vitest/pretty-format" "3.2.4"
|
||||
loupe "^3.1.4"
|
||||
tinyrainbow "^2.0.0"
|
||||
"@vitest/pretty-format" "4.0.3"
|
||||
tinyrainbow "^3.0.3"
|
||||
|
||||
ansi-regex@^5.0.1:
|
||||
version "5.0.1"
|
||||
@@ -1197,11 +1199,6 @@ aria-query@^5.0.0:
|
||||
resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.2.tgz#93f81a43480e33a338f19163a3d10a50c01dcd59"
|
||||
integrity sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==
|
||||
|
||||
assertion-error@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7"
|
||||
integrity sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==
|
||||
|
||||
babel-plugin-macros@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1"
|
||||
@@ -1251,11 +1248,6 @@ buffer@^6.0.3:
|
||||
base64-js "^1.3.1"
|
||||
ieee754 "^1.2.1"
|
||||
|
||||
cac@^6.7.14:
|
||||
version "6.7.14"
|
||||
resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959"
|
||||
integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==
|
||||
|
||||
callsites@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
|
||||
@@ -1271,16 +1263,10 @@ ccount@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/ccount/-/ccount-2.0.1.tgz#17a3bf82302e0870d6da43a01311a8bc02a3ecf5"
|
||||
integrity sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==
|
||||
|
||||
chai@^5.2.0:
|
||||
version "5.3.3"
|
||||
resolved "https://registry.yarnpkg.com/chai/-/chai-5.3.3.tgz#dd3da955e270916a4bd3f625f4b919996ada7e06"
|
||||
integrity sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==
|
||||
dependencies:
|
||||
assertion-error "^2.0.1"
|
||||
check-error "^2.1.1"
|
||||
deep-eql "^5.0.1"
|
||||
loupe "^3.1.0"
|
||||
pathval "^2.0.0"
|
||||
chai@^6.0.1:
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/chai/-/chai-6.2.0.tgz#181bca6a219cddb99c3eeefb82483800ffa550ce"
|
||||
integrity sha512-aUTnJc/JipRzJrNADXVvpVqi6CO0dn3nx4EVPxijri+fj3LUUDyZQOgVeW54Ob3Y1Xh9Iz8f+CgaCl8v0mn9bA==
|
||||
|
||||
character-entities-html4@^2.0.0:
|
||||
version "2.1.0"
|
||||
@@ -1302,11 +1288,6 @@ character-reference-invalid@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz#85c66b041e43b47210faf401278abf808ac45cb9"
|
||||
integrity sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==
|
||||
|
||||
check-error@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/check-error/-/check-error-2.1.1.tgz#87eb876ae71ee388fa0471fe423f494be1d96ccc"
|
||||
integrity sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==
|
||||
|
||||
chokidar@^4.0.0, chokidar@^4.0.3:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30"
|
||||
@@ -1375,13 +1356,20 @@ date-fns@^4.1.0:
|
||||
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-4.1.0.tgz#64b3d83fff5aa80438f5b1a633c2e83b8a1c2d14"
|
||||
integrity sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==
|
||||
|
||||
debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.4.1:
|
||||
debug@^4.1.0, debug@^4.1.1, debug@^4.3.1:
|
||||
version "4.4.1"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b"
|
||||
integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==
|
||||
dependencies:
|
||||
ms "^2.1.3"
|
||||
|
||||
debug@^4.4.3:
|
||||
version "4.4.3"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a"
|
||||
integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==
|
||||
dependencies:
|
||||
ms "^2.1.3"
|
||||
|
||||
decimal.js@^10.4.3:
|
||||
version "10.6.0"
|
||||
resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.6.0.tgz#e649a43e3ab953a72192ff5983865e509f37ed9a"
|
||||
@@ -1399,11 +1387,6 @@ decode-uri-component@^0.4.1:
|
||||
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.4.1.tgz#2ac4859663c704be22bf7db760a1494a49ab2cc5"
|
||||
integrity sha512-+8VxcR21HhTy8nOt6jf20w0c9CADrw1O8d+VZ/YzzCt4bJ3uBjw+D1q2osAB8RnpwwaeYBxy0HyKQxD5JBMuuQ==
|
||||
|
||||
deep-eql@^5.0.1:
|
||||
version "5.0.2"
|
||||
resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-5.0.2.tgz#4b756d8d770a9257300825d52a2c2cff99c3a341"
|
||||
integrity sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==
|
||||
|
||||
deepmerge@^2.1.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170"
|
||||
@@ -1515,7 +1498,7 @@ estree-walker@^3.0.3:
|
||||
dependencies:
|
||||
"@types/estree" "^1.0.0"
|
||||
|
||||
expect-type@^1.2.1:
|
||||
expect-type@^1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.2.2.tgz#c030a329fb61184126c8447585bc75a7ec6fbff3"
|
||||
integrity sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==
|
||||
@@ -1599,10 +1582,10 @@ globrex@^0.1.2:
|
||||
resolved "https://registry.yarnpkg.com/globrex/-/globrex-0.1.2.tgz#dd5d9ec826232730cd6793a5e33a9302985e6098"
|
||||
integrity sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==
|
||||
|
||||
happy-dom@^20.0.2:
|
||||
version "20.0.2"
|
||||
resolved "https://registry.yarnpkg.com/happy-dom/-/happy-dom-20.0.2.tgz#da676a1e3d0742aff8ba4789db90445842538808"
|
||||
integrity sha512-pYOyu624+6HDbY+qkjILpQGnpvZOusItCk+rvF5/V+6NkcgTKnbOldpIy22tBnxoaLtlM9nXgoqAcW29/B7CIw==
|
||||
happy-dom@^20.0.8:
|
||||
version "20.0.8"
|
||||
resolved "https://registry.yarnpkg.com/happy-dom/-/happy-dom-20.0.8.tgz#9bece083d2675ae45c2fc23871a9a02bb162a366"
|
||||
integrity sha512-TlYaNQNtzsZ97rNMBAm8U+e2cUQXNithgfCizkDgc11lgmN4j9CKMhO3FPGKWQYPwwkFcPpoXYF/CqEPLgzfOg==
|
||||
dependencies:
|
||||
"@types/node" "^20.0.0"
|
||||
"@types/whatwg-mimetype" "^3.0.2"
|
||||
@@ -1827,11 +1810,6 @@ is-plain-obj@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
||||
|
||||
js-tokens@^9.0.1:
|
||||
version "9.0.1"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-9.0.1.tgz#2ec43964658435296f6761b34e10671c2d9527f4"
|
||||
integrity sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==
|
||||
|
||||
jsesc@^3.0.2:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d"
|
||||
@@ -1874,11 +1852,6 @@ loose-envify@^1.0.0, loose-envify@^1.4.0:
|
||||
dependencies:
|
||||
js-tokens "^3.0.0 || ^4.0.0"
|
||||
|
||||
loupe@^3.1.0, loupe@^3.1.4:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.2.1.tgz#0095cf56dc5b7a9a7c08ff5b1a8796ec8ad17e76"
|
||||
integrity sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==
|
||||
|
||||
lru-cache@^5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
|
||||
@@ -1891,10 +1864,10 @@ lz-string@^1.5.0:
|
||||
resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941"
|
||||
integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==
|
||||
|
||||
magic-string@^0.30.17:
|
||||
version "0.30.18"
|
||||
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.18.tgz#905bfbbc6aa5692703a93db26a9edcaa0007d2bb"
|
||||
integrity sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ==
|
||||
magic-string@^0.30.19:
|
||||
version "0.30.21"
|
||||
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.21.tgz#56763ec09a0fa8091df27879fd94d19078c00d91"
|
||||
integrity sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==
|
||||
dependencies:
|
||||
"@jridgewell/sourcemap-codec" "^1.5.5"
|
||||
|
||||
@@ -2058,11 +2031,6 @@ pathe@^2.0.3:
|
||||
resolved "https://registry.yarnpkg.com/pathe/-/pathe-2.0.3.tgz#3ecbec55421685b70a9da872b2cff3e1cbed1716"
|
||||
integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==
|
||||
|
||||
pathval@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/pathval/-/pathval-2.0.1.tgz#8855c5a2899af072d6ac05d11e46045ad0dc605d"
|
||||
integrity sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==
|
||||
|
||||
performance-now@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
|
||||
@@ -2216,10 +2184,10 @@ react-lifecycles-compat@^3.0.4:
|
||||
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
|
||||
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
|
||||
|
||||
react-refresh@^0.17.0:
|
||||
version "0.17.0"
|
||||
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.17.0.tgz#b7e579c3657f23d04eccbe4ad2e58a8ed51e7e53"
|
||||
integrity sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==
|
||||
react-refresh@^0.18.0:
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.18.0.tgz#2dce97f4fe932a4d8142fa1630e475c1729c8062"
|
||||
integrity sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==
|
||||
|
||||
react-router-dom@^7.9.4:
|
||||
version "7.9.4"
|
||||
@@ -2471,13 +2439,6 @@ strip-indent@^3.0.0:
|
||||
dependencies:
|
||||
min-indent "^1.0.0"
|
||||
|
||||
strip-literal@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-literal/-/strip-literal-3.0.0.tgz#ce9c452a91a0af2876ed1ae4e583539a353df3fc"
|
||||
integrity sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==
|
||||
dependencies:
|
||||
js-tokens "^9.0.1"
|
||||
|
||||
stylis@4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51"
|
||||
@@ -2524,20 +2485,10 @@ tinyglobby@^0.2.15:
|
||||
fdir "^6.5.0"
|
||||
picomatch "^4.0.3"
|
||||
|
||||
tinypool@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-1.1.1.tgz#059f2d042bd37567fbc017d3d426bdd2a2612591"
|
||||
integrity sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==
|
||||
|
||||
tinyrainbow@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-2.0.0.tgz#9509b2162436315e80e3eee0fcce4474d2444294"
|
||||
integrity sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==
|
||||
|
||||
tinyspy@^4.0.3:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-4.0.3.tgz#d1d0f0602f4c15f1aae083a34d6d0df3363b1b52"
|
||||
integrity sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==
|
||||
tinyrainbow@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-3.0.3.tgz#984a5b1c1b25854a9b6bccbe77964d0593d1ea42"
|
||||
integrity sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==
|
||||
|
||||
tmp@^0.2.5:
|
||||
version "0.2.5"
|
||||
@@ -2703,17 +2654,6 @@ vfile@^6.0.0:
|
||||
"@types/unist" "^3.0.0"
|
||||
vfile-message "^4.0.0"
|
||||
|
||||
vite-node@3.2.4:
|
||||
version "3.2.4"
|
||||
resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-3.2.4.tgz#f3676d94c4af1e76898c162c92728bca65f7bb07"
|
||||
integrity sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==
|
||||
dependencies:
|
||||
cac "^6.7.14"
|
||||
debug "^4.4.1"
|
||||
es-module-lexer "^1.7.0"
|
||||
pathe "^2.0.3"
|
||||
vite "^5.0.0 || ^6.0.0 || ^7.0.0-0"
|
||||
|
||||
vite-plugin-checker@^0.11.0:
|
||||
version "0.11.0"
|
||||
resolved "https://registry.yarnpkg.com/vite-plugin-checker/-/vite-plugin-checker-0.11.0.tgz#063ce180c3751b790a6472e19c5d1a352b215070"
|
||||
@@ -2737,24 +2677,10 @@ vite-tsconfig-paths@^5.1.4:
|
||||
globrex "^0.1.2"
|
||||
tsconfck "^3.0.3"
|
||||
|
||||
"vite@^5.0.0 || ^6.0.0 || ^7.0.0-0":
|
||||
version "7.1.4"
|
||||
resolved "https://registry.yarnpkg.com/vite/-/vite-7.1.4.tgz#354944affb55e1aff0157406b74e0d0a3232df9a"
|
||||
integrity sha512-X5QFK4SGynAeeIt+A7ZWnApdUyHYm+pzv/8/A57LqSGcI88U6R6ipOs3uCesdc6yl7nl+zNO0t8LmqAdXcQihw==
|
||||
dependencies:
|
||||
esbuild "^0.25.0"
|
||||
fdir "^6.5.0"
|
||||
picomatch "^4.0.3"
|
||||
postcss "^8.5.6"
|
||||
rollup "^4.43.0"
|
||||
tinyglobby "^0.2.14"
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.3"
|
||||
|
||||
vite@^7.1.10:
|
||||
version "7.1.10"
|
||||
resolved "https://registry.yarnpkg.com/vite/-/vite-7.1.10.tgz#47c9970f3b0fe9057bfbcfeff8cd370edd7bd41b"
|
||||
integrity sha512-CmuvUBzVJ/e3HGxhg6cYk88NGgTnBoOo7ogtfJJ0fefUWAxN/WDSUa50o+oVBxuIhO8FoEZW0j2eW7sfjs5EtA==
|
||||
"vite@^6.0.0 || ^7.0.0", vite@^7.1.12:
|
||||
version "7.1.12"
|
||||
resolved "https://registry.yarnpkg.com/vite/-/vite-7.1.12.tgz#8b29a3f61eba23bcb93fc9ec9af4a3a1e83eecdb"
|
||||
integrity sha512-ZWyE8YXEXqJrrSLvYgrRP7p62OziLW7xI5HYGWFzOvupfAlrLvURSzv/FyGyy0eidogEM3ujU+kUG1zuHgb6Ug==
|
||||
dependencies:
|
||||
esbuild "^0.25.0"
|
||||
fdir "^6.5.0"
|
||||
@@ -2765,33 +2691,30 @@ vite@^7.1.10:
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.3"
|
||||
|
||||
vitest@^3.2.4:
|
||||
version "3.2.4"
|
||||
resolved "https://registry.yarnpkg.com/vitest/-/vitest-3.2.4.tgz#0637b903ad79d1539a25bc34c0ed54b5c67702ea"
|
||||
integrity sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==
|
||||
vitest@^4.0.3:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/vitest/-/vitest-4.0.3.tgz#6dcd04df504bb2260e755402768857d556d42d4b"
|
||||
integrity sha512-IUSop8jgaT7w0g1yOM/35qVtKjr/8Va4PrjzH1OUb0YH4c3OXB2lCZDkMAB6glA8T5w8S164oJGsbcmAecr4sA==
|
||||
dependencies:
|
||||
"@types/chai" "^5.2.2"
|
||||
"@vitest/expect" "3.2.4"
|
||||
"@vitest/mocker" "3.2.4"
|
||||
"@vitest/pretty-format" "^3.2.4"
|
||||
"@vitest/runner" "3.2.4"
|
||||
"@vitest/snapshot" "3.2.4"
|
||||
"@vitest/spy" "3.2.4"
|
||||
"@vitest/utils" "3.2.4"
|
||||
chai "^5.2.0"
|
||||
debug "^4.4.1"
|
||||
expect-type "^1.2.1"
|
||||
magic-string "^0.30.17"
|
||||
"@vitest/expect" "4.0.3"
|
||||
"@vitest/mocker" "4.0.3"
|
||||
"@vitest/pretty-format" "4.0.3"
|
||||
"@vitest/runner" "4.0.3"
|
||||
"@vitest/snapshot" "4.0.3"
|
||||
"@vitest/spy" "4.0.3"
|
||||
"@vitest/utils" "4.0.3"
|
||||
debug "^4.4.3"
|
||||
es-module-lexer "^1.7.0"
|
||||
expect-type "^1.2.2"
|
||||
magic-string "^0.30.19"
|
||||
pathe "^2.0.3"
|
||||
picomatch "^4.0.2"
|
||||
picomatch "^4.0.3"
|
||||
std-env "^3.9.0"
|
||||
tinybench "^2.9.0"
|
||||
tinyexec "^0.3.2"
|
||||
tinyglobby "^0.2.14"
|
||||
tinypool "^1.1.1"
|
||||
tinyrainbow "^2.0.0"
|
||||
vite "^5.0.0 || ^6.0.0 || ^7.0.0-0"
|
||||
vite-node "3.2.4"
|
||||
tinyglobby "^0.2.15"
|
||||
tinyrainbow "^3.0.3"
|
||||
vite "^6.0.0 || ^7.0.0"
|
||||
why-is-node-running "^2.3.0"
|
||||
|
||||
vscode-uri@^3.1.0:
|
||||
|
||||
@@ -15,7 +15,6 @@ if hash docker 2>/dev/null; then
|
||||
-e CI=true \
|
||||
-e NODE_OPTIONS=--openssl-legacy-provider \
|
||||
-v "$(pwd)/frontend:/app/frontend" \
|
||||
-v "$(pwd)/global:/app/global" \
|
||||
-w /app/frontend "${DOCKER_IMAGE}" \
|
||||
sh -c "yarn install && yarn lint && yarn build && chown -R $(id -u):$(id -g) /app/frontend"
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ docker pull "${TESTING_IMAGE}"
|
||||
echo -e "${BLUE}❯ ${CYAN}Testing backend ...${RESET}"
|
||||
docker run --rm \
|
||||
-v "$(pwd)/backend:/app" \
|
||||
-v "$(pwd)/global:/app/global" \
|
||||
-w /app \
|
||||
"${TESTING_IMAGE}" \
|
||||
sh -c 'yarn install && yarn lint . && rm -rf node_modules'
|
||||
|
||||
Reference in New Issue
Block a user