@vandenberghinc/volt 1.2.18 → 1.2.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/backend/dist/cjs/backend/src/payments/paddle.js +2 -2
- package/backend/dist/cjs/backend/src/payments/stripe/stripe.js +12 -14
- package/backend/dist/cjs/backend/src/server.d.ts +3 -25
- package/backend/dist/cjs/backend/src/server.js +15 -87
- package/backend/dist/cjs/backend/src/users.js +2 -2
- package/backend/dist/cjs/backend/src/view.js +1 -1
- package/backend/dist/esm/backend/src/payments/paddle.js +2 -2
- package/backend/dist/esm/backend/src/payments/stripe/stripe.js +13 -14
- package/backend/dist/esm/backend/src/server.d.ts +3 -25
- package/backend/dist/esm/backend/src/server.js +16 -91
- package/backend/dist/esm/backend/src/users.js +2 -2
- package/backend/dist/esm/backend/src/view.js +1 -1
- package/frontend/dist/backend/src/payments/paddle.js +2 -2
- package/frontend/dist/backend/src/payments/stripe/stripe.js +13 -14
- package/frontend/dist/backend/src/server.d.ts +3 -25
- package/frontend/dist/backend/src/server.js +16 -91
- package/frontend/dist/backend/src/users.js +2 -2
- package/frontend/dist/backend/src/view.js +1 -1
- package/package.json +1 -1
|
@@ -639,7 +639,7 @@ class Paddle {
|
|
|
639
639
|
}
|
|
640
640
|
product_ids.push(product.id);
|
|
641
641
|
if (typeof product.icon === "string" && product.icon.charAt(0) === "/") {
|
|
642
|
-
product.icon = `${this.server.
|
|
642
|
+
product.icon = `${this.server.https_domain}/${product.icon}`;
|
|
643
643
|
}
|
|
644
644
|
if (typeof product.id !== "string" || product.id === "") {
|
|
645
645
|
throw Error(`Product "${product_index}" does not have an assigned "id" attribute (string).`);
|
|
@@ -1260,7 +1260,7 @@ class Paddle {
|
|
|
1260
1260
|
const now = this.performance.start();
|
|
1261
1261
|
const webhook_settings = {
|
|
1262
1262
|
description: "volt webhook",
|
|
1263
|
-
destination: `${this.server.
|
|
1263
|
+
destination: `${this.server.https_domain}/volt/payments/webhook`,
|
|
1264
1264
|
type: "url",
|
|
1265
1265
|
subscribed_events: [
|
|
1266
1266
|
// "transaction.billed",
|
|
@@ -249,20 +249,18 @@ class Stripe {
|
|
|
249
249
|
async initialize(opts) {
|
|
250
250
|
this.products = await (0, import_products.initialize_products)(this.client, this.server, this.raw_products);
|
|
251
251
|
if (!opts.worker) {
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
this.webhook_signing_secret = res.webhook_signing_secret;
|
|
265
|
-
}
|
|
252
|
+
const res = await (0, import_webhooks.register_or_update_stripe_webhook_endpoint)(this.client, this.server, {
|
|
253
|
+
/**
|
|
254
|
+
* @warning
|
|
255
|
+
* Never change the webhook_id since this could break updating the webhook endpoint
|
|
256
|
+
* if the url / description etc changes.
|
|
257
|
+
*/
|
|
258
|
+
webhook_app_id: "Volt.Stripe.Webhook",
|
|
259
|
+
webhook_url: `${this.server.https_domain}/volt/api/stripe/webhook`,
|
|
260
|
+
description: "The internal volt stripe payments webhook endpoint.",
|
|
261
|
+
ensure_enabled: true
|
|
262
|
+
});
|
|
263
|
+
this.webhook_signing_secret = res.webhook_signing_secret;
|
|
266
264
|
await this.initialize_endpoints();
|
|
267
265
|
}
|
|
268
266
|
}
|
|
@@ -223,10 +223,10 @@ export declare class Server {
|
|
|
223
223
|
port: number;
|
|
224
224
|
/** The binded https port. */
|
|
225
225
|
https_port: number;
|
|
226
|
-
/** The raw domain. */
|
|
226
|
+
/** The raw domain without http/https . */
|
|
227
227
|
domain: string;
|
|
228
|
-
/** The
|
|
229
|
-
|
|
228
|
+
/** The https domain, this is used for things like stripe webhooks, metadata, etc. */
|
|
229
|
+
https_domain: string;
|
|
230
230
|
/** The persistent storage source directory. */
|
|
231
231
|
source: vlib.Path;
|
|
232
232
|
/** Is the primary thread. */
|
|
@@ -477,26 +477,4 @@ export declare class Server {
|
|
|
477
477
|
* @docs
|
|
478
478
|
*/
|
|
479
479
|
fetch_status(type?: "object" | "string"): Promise<string | Record<string, any>>;
|
|
480
|
-
/**
|
|
481
|
-
* Generate a key and csr for tls.
|
|
482
|
-
* @docs
|
|
483
|
-
*/
|
|
484
|
-
generate_ssl_key({ output_path, ec, }: {
|
|
485
|
-
output_path: string;
|
|
486
|
-
ec?: boolean;
|
|
487
|
-
}): Promise<void>;
|
|
488
|
-
/**
|
|
489
|
-
* Generate a csr for tls.
|
|
490
|
-
* @docs
|
|
491
|
-
*/
|
|
492
|
-
generate_csr({ output_path, key_path, name, domain, organization_unit, country_code, province, city, }: {
|
|
493
|
-
output_path: string;
|
|
494
|
-
key_path: string;
|
|
495
|
-
name: string;
|
|
496
|
-
domain: string;
|
|
497
|
-
organization_unit: string;
|
|
498
|
-
country_code: string;
|
|
499
|
-
province: string;
|
|
500
|
-
city: string;
|
|
501
|
-
}): Promise<void>;
|
|
502
480
|
}
|
|
@@ -77,10 +77,10 @@ class Server {
|
|
|
77
77
|
port;
|
|
78
78
|
/** The binded https port. */
|
|
79
79
|
https_port;
|
|
80
|
-
/** The raw domain. */
|
|
80
|
+
/** The raw domain without http/https . */
|
|
81
81
|
domain;
|
|
82
|
-
/** The
|
|
83
|
-
|
|
82
|
+
/** The https domain, this is used for things like stripe webhooks, metadata, etc. */
|
|
83
|
+
https_domain;
|
|
84
84
|
/** The persistent storage source directory. */
|
|
85
85
|
source;
|
|
86
86
|
/** Is the primary thread. */
|
|
@@ -244,12 +244,9 @@ class Server {
|
|
|
244
244
|
this.source = this.source.abs();
|
|
245
245
|
this.domain = domain.replace("https://", "").replace("http://", "");
|
|
246
246
|
while (this.domain.length > 0 && this.domain.charAt(this.domain.length - 1) === "/") {
|
|
247
|
-
this.domain = this.domain.
|
|
248
|
-
}
|
|
249
|
-
this.full_domain = `http${this.tls ? "s" : ""}://${this.domain}`;
|
|
250
|
-
while (this.full_domain.endsWith("/")) {
|
|
251
|
-
this.full_domain = this.full_domain.slice(0, -1);
|
|
247
|
+
this.domain = this.domain.slice(0, -1);
|
|
252
248
|
}
|
|
249
|
+
this.https_domain = `https://${this.domain}`;
|
|
253
250
|
this.endpoint_cache_dir = new vlib.Path("/tmp/volt_server_endpoint_cache/" + this.hash(this.domain));
|
|
254
251
|
this.statics = statics;
|
|
255
252
|
this.statics_aspect_ratios = /* @__PURE__ */ new Map();
|
|
@@ -261,12 +258,12 @@ class Server {
|
|
|
261
258
|
meta = new import_meta2.Meta(meta);
|
|
262
259
|
}
|
|
263
260
|
if (favicon != null && meta.favicon == null) {
|
|
264
|
-
meta.favicon =
|
|
261
|
+
meta.favicon = "/favicon.ico";
|
|
265
262
|
}
|
|
266
263
|
if (favicon != null && meta.image == null) {
|
|
267
|
-
meta.image = this.
|
|
264
|
+
meta.image = this.https_domain + "/favicon.ico";
|
|
268
265
|
} else if (meta.image != null && !meta.image.startsWith("http")) {
|
|
269
|
-
meta.image = this.
|
|
266
|
+
meta.image = this.https_domain + meta.image;
|
|
270
267
|
}
|
|
271
268
|
this.meta = meta;
|
|
272
269
|
const base_default_headers = {
|
|
@@ -565,17 +562,17 @@ class Server {
|
|
|
565
562
|
continue;
|
|
566
563
|
const ep = encodeURI(endpoint.route.endpoint_str.startsWith("/") ? endpoint.route.endpoint_str : `/${endpoint.route.endpoint_str}`);
|
|
567
564
|
sitemap += `<url>
|
|
568
|
-
<loc>${
|
|
565
|
+
<loc>${ep}</loc>
|
|
569
566
|
</url>
|
|
570
567
|
`;
|
|
571
568
|
}
|
|
572
569
|
}
|
|
573
570
|
this.additional_sitemap_endpoints.forEach((endpoint) => {
|
|
574
|
-
while (endpoint.length >
|
|
575
|
-
endpoint = endpoint.
|
|
571
|
+
while (endpoint.length > 1 && endpoint.charAt(0) === "/") {
|
|
572
|
+
endpoint = endpoint.slice(1);
|
|
576
573
|
}
|
|
577
574
|
sitemap += `<url>
|
|
578
|
-
<loc
|
|
575
|
+
<loc>/${endpoint}</loc>
|
|
579
576
|
</url>
|
|
580
577
|
`;
|
|
581
578
|
});
|
|
@@ -606,7 +603,7 @@ class Server {
|
|
|
606
603
|
`;
|
|
607
604
|
}
|
|
608
605
|
robots += `
|
|
609
|
-
Sitemap:
|
|
606
|
+
Sitemap: /sitemap.xml`;
|
|
610
607
|
this.endpoint({
|
|
611
608
|
method: "GET",
|
|
612
609
|
endpoint: "/robots.txt",
|
|
@@ -1417,10 +1414,7 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
|
|
|
1417
1414
|
}
|
|
1418
1415
|
this.performance.start();
|
|
1419
1416
|
for (const callback of this.events.get("start")) {
|
|
1420
|
-
|
|
1421
|
-
if (res instanceof Promise) {
|
|
1422
|
-
await res;
|
|
1423
|
-
}
|
|
1417
|
+
await callback({ forked });
|
|
1424
1418
|
}
|
|
1425
1419
|
this.performance.end("on-start-callbacks");
|
|
1426
1420
|
console.log(this.performance.dump());
|
|
@@ -1444,10 +1438,7 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
|
|
|
1444
1438
|
async stop() {
|
|
1445
1439
|
this.log(0, "Stopping the server...");
|
|
1446
1440
|
for (const callback of this.events.get("stop")) {
|
|
1447
|
-
|
|
1448
|
-
if (res instanceof Promise) {
|
|
1449
|
-
await res;
|
|
1450
|
-
}
|
|
1441
|
+
await callback();
|
|
1451
1442
|
}
|
|
1452
1443
|
if (this.rate_limit) {
|
|
1453
1444
|
await this.rate_limit.stop();
|
|
@@ -1644,69 +1635,6 @@ Sitemap: ${this.full_domain}/sitemap.xml`;
|
|
|
1644
1635
|
}
|
|
1645
1636
|
return status;
|
|
1646
1637
|
}
|
|
1647
|
-
// ---------------------------------------------------------
|
|
1648
|
-
// TLS.
|
|
1649
|
-
/**
|
|
1650
|
-
* Generate a key and csr for tls.
|
|
1651
|
-
* @docs
|
|
1652
|
-
*/
|
|
1653
|
-
async generate_ssl_key({ output_path, ec = true }) {
|
|
1654
|
-
if (output_path == null) {
|
|
1655
|
-
throw Error('Define parameter "path".');
|
|
1656
|
-
}
|
|
1657
|
-
const key = new vlib.Path(output_path);
|
|
1658
|
-
if (key.exists()) {
|
|
1659
|
-
throw Error(`Key path "${key.str()}" already exists, remove the file manually to continue.`);
|
|
1660
|
-
}
|
|
1661
|
-
const proc = new vlib.Proc();
|
|
1662
|
-
await proc.start({
|
|
1663
|
-
command: "openssl",
|
|
1664
|
-
args: ec ? ["ecparam", "-genkey", "-name", "secp384r1", "-out", key.str()] : ["genpkey", "-algorithm", "RSA", "-pkeyopt", "rsa_keygen_bits:2048", "-out", key.str()],
|
|
1665
|
-
opts: { stdio: "inherit" }
|
|
1666
|
-
});
|
|
1667
|
-
if (proc.exit_status != 0) {
|
|
1668
|
-
throw Error(`Encountered an error while generating the private key [${proc.exit_status}]: ${proc.err}`);
|
|
1669
|
-
}
|
|
1670
|
-
}
|
|
1671
|
-
/**
|
|
1672
|
-
* Generate a csr for tls.
|
|
1673
|
-
* @docs
|
|
1674
|
-
*/
|
|
1675
|
-
async generate_csr({ output_path, key_path, name, domain, organization_unit, country_code, province, city }) {
|
|
1676
|
-
if (key_path == null) {
|
|
1677
|
-
throw Error('Define parameter "key_path".');
|
|
1678
|
-
}
|
|
1679
|
-
if (organization_unit == null) {
|
|
1680
|
-
throw Error('Define parameter "organization_unit".');
|
|
1681
|
-
}
|
|
1682
|
-
const key = new vlib.Path(key_path);
|
|
1683
|
-
if (!key.exists()) {
|
|
1684
|
-
throw Error(`Key path "${key.str()}" does not exist.`);
|
|
1685
|
-
}
|
|
1686
|
-
const csr = new vlib.Path(output_path);
|
|
1687
|
-
if (csr.exists()) {
|
|
1688
|
-
throw Error(`CSR path "${csr.str()}" already exists, remove the file manually to continue.`);
|
|
1689
|
-
}
|
|
1690
|
-
const proc = new vlib.Proc();
|
|
1691
|
-
await proc.start({
|
|
1692
|
-
command: "openssl",
|
|
1693
|
-
args: [
|
|
1694
|
-
"req",
|
|
1695
|
-
"-new",
|
|
1696
|
-
"-key",
|
|
1697
|
-
key.str(),
|
|
1698
|
-
"-out",
|
|
1699
|
-
csr.str(),
|
|
1700
|
-
"-subj",
|
|
1701
|
-
`/C=${country_code}/ST=${province}/L=${city}/O=${name}/OU=${organization_unit}/CN=${domain}`
|
|
1702
|
-
],
|
|
1703
|
-
opts: { stdio: "inherit" }
|
|
1704
|
-
});
|
|
1705
|
-
if (proc.exit_status != 0) {
|
|
1706
|
-
throw Error(`Encountered an error while generating the CSR [${proc.exit_status}]: ${proc.err}`);
|
|
1707
|
-
}
|
|
1708
|
-
this.log(0, `Generated the tls key with CSR for domain "${this.domain}".`);
|
|
1709
|
-
}
|
|
1710
1638
|
}
|
|
1711
1639
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1712
1640
|
0 && (module.exports = {
|
|
@@ -561,11 +561,11 @@ class Users {
|
|
|
561
561
|
let header;
|
|
562
562
|
if (this.server.company.stroke_icon != null) {
|
|
563
563
|
header = [
|
|
564
|
-
Image(`${this.server.
|
|
564
|
+
Image(`${this.server.https_domain}/${this.server.company.stroke_icon ?? ""}`).height(16)
|
|
565
565
|
];
|
|
566
566
|
} else if (this.server.company.icon != null) {
|
|
567
567
|
header = [
|
|
568
|
-
Image(`${this.server.
|
|
568
|
+
Image(`${this.server.https_domain}/${this.server.company.icon ?? ""}`).frame(20, 40)
|
|
569
569
|
];
|
|
570
570
|
}
|
|
571
571
|
if (header) {
|
|
@@ -326,7 +326,7 @@ ${bundle.debug({ limit: 25 })}`);
|
|
|
326
326
|
html += `<!DOCTYPE html><html lang='${this.lang}'>${line_break}`;
|
|
327
327
|
html += `<head>${line_break}`;
|
|
328
328
|
if (this.meta) {
|
|
329
|
-
html += this.meta.build_html(this.server.
|
|
329
|
+
html += this.meta.build_html(this.server.https_domain) + line_break;
|
|
330
330
|
}
|
|
331
331
|
html += `<style nonce="${nonce_identifier}">html { min-width:100%;min-height:100%; }body { width:100vw;height:100vh;margin:0;padding:0;${this.body_style ?? ""} }</style>${line_break}`;
|
|
332
332
|
const embed_stylesheet = (url, embed) => {
|
|
@@ -706,7 +706,7 @@ export class Paddle {
|
|
|
706
706
|
product_ids.push(product.id);
|
|
707
707
|
// Set the icon absolute url.
|
|
708
708
|
if (typeof product.icon === "string" && product.icon.charAt(0) === "/") {
|
|
709
|
-
product.icon = `${this.server.
|
|
709
|
+
product.icon = `${this.server.https_domain}/${product.icon}`;
|
|
710
710
|
}
|
|
711
711
|
// Check attributes.
|
|
712
712
|
if (typeof product.id !== "string" || product.id === "") {
|
|
@@ -1458,7 +1458,7 @@ export class Paddle {
|
|
|
1458
1458
|
// Register the webhook.
|
|
1459
1459
|
const webhook_settings = {
|
|
1460
1460
|
description: "volt webhook",
|
|
1461
|
-
destination: `${this.server.
|
|
1461
|
+
destination: `${this.server.https_domain}/volt/payments/webhook`,
|
|
1462
1462
|
type: "url",
|
|
1463
1463
|
subscribed_events: [
|
|
1464
1464
|
// "transaction.billed",
|
|
@@ -245,21 +245,20 @@ export class Stripe {
|
|
|
245
245
|
// Initialize products.
|
|
246
246
|
this.products = await initialize_products(this.client, this.server, this.raw_products);
|
|
247
247
|
// Ensure the webhook is registered.
|
|
248
|
+
// Also when not running on https since we could be behind a proxy.
|
|
248
249
|
if (!opts.worker) {
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
this.webhook_signing_secret = res.webhook_signing_secret;
|
|
262
|
-
}
|
|
250
|
+
const res = await register_or_update_stripe_webhook_endpoint(this.client, this.server, {
|
|
251
|
+
/**
|
|
252
|
+
* @warning
|
|
253
|
+
* Never change the webhook_id since this could break updating the webhook endpoint
|
|
254
|
+
* if the url / description etc changes.
|
|
255
|
+
*/
|
|
256
|
+
webhook_app_id: "Volt.Stripe.Webhook",
|
|
257
|
+
webhook_url: `${this.server.https_domain}/volt/api/stripe/webhook`,
|
|
258
|
+
description: "The internal volt stripe payments webhook endpoint.",
|
|
259
|
+
ensure_enabled: true,
|
|
260
|
+
});
|
|
261
|
+
this.webhook_signing_secret = res.webhook_signing_secret;
|
|
263
262
|
// Initialize endpoints.
|
|
264
263
|
await this.initialize_endpoints();
|
|
265
264
|
}
|
|
@@ -223,10 +223,10 @@ export declare class Server {
|
|
|
223
223
|
port: number;
|
|
224
224
|
/** The binded https port. */
|
|
225
225
|
https_port: number;
|
|
226
|
-
/** The raw domain. */
|
|
226
|
+
/** The raw domain without http/https . */
|
|
227
227
|
domain: string;
|
|
228
|
-
/** The
|
|
229
|
-
|
|
228
|
+
/** The https domain, this is used for things like stripe webhooks, metadata, etc. */
|
|
229
|
+
https_domain: string;
|
|
230
230
|
/** The persistent storage source directory. */
|
|
231
231
|
source: vlib.Path;
|
|
232
232
|
/** Is the primary thread. */
|
|
@@ -477,26 +477,4 @@ export declare class Server {
|
|
|
477
477
|
* @docs
|
|
478
478
|
*/
|
|
479
479
|
fetch_status(type?: "object" | "string"): Promise<string | Record<string, any>>;
|
|
480
|
-
/**
|
|
481
|
-
* Generate a key and csr for tls.
|
|
482
|
-
* @docs
|
|
483
|
-
*/
|
|
484
|
-
generate_ssl_key({ output_path, ec, }: {
|
|
485
|
-
output_path: string;
|
|
486
|
-
ec?: boolean;
|
|
487
|
-
}): Promise<void>;
|
|
488
|
-
/**
|
|
489
|
-
* Generate a csr for tls.
|
|
490
|
-
* @docs
|
|
491
|
-
*/
|
|
492
|
-
generate_csr({ output_path, key_path, name, domain, organization_unit, country_code, province, city, }: {
|
|
493
|
-
output_path: string;
|
|
494
|
-
key_path: string;
|
|
495
|
-
name: string;
|
|
496
|
-
domain: string;
|
|
497
|
-
organization_unit: string;
|
|
498
|
-
country_code: string;
|
|
499
|
-
province: string;
|
|
500
|
-
city: string;
|
|
501
|
-
}): Promise<void>;
|
|
502
480
|
}
|
|
@@ -59,10 +59,10 @@ export class Server {
|
|
|
59
59
|
port;
|
|
60
60
|
/** The binded https port. */
|
|
61
61
|
https_port;
|
|
62
|
-
/** The raw domain. */
|
|
62
|
+
/** The raw domain without http/https . */
|
|
63
63
|
domain;
|
|
64
|
-
/** The
|
|
65
|
-
|
|
64
|
+
/** The https domain, this is used for things like stripe webhooks, metadata, etc. */
|
|
65
|
+
https_domain;
|
|
66
66
|
/** The persistent storage source directory. */
|
|
67
67
|
source;
|
|
68
68
|
/** Is the primary thread. */
|
|
@@ -329,13 +329,10 @@ export class Server {
|
|
|
329
329
|
// Set domain.
|
|
330
330
|
this.domain = domain.replace("https://", "").replace("http://", "");
|
|
331
331
|
while (this.domain.length > 0 && this.domain.charAt(this.domain.length - 1) === "/") {
|
|
332
|
-
this.domain = this.domain.
|
|
333
|
-
}
|
|
334
|
-
// Set full domain.
|
|
335
|
-
this.full_domain = `http${this.tls ? "s" : ""}://${this.domain}`;
|
|
336
|
-
while (this.full_domain.endsWith("/")) {
|
|
337
|
-
this.full_domain = this.full_domain.slice(0, -1);
|
|
332
|
+
this.domain = this.domain.slice(0, -1);
|
|
338
333
|
}
|
|
334
|
+
// Set https domain.
|
|
335
|
+
this.https_domain = `https://${this.domain}`;
|
|
339
336
|
// Set endpoint cache.
|
|
340
337
|
this.endpoint_cache_dir = new vlib.Path("/tmp/volt_server_endpoint_cache/" + this.hash(this.domain));
|
|
341
338
|
// Set statics.
|
|
@@ -351,13 +348,13 @@ export class Server {
|
|
|
351
348
|
meta = new Meta(meta);
|
|
352
349
|
}
|
|
353
350
|
if (favicon != null && meta.favicon == null) {
|
|
354
|
-
meta.favicon =
|
|
351
|
+
meta.favicon = "/favicon.ico";
|
|
355
352
|
}
|
|
356
353
|
if (favicon != null && meta.image == null) {
|
|
357
|
-
meta.image = this.
|
|
354
|
+
meta.image = this.https_domain + "/favicon.ico";
|
|
358
355
|
}
|
|
359
356
|
else if (meta.image != null && !meta.image.startsWith("http")) {
|
|
360
|
-
meta.image = this.
|
|
357
|
+
meta.image = this.https_domain + meta.image;
|
|
361
358
|
}
|
|
362
359
|
this.meta = meta;
|
|
363
360
|
// Default headers.
|
|
@@ -685,14 +682,14 @@ export class Server {
|
|
|
685
682
|
const ep = encodeURI(endpoint.route.endpoint_str.startsWith("/")
|
|
686
683
|
? endpoint.route.endpoint_str
|
|
687
684
|
: `/${endpoint.route.endpoint_str}`);
|
|
688
|
-
sitemap += `<url>\n <loc>${
|
|
685
|
+
sitemap += `<url>\n <loc>${ep}</loc>\n</url>\n`;
|
|
689
686
|
}
|
|
690
687
|
}
|
|
691
688
|
this.additional_sitemap_endpoints.forEach((endpoint) => {
|
|
692
|
-
while (endpoint.length >
|
|
693
|
-
endpoint = endpoint.
|
|
689
|
+
while (endpoint.length > 1 && endpoint.charAt(0) === "/") {
|
|
690
|
+
endpoint = endpoint.slice(1);
|
|
694
691
|
}
|
|
695
|
-
sitemap += `<url>\n <loc
|
|
692
|
+
sitemap += `<url>\n <loc>/${endpoint}</loc>\n</url>\n`;
|
|
696
693
|
});
|
|
697
694
|
sitemap += "</urlset>\n";
|
|
698
695
|
this.endpoint({
|
|
@@ -720,7 +717,7 @@ export class Server {
|
|
|
720
717
|
if (disallowed === 0) {
|
|
721
718
|
robots += `Disallow: \n`;
|
|
722
719
|
}
|
|
723
|
-
robots += `\nSitemap:
|
|
720
|
+
robots += `\nSitemap: /sitemap.xml`;
|
|
724
721
|
this.endpoint({
|
|
725
722
|
method: "GET",
|
|
726
723
|
endpoint: "/robots.txt",
|
|
@@ -1711,10 +1708,7 @@ export class Server {
|
|
|
1711
1708
|
// On start callbacks.
|
|
1712
1709
|
this.performance.start();
|
|
1713
1710
|
for (const callback of this.events.get("start")) {
|
|
1714
|
-
|
|
1715
|
-
if (res instanceof Promise) {
|
|
1716
|
-
await res;
|
|
1717
|
-
}
|
|
1711
|
+
await callback({ forked });
|
|
1718
1712
|
}
|
|
1719
1713
|
/* @performance */ this.performance.end("on-start-callbacks");
|
|
1720
1714
|
// Start browser preview on primary node.
|
|
@@ -1747,10 +1741,7 @@ export class Server {
|
|
|
1747
1741
|
this.log(0, "Stopping the server...");
|
|
1748
1742
|
// On stop callbacks.
|
|
1749
1743
|
for (const callback of this.events.get("stop")) {
|
|
1750
|
-
|
|
1751
|
-
if (res instanceof Promise) {
|
|
1752
|
-
await res;
|
|
1753
|
-
}
|
|
1744
|
+
await callback();
|
|
1754
1745
|
}
|
|
1755
1746
|
// Stop rate limit.
|
|
1756
1747
|
if (this.rate_limit) {
|
|
@@ -1966,70 +1957,4 @@ export class Server {
|
|
|
1966
1957
|
// Response.
|
|
1967
1958
|
return status;
|
|
1968
1959
|
}
|
|
1969
|
-
// ---------------------------------------------------------
|
|
1970
|
-
// TLS.
|
|
1971
|
-
/**
|
|
1972
|
-
* Generate a key and csr for tls.
|
|
1973
|
-
* @docs
|
|
1974
|
-
*/
|
|
1975
|
-
async generate_ssl_key({ output_path, ec = true, }) {
|
|
1976
|
-
// Args.
|
|
1977
|
-
if (output_path == null) {
|
|
1978
|
-
throw Error("Define parameter \"path\".");
|
|
1979
|
-
}
|
|
1980
|
-
// Paths.
|
|
1981
|
-
const key = new vlib.Path(output_path);
|
|
1982
|
-
if (key.exists()) {
|
|
1983
|
-
throw Error(`Key path "${key.str()}" already exists, remove the file manually to continue.`);
|
|
1984
|
-
}
|
|
1985
|
-
// Generate the private key using the EC parameters file
|
|
1986
|
-
const proc = new vlib.Proc();
|
|
1987
|
-
await proc.start({
|
|
1988
|
-
command: "openssl",
|
|
1989
|
-
args: ec
|
|
1990
|
-
? ["ecparam", "-genkey", "-name", "secp384r1", "-out", key.str()]
|
|
1991
|
-
: ["genpkey", "-algorithm", "RSA", "-pkeyopt", "rsa_keygen_bits:2048", "-out", key.str()],
|
|
1992
|
-
opts: { stdio: "inherit" },
|
|
1993
|
-
});
|
|
1994
|
-
if (proc.exit_status != 0) {
|
|
1995
|
-
throw Error(`Encountered an error while generating the private key [${proc.exit_status}]: ${proc.err}`);
|
|
1996
|
-
}
|
|
1997
|
-
}
|
|
1998
|
-
/**
|
|
1999
|
-
* Generate a csr for tls.
|
|
2000
|
-
* @docs
|
|
2001
|
-
*/
|
|
2002
|
-
async generate_csr({ output_path, key_path, name, domain, organization_unit, country_code, province, city, }) {
|
|
2003
|
-
// Args.
|
|
2004
|
-
if (key_path == null) {
|
|
2005
|
-
throw Error("Define parameter \"key_path\".");
|
|
2006
|
-
}
|
|
2007
|
-
if (organization_unit == null) {
|
|
2008
|
-
throw Error("Define parameter \"organization_unit\".");
|
|
2009
|
-
}
|
|
2010
|
-
// Paths.
|
|
2011
|
-
const key = new vlib.Path(key_path);
|
|
2012
|
-
if (!key.exists()) {
|
|
2013
|
-
throw Error(`Key path "${key.str()}" does not exist.`);
|
|
2014
|
-
}
|
|
2015
|
-
const csr = new vlib.Path(output_path);
|
|
2016
|
-
if (csr.exists()) {
|
|
2017
|
-
throw Error(`CSR path "${csr.str()}" already exists, remove the file manually to continue.`);
|
|
2018
|
-
}
|
|
2019
|
-
// Generate the CSR using the generated private key
|
|
2020
|
-
const proc = new vlib.Proc();
|
|
2021
|
-
await proc.start({
|
|
2022
|
-
command: "openssl",
|
|
2023
|
-
args: [
|
|
2024
|
-
"req", "-new", "-key", key.str(), "-out", csr.str(),
|
|
2025
|
-
"-subj",
|
|
2026
|
-
`/C=${country_code}/ST=${province}/L=${city}/O=${name}/OU=${organization_unit}/CN=${domain}`
|
|
2027
|
-
],
|
|
2028
|
-
opts: { stdio: "inherit" },
|
|
2029
|
-
});
|
|
2030
|
-
if (proc.exit_status != 0) {
|
|
2031
|
-
throw Error(`Encountered an error while generating the CSR [${proc.exit_status}]: ${proc.err}`);
|
|
2032
|
-
}
|
|
2033
|
-
this.log(0, `Generated the tls key with CSR for domain "${this.domain}".`);
|
|
2034
|
-
}
|
|
2035
1960
|
}
|
|
@@ -567,12 +567,12 @@ export class Users {
|
|
|
567
567
|
let header;
|
|
568
568
|
if (this.server.company.stroke_icon != null) {
|
|
569
569
|
header = [
|
|
570
|
-
Image(`${this.server.
|
|
570
|
+
Image(`${this.server.https_domain}/${this.server.company.stroke_icon ?? ""}`).height(16),
|
|
571
571
|
];
|
|
572
572
|
}
|
|
573
573
|
else if (this.server.company.icon != null) {
|
|
574
574
|
header = [
|
|
575
|
-
Image(`${this.server.
|
|
575
|
+
Image(`${this.server.https_domain}/${this.server.company.icon ?? ""}`).frame(20, 40),
|
|
576
576
|
];
|
|
577
577
|
}
|
|
578
578
|
if (header) {
|
|
@@ -320,7 +320,7 @@ export class View {
|
|
|
320
320
|
html += `<head>${line_break}`;
|
|
321
321
|
// Meta.
|
|
322
322
|
if (this.meta) {
|
|
323
|
-
html += this.meta.build_html(this.server.
|
|
323
|
+
html += this.meta.build_html(this.server.https_domain) + line_break;
|
|
324
324
|
}
|
|
325
325
|
// this.html = "Hello World!";
|
|
326
326
|
// return;
|
|
@@ -706,7 +706,7 @@ export class Paddle {
|
|
|
706
706
|
product_ids.push(product.id);
|
|
707
707
|
// Set the icon absolute url.
|
|
708
708
|
if (typeof product.icon === "string" && product.icon.charAt(0) === "/") {
|
|
709
|
-
product.icon = `${this.server.
|
|
709
|
+
product.icon = `${this.server.https_domain}/${product.icon}`;
|
|
710
710
|
}
|
|
711
711
|
// Check attributes.
|
|
712
712
|
if (typeof product.id !== "string" || product.id === "") {
|
|
@@ -1458,7 +1458,7 @@ export class Paddle {
|
|
|
1458
1458
|
// Register the webhook.
|
|
1459
1459
|
const webhook_settings = {
|
|
1460
1460
|
description: "volt webhook",
|
|
1461
|
-
destination: `${this.server.
|
|
1461
|
+
destination: `${this.server.https_domain}/volt/payments/webhook`,
|
|
1462
1462
|
type: "url",
|
|
1463
1463
|
subscribed_events: [
|
|
1464
1464
|
// "transaction.billed",
|
|
@@ -245,21 +245,20 @@ export class Stripe {
|
|
|
245
245
|
// Initialize products.
|
|
246
246
|
this.products = await initialize_products(this.client, this.server, this.raw_products);
|
|
247
247
|
// Ensure the webhook is registered.
|
|
248
|
+
// Also when not running on https since we could be behind a proxy.
|
|
248
249
|
if (!opts.worker) {
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
this.webhook_signing_secret = res.webhook_signing_secret;
|
|
262
|
-
}
|
|
250
|
+
const res = await register_or_update_stripe_webhook_endpoint(this.client, this.server, {
|
|
251
|
+
/**
|
|
252
|
+
* @warning
|
|
253
|
+
* Never change the webhook_id since this could break updating the webhook endpoint
|
|
254
|
+
* if the url / description etc changes.
|
|
255
|
+
*/
|
|
256
|
+
webhook_app_id: "Volt.Stripe.Webhook",
|
|
257
|
+
webhook_url: `${this.server.https_domain}/volt/api/stripe/webhook`,
|
|
258
|
+
description: "The internal volt stripe payments webhook endpoint.",
|
|
259
|
+
ensure_enabled: true,
|
|
260
|
+
});
|
|
261
|
+
this.webhook_signing_secret = res.webhook_signing_secret;
|
|
263
262
|
// Initialize endpoints.
|
|
264
263
|
await this.initialize_endpoints();
|
|
265
264
|
}
|
|
@@ -223,10 +223,10 @@ export declare class Server {
|
|
|
223
223
|
port: number;
|
|
224
224
|
/** The binded https port. */
|
|
225
225
|
https_port: number;
|
|
226
|
-
/** The raw domain. */
|
|
226
|
+
/** The raw domain without http/https . */
|
|
227
227
|
domain: string;
|
|
228
|
-
/** The
|
|
229
|
-
|
|
228
|
+
/** The https domain, this is used for things like stripe webhooks, metadata, etc. */
|
|
229
|
+
https_domain: string;
|
|
230
230
|
/** The persistent storage source directory. */
|
|
231
231
|
source: vlib.Path;
|
|
232
232
|
/** Is the primary thread. */
|
|
@@ -477,26 +477,4 @@ export declare class Server {
|
|
|
477
477
|
* @docs
|
|
478
478
|
*/
|
|
479
479
|
fetch_status(type?: "object" | "string"): Promise<string | Record<string, any>>;
|
|
480
|
-
/**
|
|
481
|
-
* Generate a key and csr for tls.
|
|
482
|
-
* @docs
|
|
483
|
-
*/
|
|
484
|
-
generate_ssl_key({ output_path, ec, }: {
|
|
485
|
-
output_path: string;
|
|
486
|
-
ec?: boolean;
|
|
487
|
-
}): Promise<void>;
|
|
488
|
-
/**
|
|
489
|
-
* Generate a csr for tls.
|
|
490
|
-
* @docs
|
|
491
|
-
*/
|
|
492
|
-
generate_csr({ output_path, key_path, name, domain, organization_unit, country_code, province, city, }: {
|
|
493
|
-
output_path: string;
|
|
494
|
-
key_path: string;
|
|
495
|
-
name: string;
|
|
496
|
-
domain: string;
|
|
497
|
-
organization_unit: string;
|
|
498
|
-
country_code: string;
|
|
499
|
-
province: string;
|
|
500
|
-
city: string;
|
|
501
|
-
}): Promise<void>;
|
|
502
480
|
}
|
|
@@ -59,10 +59,10 @@ export class Server {
|
|
|
59
59
|
port;
|
|
60
60
|
/** The binded https port. */
|
|
61
61
|
https_port;
|
|
62
|
-
/** The raw domain. */
|
|
62
|
+
/** The raw domain without http/https . */
|
|
63
63
|
domain;
|
|
64
|
-
/** The
|
|
65
|
-
|
|
64
|
+
/** The https domain, this is used for things like stripe webhooks, metadata, etc. */
|
|
65
|
+
https_domain;
|
|
66
66
|
/** The persistent storage source directory. */
|
|
67
67
|
source;
|
|
68
68
|
/** Is the primary thread. */
|
|
@@ -329,13 +329,10 @@ export class Server {
|
|
|
329
329
|
// Set domain.
|
|
330
330
|
this.domain = domain.replace("https://", "").replace("http://", "");
|
|
331
331
|
while (this.domain.length > 0 && this.domain.charAt(this.domain.length - 1) === "/") {
|
|
332
|
-
this.domain = this.domain.
|
|
333
|
-
}
|
|
334
|
-
// Set full domain.
|
|
335
|
-
this.full_domain = `http${this.tls ? "s" : ""}://${this.domain}`;
|
|
336
|
-
while (this.full_domain.endsWith("/")) {
|
|
337
|
-
this.full_domain = this.full_domain.slice(0, -1);
|
|
332
|
+
this.domain = this.domain.slice(0, -1);
|
|
338
333
|
}
|
|
334
|
+
// Set https domain.
|
|
335
|
+
this.https_domain = `https://${this.domain}`;
|
|
339
336
|
// Set endpoint cache.
|
|
340
337
|
this.endpoint_cache_dir = new vlib.Path("/tmp/volt_server_endpoint_cache/" + this.hash(this.domain));
|
|
341
338
|
// Set statics.
|
|
@@ -351,13 +348,13 @@ export class Server {
|
|
|
351
348
|
meta = new Meta(meta);
|
|
352
349
|
}
|
|
353
350
|
if (favicon != null && meta.favicon == null) {
|
|
354
|
-
meta.favicon =
|
|
351
|
+
meta.favicon = "/favicon.ico";
|
|
355
352
|
}
|
|
356
353
|
if (favicon != null && meta.image == null) {
|
|
357
|
-
meta.image = this.
|
|
354
|
+
meta.image = this.https_domain + "/favicon.ico";
|
|
358
355
|
}
|
|
359
356
|
else if (meta.image != null && !meta.image.startsWith("http")) {
|
|
360
|
-
meta.image = this.
|
|
357
|
+
meta.image = this.https_domain + meta.image;
|
|
361
358
|
}
|
|
362
359
|
this.meta = meta;
|
|
363
360
|
// Default headers.
|
|
@@ -685,14 +682,14 @@ export class Server {
|
|
|
685
682
|
const ep = encodeURI(endpoint.route.endpoint_str.startsWith("/")
|
|
686
683
|
? endpoint.route.endpoint_str
|
|
687
684
|
: `/${endpoint.route.endpoint_str}`);
|
|
688
|
-
sitemap += `<url>\n <loc>${
|
|
685
|
+
sitemap += `<url>\n <loc>${ep}</loc>\n</url>\n`;
|
|
689
686
|
}
|
|
690
687
|
}
|
|
691
688
|
this.additional_sitemap_endpoints.forEach((endpoint) => {
|
|
692
|
-
while (endpoint.length >
|
|
693
|
-
endpoint = endpoint.
|
|
689
|
+
while (endpoint.length > 1 && endpoint.charAt(0) === "/") {
|
|
690
|
+
endpoint = endpoint.slice(1);
|
|
694
691
|
}
|
|
695
|
-
sitemap += `<url>\n <loc
|
|
692
|
+
sitemap += `<url>\n <loc>/${endpoint}</loc>\n</url>\n`;
|
|
696
693
|
});
|
|
697
694
|
sitemap += "</urlset>\n";
|
|
698
695
|
this.endpoint({
|
|
@@ -720,7 +717,7 @@ export class Server {
|
|
|
720
717
|
if (disallowed === 0) {
|
|
721
718
|
robots += `Disallow: \n`;
|
|
722
719
|
}
|
|
723
|
-
robots += `\nSitemap:
|
|
720
|
+
robots += `\nSitemap: /sitemap.xml`;
|
|
724
721
|
this.endpoint({
|
|
725
722
|
method: "GET",
|
|
726
723
|
endpoint: "/robots.txt",
|
|
@@ -1711,10 +1708,7 @@ export class Server {
|
|
|
1711
1708
|
// On start callbacks.
|
|
1712
1709
|
this.performance.start();
|
|
1713
1710
|
for (const callback of this.events.get("start")) {
|
|
1714
|
-
|
|
1715
|
-
if (res instanceof Promise) {
|
|
1716
|
-
await res;
|
|
1717
|
-
}
|
|
1711
|
+
await callback({ forked });
|
|
1718
1712
|
}
|
|
1719
1713
|
/* @performance */ this.performance.end("on-start-callbacks");
|
|
1720
1714
|
// Start browser preview on primary node.
|
|
@@ -1747,10 +1741,7 @@ export class Server {
|
|
|
1747
1741
|
this.log(0, "Stopping the server...");
|
|
1748
1742
|
// On stop callbacks.
|
|
1749
1743
|
for (const callback of this.events.get("stop")) {
|
|
1750
|
-
|
|
1751
|
-
if (res instanceof Promise) {
|
|
1752
|
-
await res;
|
|
1753
|
-
}
|
|
1744
|
+
await callback();
|
|
1754
1745
|
}
|
|
1755
1746
|
// Stop rate limit.
|
|
1756
1747
|
if (this.rate_limit) {
|
|
@@ -1966,70 +1957,4 @@ export class Server {
|
|
|
1966
1957
|
// Response.
|
|
1967
1958
|
return status;
|
|
1968
1959
|
}
|
|
1969
|
-
// ---------------------------------------------------------
|
|
1970
|
-
// TLS.
|
|
1971
|
-
/**
|
|
1972
|
-
* Generate a key and csr for tls.
|
|
1973
|
-
* @docs
|
|
1974
|
-
*/
|
|
1975
|
-
async generate_ssl_key({ output_path, ec = true, }) {
|
|
1976
|
-
// Args.
|
|
1977
|
-
if (output_path == null) {
|
|
1978
|
-
throw Error("Define parameter \"path\".");
|
|
1979
|
-
}
|
|
1980
|
-
// Paths.
|
|
1981
|
-
const key = new vlib.Path(output_path);
|
|
1982
|
-
if (key.exists()) {
|
|
1983
|
-
throw Error(`Key path "${key.str()}" already exists, remove the file manually to continue.`);
|
|
1984
|
-
}
|
|
1985
|
-
// Generate the private key using the EC parameters file
|
|
1986
|
-
const proc = new vlib.Proc();
|
|
1987
|
-
await proc.start({
|
|
1988
|
-
command: "openssl",
|
|
1989
|
-
args: ec
|
|
1990
|
-
? ["ecparam", "-genkey", "-name", "secp384r1", "-out", key.str()]
|
|
1991
|
-
: ["genpkey", "-algorithm", "RSA", "-pkeyopt", "rsa_keygen_bits:2048", "-out", key.str()],
|
|
1992
|
-
opts: { stdio: "inherit" },
|
|
1993
|
-
});
|
|
1994
|
-
if (proc.exit_status != 0) {
|
|
1995
|
-
throw Error(`Encountered an error while generating the private key [${proc.exit_status}]: ${proc.err}`);
|
|
1996
|
-
}
|
|
1997
|
-
}
|
|
1998
|
-
/**
|
|
1999
|
-
* Generate a csr for tls.
|
|
2000
|
-
* @docs
|
|
2001
|
-
*/
|
|
2002
|
-
async generate_csr({ output_path, key_path, name, domain, organization_unit, country_code, province, city, }) {
|
|
2003
|
-
// Args.
|
|
2004
|
-
if (key_path == null) {
|
|
2005
|
-
throw Error("Define parameter \"key_path\".");
|
|
2006
|
-
}
|
|
2007
|
-
if (organization_unit == null) {
|
|
2008
|
-
throw Error("Define parameter \"organization_unit\".");
|
|
2009
|
-
}
|
|
2010
|
-
// Paths.
|
|
2011
|
-
const key = new vlib.Path(key_path);
|
|
2012
|
-
if (!key.exists()) {
|
|
2013
|
-
throw Error(`Key path "${key.str()}" does not exist.`);
|
|
2014
|
-
}
|
|
2015
|
-
const csr = new vlib.Path(output_path);
|
|
2016
|
-
if (csr.exists()) {
|
|
2017
|
-
throw Error(`CSR path "${csr.str()}" already exists, remove the file manually to continue.`);
|
|
2018
|
-
}
|
|
2019
|
-
// Generate the CSR using the generated private key
|
|
2020
|
-
const proc = new vlib.Proc();
|
|
2021
|
-
await proc.start({
|
|
2022
|
-
command: "openssl",
|
|
2023
|
-
args: [
|
|
2024
|
-
"req", "-new", "-key", key.str(), "-out", csr.str(),
|
|
2025
|
-
"-subj",
|
|
2026
|
-
`/C=${country_code}/ST=${province}/L=${city}/O=${name}/OU=${organization_unit}/CN=${domain}`
|
|
2027
|
-
],
|
|
2028
|
-
opts: { stdio: "inherit" },
|
|
2029
|
-
});
|
|
2030
|
-
if (proc.exit_status != 0) {
|
|
2031
|
-
throw Error(`Encountered an error while generating the CSR [${proc.exit_status}]: ${proc.err}`);
|
|
2032
|
-
}
|
|
2033
|
-
this.log(0, `Generated the tls key with CSR for domain "${this.domain}".`);
|
|
2034
|
-
}
|
|
2035
1960
|
}
|
|
@@ -567,12 +567,12 @@ export class Users {
|
|
|
567
567
|
let header;
|
|
568
568
|
if (this.server.company.stroke_icon != null) {
|
|
569
569
|
header = [
|
|
570
|
-
Image(`${this.server.
|
|
570
|
+
Image(`${this.server.https_domain}/${this.server.company.stroke_icon ?? ""}`).height(16),
|
|
571
571
|
];
|
|
572
572
|
}
|
|
573
573
|
else if (this.server.company.icon != null) {
|
|
574
574
|
header = [
|
|
575
|
-
Image(`${this.server.
|
|
575
|
+
Image(`${this.server.https_domain}/${this.server.company.icon ?? ""}`).frame(20, 40),
|
|
576
576
|
];
|
|
577
577
|
}
|
|
578
578
|
if (header) {
|
|
@@ -320,7 +320,7 @@ export class View {
|
|
|
320
320
|
html += `<head>${line_break}`;
|
|
321
321
|
// Meta.
|
|
322
322
|
if (this.meta) {
|
|
323
|
-
html += this.meta.build_html(this.server.
|
|
323
|
+
html += this.meta.build_html(this.server.https_domain) + line_break;
|
|
324
324
|
}
|
|
325
325
|
// this.html = "Hello World!";
|
|
326
326
|
// return;
|