@semics-tech/emdash-events-suite 1.0.0-rc.3 → 1.0.0-rc.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@semics-tech/emdash-events-suite",
3
- "version": "1.0.0-rc.3",
3
+ "version": "1.0.0-rc.4",
4
4
  "type": "module",
5
5
  "description": "Links semics Events and E-sign on one EmDash site: one config call and a booking flow with inline waiver signing",
6
6
  "license": "MIT",
@@ -22,8 +22,8 @@
22
22
  "src/astro"
23
23
  ],
24
24
  "dependencies": {
25
- "@semics-tech/emdash-events": "1.0.0-rc.3",
26
- "@semics-tech/emdash-esign": "1.0.0-rc.3"
25
+ "@semics-tech/emdash-esign": "1.0.0-rc.4",
26
+ "@semics-tech/emdash-events": "1.0.0-rc.4"
27
27
  },
28
28
  "peerDependencies": {
29
29
  "emdash": ">=1.2.0 <2"
@@ -10,7 +10,7 @@ import SigningCeremony from "@semics-tech/emdash-esign/astro/SigningCeremony.ast
10
10
  import { ceremonyCsp } from "@semics-tech/emdash-esign/astro/lib/csp";
11
11
  import { crossSiteResponse } from "@semics-tech/emdash-events/astro/lib/checkout-form";
12
12
 
13
- import { handleWaiverRequest } from "./lib/flow";
13
+ import { handleWaiverRequest, leavesSite } from "./lib/flow";
14
14
  import { WAIVER_MESSAGES, WAIVER_PATH } from "./lib/form";
15
15
  import { waiverSlot } from "./lib/slot";
16
16
 
@@ -23,7 +23,9 @@ const outcome = await handleWaiverRequest(
23
23
  if (outcome.type === "forbidden") return crossSiteResponse();
24
24
  const cookies = outcome.type === "redirect" || outcome.type === "render" ? outcome.cookies : [];
25
25
  for (const cookie of cookies) Astro.cookies.set(cookie.name, cookie.value, cookie.options);
26
- if (outcome.type === "redirect") return Astro.redirect(outcome.location, 303);
26
+ if (outcome.type === "redirect" && !leavesSite(outcome.location, Astro.url)) return Astro.redirect(outcome.location, 303);
27
+ // The payment page is another site, which the CSP below stops a post redirecting to (T155): a page goes there instead.
28
+ const payment = outcome.type === "redirect" ? outcome.location : undefined;
27
29
 
28
30
  Astro.response.headers.set("Referrer-Policy", "no-referrer");
29
31
  Astro.response.headers.set("Cache-Control", "private, no-store");
@@ -54,9 +56,16 @@ const signer = render?.view.kind === "ready" ? render.view.session.signer : unde
54
56
  <meta name="viewport" content="width=device-width, initial-scale=1" />
55
57
  <meta name="robots" content="noindex" />
56
58
  <meta name="referrer" content="no-referrer" />
57
- <title>Sign the waiver</title>
59
+ <title>{payment ? "Continue to payment" : "Sign the waiver"}</title>
60
+ {payment && <meta http-equiv="refresh" content={`0;url=${payment}`} data-testid="waiver-pay-refresh" />}
58
61
  </head>
59
62
  <body>
63
+ {payment ? (
64
+ <main class="semics-esign semics-sign" data-testid="waiver-page" data-step="pay">
65
+ <h1>Continue to payment</h1>
66
+ <p><a href={payment} data-testid="waiver-pay-link">Go to the payment page</a></p>
67
+ </main>
68
+ ) : (
60
69
  <main class="semics-esign semics-sign" data-testid="waiver-page" data-step={render ? "sign" : "error"}>
61
70
  <h1>Sign the waiver</h1>
62
71
  {error && <p role="alert" data-testid="waiver-error">{error}</p>}
@@ -89,5 +98,6 @@ const signer = render?.view.kind === "ready" ? render.view.session.signer : unde
89
98
  )}
90
99
  {ref && <p><a href={`/booking?ref=${ref}`}>Back to your booking</a></p>}
91
100
  </main>
101
+ )}
92
102
  </body>
93
103
  </html>
@@ -100,6 +100,14 @@ export interface BookingAnswer {
100
100
  waiver?: { refs: string[]; voids?: Record<string, string> };
101
101
  }
102
102
 
103
+ /**
104
+ * Whether a redirect leaves this site (T155). A form on the signing page cannot be redirected there:
105
+ * its CSP's `form-action 'self'` also covers where the post redirects, so the browser stops on the page.
106
+ */
107
+ export function leavesSite(location: string, site: URL): boolean {
108
+ return new URL(location, site).origin !== site.origin;
109
+ }
110
+
103
111
  /** Booking statuses with nothing left to sign for: the places are gone (T151). */
104
112
  const ENDED = ["expired", "cancelled", "declined", "refunded", "refunded_unavailable"];
105
113