-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Return form submissions * Added form submission page * Add table CSS * Various tweaks * Add single submission view
- Loading branch information
1 parent
ae77e36
commit 7adb2b4
Showing
9 changed files
with
258 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
functions/api/contact-urgent.js → functions/api/form/contact-urgent.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
export async function onRequest(context) { | ||
if (context.request.method !== "GET") { | ||
return new Response("Invalid request method", { status: 405 }); | ||
} | ||
|
||
const submissionsQuery = await context.env.DB_FORMS.prepare("SELECT submission_id, form_id, submitted_ts, spam_reasons, json_extract(headers, '$.cf-connecting-ip') as ip, json_extract(cf, '$.asn') as asn, json_extract(cf, '$.country') as country FROM submissions WHERE submitted_ts > ? ORDER BY submitted_ts DESC") | ||
.bind( | ||
new Date().subtractDays(30).toISOString(), | ||
) | ||
.all(); | ||
const rows = submissionsQuery | ||
.results | ||
.map((row) => { | ||
row.spam_reasons = JSON.parse(row.spam_reasons); | ||
row.asn = row.asn.toString(); | ||
return row; | ||
}); | ||
|
||
return Response.json(rows); | ||
} | ||
|
||
// TODO: this is bad practice, consider replacing (see https://www.reddit.com/r/learnjavascript/comments/qgtut6/comment/hi8jg6w/) | ||
Date.prototype.subtractDays = function(days) { | ||
var date = new Date(this.valueOf()); | ||
date.setDate(date.getDate() - days); | ||
return date; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
export async function onRequest(context) { | ||
if (context.request.method !== "GET") { | ||
return new Response("Invalid request method", { status: 405 }); | ||
} | ||
|
||
const submissionsQuery = await context.env.DB_FORMS.prepare("SELECT * FROM submissions WHERE submission_id = ? ORDER BY submitted_ts DESC") | ||
.bind( | ||
context.params.submission, | ||
) | ||
.all(); | ||
const rows = submissionsQuery | ||
.results | ||
.map((row) => { | ||
row.fields = JSON.parse(row.fields); | ||
row.spam_reasons = JSON.parse(row.spam_reasons); | ||
row.cf = JSON.parse(row.cf); | ||
row.headers = JSON.parse(row.headers); | ||
return row; | ||
}); | ||
|
||
if (rows.length === 0) { | ||
return new Response("Submission not found", { status: 404 }); | ||
} else if (rows.length === 1) { | ||
return Response.json(rows[0]); | ||
} else { | ||
return new Response(`Multiple submissions found for ID "${context.params.submission}"`, { status: 500 }); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
--- | ||
layout: default | ||
title: Form Submissions | ||
--- | ||
|
||
<div id="description"></div> | ||
<div id="content"><div class="lds-dual-ring"></div></div> | ||
|
||
<script> | ||
const description = document.getElementById("description"); | ||
const content = document.getElementById("content"); | ||
if (window.location.hash) { | ||
displaySubmission(window.location.hash.substring(1)); | ||
} else { | ||
displaySubmissions(); | ||
} | ||
|
||
function displaySubmission(id) { | ||
description.innerHTML = ` | ||
<p><a href="javascript:displaySubmissions()">Go back to submissions</a></p> | ||
<h2>Form submission ${id} | ||
`; | ||
content.innerHTML = '<div class="lds-dual-ring"></div>'; | ||
fetch(`/secure/api/form/${id}`, { | ||
method: "GET", | ||
headers: { | ||
"accept": "application/json", | ||
"content-type": "application/json", | ||
}, | ||
}) | ||
.then(res => res.json()) | ||
.then(submission => { | ||
const submitted = new Date(submission.submitted_ts); | ||
content.innerHTML = ` | ||
<h3>Form ID</h3> | ||
<p>${submission.form_id}</p> | ||
<h3>Submitted</h3> | ||
<p>${submitted.toLocaleDateString()} ${submitted.toLocaleTimeString()}</p> | ||
`; | ||
if (submission.reply_email) { | ||
const replyEmail = submission.reply_email; | ||
content.innerHTML += ` | ||
<h3>Email address (reply-to)</h3> | ||
<p><a href="mailto:${replyEmail}">${replyEmail}</a></p> | ||
`; | ||
} | ||
if (submission.spam_reasons.length) { | ||
content.innerHTML += "<h3>Spam reasons</h3><ul>"; | ||
submission.spam_reasons.forEach(reason => { | ||
content.innerHTML += `<li>${reason}</li>`; | ||
}) | ||
content.innerHTML += "</ul>"; | ||
} | ||
content.innerHTML += ` | ||
<h3>Form fields</h3> | ||
<p>${escapeHtml(JSON.stringify(submission.fields))}</p> | ||
<h3>cf object</h3> | ||
<p>${JSON.stringify(submission.cf)}</p> | ||
<h3>HTTP headers</h3> | ||
<p>${JSON.stringify(submission.headers)}</p> | ||
`; | ||
window.location.hash = id; | ||
}) | ||
} | ||
|
||
function displaySubmissions() { | ||
description.innerHTML = "<p>This table shows form submissions over the last 30 days:</p>"; | ||
content.innerHTML = '<div class="lds-dual-ring"></div>'; | ||
fetch("/secure/api/form", { | ||
method: "GET", | ||
headers: { | ||
"accept": "application/json", | ||
"content-type": "application/json", | ||
}, | ||
}) | ||
.then(res => res.json()) | ||
.then(submissions => { | ||
const table = document.createElement("table"); | ||
const thead = table.createTHead(); | ||
const headings = thead.insertRow(); | ||
[ | ||
"Submission ID", | ||
"Form ID", | ||
"Submitted", | ||
"Spam Reasons", | ||
"IP Address", | ||
"ASN", | ||
].forEach(heading => { | ||
const th = document.createElement("th"); | ||
th.innerHTML = heading; | ||
headings.appendChild(th); | ||
}); | ||
const tbody = table.createTBody(); | ||
submissions.forEach(row => { | ||
const tr = tbody.insertRow(); | ||
|
||
const tdSubmissionId = tr.insertCell(); | ||
const id = row.submission_id; | ||
tdSubmissionId.innerHTML = `<a href="javascript:displaySubmission('${id}')">${id}</a>`; | ||
|
||
const tdFormId = tr.insertCell(); | ||
tdFormId.innerHTML = row.form_id; | ||
|
||
const tdSubmitted = tr.insertCell(); | ||
const submitted = new Date(row.submitted_ts); | ||
tdSubmitted.innerHTML = `${submitted.toLocaleDateString()} ${submitted.toLocaleTimeString()}`; | ||
|
||
const tdSpamReasons = tr.insertCell(); | ||
tdSpamReasons.innerHTML = row.spam_reasons.join([separator = ', ']); | ||
|
||
const tdIpAddress = tr.insertCell(); | ||
tdIpAddress.innerHTML = `${getFlagEmoji(row.country)} <a href="https://cleantalk.org/blacklists/${row.ip}">${row.ip}</a>`; | ||
|
||
const tdAsn = tr.insertCell(); | ||
const asn = row.asn; | ||
tdAsn.innerHTML = `<a href="https://bgp.tools/as/${asn}">AS${asn}</a>`; | ||
}); | ||
content.innerHTML = table.outerHTML; | ||
history.pushState("", document.title, window.location.pathname + window.location.search); | ||
}); | ||
} | ||
|
||
function escapeHtml(unsafe) { | ||
return unsafe | ||
.replace(/&/g, "&") | ||
.replace(/</g, "<") | ||
.replace(/>/g, ">") | ||
.replace(/"/g, """) | ||
.replace(/'/g, "'"); | ||
} | ||
|
||
// https://www.bqst.fr/country-code-to-flag-emoji/ | ||
const getFlagEmoji = countryCode=>String.fromCodePoint(...[...countryCode.toUpperCase()].map(x=>0x1f1a5+x.charCodeAt())); | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters