Skip to content

Commit 6cdcfd7

Browse files
committed
Created urgent contact form
1 parent b3a0340 commit 6cdcfd7

File tree

4 files changed

+102
-6
lines changed

4 files changed

+102
-6
lines changed

contact-urgent.md

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
---
2+
layout: default
3+
title: Urgent Contact
4+
---
5+
6+
If you have an access token then you can send me an urgent message using this form:
7+
8+
<form id="contact-form" method="post" action="/api/contact-urgent">
9+
<fieldset style="display:none">
10+
<label for="name">Leave blank if you're human:</label>
11+
<input type="text" name="name" id="name" placeholder="Leave blank if you're human">
12+
</fieldset>
13+
<fieldset style="margin-bottom:1em">
14+
<label for="email" style="display:inline-block; margin-bottom:0.5em">Email address:</label>
15+
<input type="email" name="email" id="email" placeholder="Email address" style="box-sizing:border-box; width:100%; max-width:20em" required>
16+
</fieldset>
17+
<fieldset style="margin-bottom:0.5em">
18+
<label for="message">Message:</label>
19+
</fieldset>
20+
<fieldset style="margin-bottom:1em">
21+
<textarea name="message" id="message" placeholder="Message" style="box-sizing:border-box; width:100%; max-width:60em; height:15em" required></textarea>
22+
</fieldset>
23+
<fieldset style="margin-bottom:1em">
24+
<label for="token" style="display:inline-block; margin-bottom:0.5em">Token:</label>
25+
<input type="text" name="token" id="token" placeholder="token" style="box-sizing:border-box; width:100%; max-width:20em" required>
26+
</fieldset>
27+
<button type="submit" style="margin-bottom:1em">Send</button>
28+
</form>
29+
30+
<script>
31+
document.getElementById("contact-form").addEventListener("submit", event => {
32+
event.preventDefault();
33+
const formData = new FormData(event.target);
34+
const token = formData.get("token");
35+
fetch("/api/token-verify", {
36+
method: "POST",
37+
headers: {
38+
"accept": "application/json",
39+
"content-type": "application/json"
40+
},
41+
body: JSON.stringify({ token })
42+
})
43+
.then(res => res.json())
44+
.then(res => {
45+
const element = document.getElementById("token-verify-output");
46+
if (!res.ok) {
47+
alert(`Token ${token} does not appear to be valid.`)
48+
} else {
49+
fetch("/api/contact-urgent", {
50+
method: "POST",
51+
headers: {
52+
"accept": "application/json",
53+
"content-type": "application/json",
54+
},
55+
body: JSON.stringify(Object.fromEntries(formData.entries()))
56+
})
57+
.then(res => res.json())
58+
.then(res => {
59+
alert("Your message has been sent successfully.");
60+
event.target.reset();
61+
})
62+
}
63+
});
64+
});
65+
</script>

functions-src/forms.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@ async function handleForm({
88
formId,
99
honeypotField,
1010
}) {
11+
const headers = Object.fromEntries(context.request.headers.entries());
12+
const usingJson = (headers.content-type === "application/json");
1113
const submissionId = ulid();
1214
const submittedTs = new Date().toISOString();
13-
const fields = Object.fromEntries((await context.request.formData()).entries());
15+
const fields = usingJson ?
16+
await context.request.json() :
17+
Object.fromEntries((await context.request.formData()).entries());
1418
const replyEmail = fields.email;
1519
const spamReasons = [];
1620
const cf = context.request.cf;
17-
const headers = Object.fromEntries(context.request.headers.entries());
1821

1922
if (typeof honeypotField === "string") {
2023
if (fields[honeypotField] !== "") {

functions/api/contact-urgent.js

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { handleForm } from "../../functions-src/forms.js"
2+
import { verifySecureToken } from "../../functions-src/secure-token.js"
3+
4+
export async function onRequest(context) {
5+
if (context.request.method !== "POST") {
6+
return new Response("Invalid request method", { status: 405 });
7+
}
8+
9+
const headers = Object.fromEntries(context.request.headers.entries());
10+
const url = new URL(context.request.url)
11+
const usingJson = (headers.content-type === "application/json");
12+
13+
// TODO: verify token
14+
15+
const success = await handleForm({
16+
context,
17+
formId: "URGENT-CONTACT",
18+
honeypotField: "name",
19+
});
20+
21+
if (!success && !usingJson) {
22+
return new Response("Oops! Something went wrong. Please try submitting the form again.", { status: 500 });
23+
}
24+
25+
return usingJson ?
26+
Response. Response.json({ success }) :
27+
Response.redirect(`https://${url.hostname}/contact-success`, 303);
28+
}

secure/token-generator.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ Use this form to generate a token for the urgent contact form.
3939
fetch('/secure/api/token-generate', {
4040
method: 'POST',
4141
headers: {
42-
'Accept': 'application/json',
43-
'Content-Type': 'application/json'
42+
'accept': 'application/json',
43+
'content-type': 'application/json'
4444
},
4545
body: JSON.stringify({ name, expiry })
4646
})
@@ -55,8 +55,8 @@ Use this form to generate a token for the urgent contact form.
5555
fetch('/api/token-verify', {
5656
method: 'POST',
5757
headers: {
58-
'Accept': 'application/json',
59-
'Content-Type': 'application/json'
58+
'accept': 'application/json',
59+
'content-type': 'application/json'
6060
},
6161
body: JSON.stringify({ token })
6262
})

0 commit comments

Comments
 (0)