summaryrefslogtreecommitdiff
path: root/http/public
diff options
context:
space:
mode:
Diffstat (limited to 'http/public')
-rw-r--r--http/public/do/send_email.php124
-rw-r--r--http/public/do/send_otp.php104
-rw-r--r--http/public/do/verify_otp.php63
l---------http/public/images1
-rw-r--r--http/public/scripts/contact/actions.js60
-rw-r--r--http/public/scripts/contact/post-error-message.js34
-rw-r--r--http/public/scripts/contact/resend-otp.js31
-rw-r--r--http/public/scripts/contact/reset-resend-button.js32
-rw-r--r--http/public/scripts/contact/selectors.js25
-rw-r--r--http/public/scripts/contact/submit-contact-form.js53
-rw-r--r--http/public/scripts/contact/submit-otp-form.js77
-rw-r--r--http/public/scripts/otp-form-wc.js68
12 files changed, 0 insertions, 672 deletions
diff --git a/http/public/do/send_email.php b/http/public/do/send_email.php
deleted file mode 100644
index 51d8b19..0000000
--- a/http/public/do/send_email.php
+++ /dev/null
@@ -1,124 +0,0 @@
-<?php
-
-use JoeacNet\Http\Config;
-use JoeacNet\Http\Db;
-use JoeacNet\Http\Mail;
-
-require_once __DIR__ . "/../../vendor/autoload.php";
-require_once __DIR__ . "/../../php/config.php";
-require_once __DIR__ . "/../../php/db.php";
-require_once __DIR__ . "/../../php/mail.php";
-
-$db = Db\connectDb();
-
-$payload = json_decode(file_get_contents("php://input"), true);
-$name = getNameFromPayloadAndValidate($payload);
-$email = getEmailFromPayloadAndValidate($payload);
-$message = getMessageFromPayloadAndValidate($payload);
-$token = getTokenFromPayloadAndValidate($payload);
-$userId = getUserIdFromPayloadAndValidate($payload);
-
-limitMaxDailyEmails($db);
-verifyToken(db: $db, userId: $userId, token: $token);
-Db\deleteAllTokensForUser($db, $userId);
-
-$messageId = Mail\sendEmail(
- subject: "joeac.net: $name left a message",
- replyToEmail: $email,
- replyToName: $name,
- toEmail: Config\contactMailbox(),
- toName: Config\contactMailboxName(),
- body: "$name <$email> sent you a message:\n\n\n$message",
-);
-Db\recordSentEmail($db, $messageId);
-syslog(LOG_INFO, "Sent an email to Joe. Message ID: $messageId");
-
-http_response_code(200);
-echo $messageId;
-exit();
-
-/// functions ///
-
-function verifyToken(PDO $db, string $userId, string $token)
-{
- if (!Db\isTokenValid($db, $userId, $token)) {
- http_response_code(400);
- echo "token is not valid";
- exit();
- }
-}
-
-function limitMaxDailyEmails(PDO $db)
-{
- $countEmailsSentLast24Hours = Db\countEmailsSentLast24Hours($db);
- if ($countEmailsSentLast24Hours > Config\maxDailyEmails()) {
- $msg =
- "$countEmailsSentLast24Hours emails have been sent in the last 24 hours, but the max daily load is " .
- Config\maxDailyEmails() .
- ".";
- syslog(LOG_WARNING, $msg);
- http_response_code(500);
- echo $msg;
- exit();
- }
-}
-
-function getNameFromPayloadAndValidate(array $payload): string
-{
- $name = (string) $payload["name"];
- if (is_null($name) || $name == "") {
- http_response_code(400);
- echo "name must not be empty";
- exit();
- }
- return $name;
-}
-
-function getEmailFromPayloadAndValidate(array $payload): string
-{
- $email = (string) $payload["email"];
- if (is_null($email) || $email == "") {
- http_response_code(400);
- echo "email must not be empty";
- exit();
- }
- if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
- http_response_code(400);
- echo "<$email> is not a valid email address.";
- exit();
- }
- return $email;
-}
-
-function getMessageFromPayloadAndValidate(array $payload): string
-{
- $message = (string) $payload["message"];
- if (is_null($message) || $message == "") {
- http_response_code(400);
- echo "message must not be empty";
- exit();
- }
- return $message;
-}
-
-function getTokenFromPayloadAndValidate(array $payload): string
-{
- $token = (string) $payload["token"];
- if (is_null($token) || $token == "") {
- http_response_code(400);
- echo "token must not be empty";
- exit();
- }
- return $token;
-}
-
-function getUserIdFromPayloadAndValidate(array $payload): string
-{
- $userId = (string) $payload["userId"];
- if (is_null($userId) || $userId == "") {
- http_response_code(400);
- echo "userId must not be empty";
- exit();
- }
- return $userId;
-}
diff --git a/http/public/do/send_otp.php b/http/public/do/send_otp.php
deleted file mode 100644
index 5ca4d85..0000000
--- a/http/public/do/send_otp.php
+++ /dev/null
@@ -1,104 +0,0 @@
-<?php
-
-use JoeacNet\Http\Config;
-use JoeacNet\Http\Db;
-use JoeacNet\Http\Mail;
-
-require_once __DIR__ . "/../../php/config.php";
-require_once __DIR__ . "/../../php/db.php";
-require_once __DIR__ . "/../../php/mail.php";
-
-const SEND_OTP_TYPES = ["email"];
-
-$db = Db\connectDb();
-
-$payload = json_decode(file_get_contents("php://input"), true);
-$email = getEmailFromPayloadAndValidate($payload);
-$name = getNameFromPayloadAndValidate($payload);
-$type = getTypeFromPayloadAndValidate($payload);
-
-limitMaxDailyEmails(db: $db, email: $email, name: $name);
-
-$otp = strtoupper(bin2hex(random_bytes(3)));
-$prettyOtp = substr($otp, 0, 3) . "-" . substr($otp, 3, 6);
-Db\insertOtp(db: $db, userId: $email, otp: $otp);
-
-try {
- $messageId = Mail\sendEmail(
- toEmail: $email,
- toName: $name,
- subject: "joeac.net: your OTP is $prettyOtp",
- body: <<<BODY
- Someone tried to use this email address on joeac.net. If this was you,
- your one-time passcode is $prettyOtp. If this wasn't you, you don't need
- to do anything.
- BODY,
- );
-} catch (Exception $e) {
- error_log("Email could not be sent: $e");
- http_response_code(500);
- echo "Email could not be sent: $e";
- exit();
-}
-
-Db\recordSentEmail($db, $messageId);
-syslog(LOG_INFO, "Sent OTP ($prettyOtp) to $email. Message ID: $messageId");
-
-http_response_code(200);
-echo $messageId;
-exit();
-
-/// functions ///
-
-function limitMaxDailyEmails(PDO $db, string $email, string $name)
-{
- $countEmailsSentLast24Hours = Db\countEmailsSentLast24Hours($db);
- if ($countEmailsSentLast24Hours > Config\maxDailyEmails()) {
- $msg =
- "$name <$email> requested an OTP email, but $countEmailsSentLast24Hours emails have already been sent, whereas the max daily load is " .
- Config\maxDailyEmails() .
- ".";
- syslog(LOG_WARNING, $msg);
- http_response_code(500);
- echo $msg;
- exit();
- }
-}
-
-function getNameFromPayloadAndValidate(array $payload): string
-{
- $name = (string) $payload["name"];
- if (is_null($name) || $name == "") {
- http_response_code(400);
- echo "name must not be empty";
- exit();
- }
- return $name;
-}
-
-function getEmailFromPayloadAndValidate(array $payload): string
-{
- $email = (string) $payload["email"];
- if (is_null($email) || $email == "") {
- http_response_code(400);
- echo "email must not be empty";
- exit();
- }
- if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
- http_response_code(400);
- echo "<$email> is not a valid email address.";
- exit();
- }
- return $email;
-}
-
-function getTypeFromPayloadAndValidate(array $payload): string
-{
- $type = (string) $payload["type"];
- if (!in_array($type, SEND_OTP_TYPES)) {
- http_response_code(400);
- echo "type must be one of: " . SEND_OTP_TYPES;
- exit();
- }
- return $type;
-}
diff --git a/http/public/do/verify_otp.php b/http/public/do/verify_otp.php
deleted file mode 100644
index 7f86858..0000000
--- a/http/public/do/verify_otp.php
+++ /dev/null
@@ -1,63 +0,0 @@
-<?php
-
-use JoeacNet\Http\Db;
-
-require_once __DIR__ . "/../../php/db.php";
-
-$db = Db\connectDb();
-
-$payload = json_decode(file_get_contents("php://input"), true);
-$guess = getGuessFromPayloadAndValidate($payload);
-$leniencySecs = getLeniencySecsFromPayloadAndValidate($payload);
-$userId = getUserIdFromPayloadAndValidate($payload);
-
-if (
- !Db\isOtpCorrect(
- db: $db,
- userId: $userId,
- guess: $guess,
- leniencySecs: $leniencySecs,
- )
-) {
- http_response_code(400);
- echo "OTP is not valid";
- exit();
-}
-Db\deleteAllOtpsForUser($db, $userId);
-$token = bin2hex(random_bytes(256));
-Db\insertSendEmailToken(db: $db, userId: $userId, token: $token);
-http_response_code(200);
-echo $token;
-exit();
-
-/// functions ///
-
-function getGuessFromPayloadAndValidate(array $payload): string
-{
- $guess = (string) $payload["guess"];
- if (strlen($guess) != 6) {
- http_response_code(400);
- echo "guess must be six characters long";
- exit();
- }
- return $guess;
-}
-
-function getLeniencySecsFromPayloadAndValidate(array $payload): int
-{
- if ((bool) $payload["lenient"] ?? false) {
- return 60;
- }
- return 0;
-}
-
-function getUserIdFromPayloadAndValidate(array $payload): string
-{
- $userId = (string) $payload["userId"];
- if (is_null($userId) || $userId == "") {
- http_response_code(400);
- echo "userId must not be empty";
- exit();
- }
- return $userId;
-}
diff --git a/http/public/images b/http/public/images
deleted file mode 120000
index ccc7a5b..0000000
--- a/http/public/images
+++ /dev/null
@@ -1 +0,0 @@
-../../common/images/ \ No newline at end of file
diff --git a/http/public/scripts/contact/actions.js b/http/public/scripts/contact/actions.js
deleted file mode 100644
index 5a7e32a..0000000
--- a/http/public/scripts/contact/actions.js
+++ /dev/null
@@ -1,60 +0,0 @@
-export const actions = {
- /**
- * @param {{type: 'email', name: string, email: string}}
- * @returns {Promise<void>}
- */
- sendOtp: async ({ type, name, email }) => {
- const url = "/do/send_otp.php";
- const req = new Request(url, {
- method: "POST",
- body: JSON.stringify({ type, name, email }),
- });
- const res = await fetch(req);
- if (!res.ok) {
- throw new Error(
- `Request to ${url} failed: ${res.status} ${res.statusText} ${await res.text()}`,
- );
- }
- },
-
- /**
- * @param {{guess: string, lenient?: bool, userId: string}}
- * @returns {Promise<string | false>}
- */
- verifyOtp: async ({ guess, lenient, userId }) => {
- const url = "/do/verify_otp.php";
- const req = new Request(url, {
- method: "POST",
- body: JSON.stringify({ guess, lenient, userId }),
- });
- const res = await fetch(req);
-
- if (res.status === 400) {
- return false;
- } else if (!res.ok) {
- throw new Error(
- `Request to ${url} failed: ${res.status} ${res.statusText} ${await res.text()}`,
- );
- }
-
- return res.text();
- },
-
- /**
- * @param {{email: string, message: string, name: string, userId: string, token: string}}
- * @returns {Promise<void>}
- */
- sendEmail: async ({ email, message, name, userId, token }) => {
- const url = "/do/send_email.php";
- const req = new Request(url, {
- method: "POST",
- body: JSON.stringify({ email, message, name, userId, token }),
- });
- const res = await fetch(req);
- if (!res.ok) {
- throw new Error(
- `Request to ${url} failed: ${res.status} ${res.statusText} ${await res.text()}`,
- );
- }
- },
-};
diff --git a/http/public/scripts/contact/post-error-message.js b/http/public/scripts/contact/post-error-message.js
deleted file mode 100644
index 121cbb6..0000000
--- a/http/public/scripts/contact/post-error-message.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/** @typedef {import("./selectors.js").Selectors} Selectors */
-
-/**
- * @param {{contactForm: Selectors}} contactForm
- * @param {string} errorMsg
- */
-export function postErrorMessageOnContactForm({ contactForm }, errorMsg) {
- const errorElem = contactForm.errorElem();
- if (errorElem) {
- errorElem.textContent = errorMsg;
- errorElem.removeAttribute("hidden");
- } else {
- alert(errorMsg);
- }
-}
-
-/**
- * @param {{otpDialog: Selectors}} otpDialog
- * @param {string} errorMsg
- */
-export function postErrorMessageOnOtpForm({ otpDialog }, errorMsg) {
- const errorElem = otpDialog.errorElem();
- if (errorElem) {
- errorElem.textContent = errorMsg;
- errorElem.removeAttribute("hidden");
- } else {
- alert(errorMsg);
- }
- /** @type NodeListOf<HTMLInputElement> */
- const inputs = otpDialog.allOtpInputs();
- for (const input of inputs) {
- input.value = "";
- }
-}
diff --git a/http/public/scripts/contact/resend-otp.js b/http/public/scripts/contact/resend-otp.js
deleted file mode 100644
index e083d95..0000000
--- a/http/public/scripts/contact/resend-otp.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/** @typedef {import("./selectors.js").Selectors} Selectors */
-
-import { actions } from "./actions.js";
-import { resetResendButton } from "./reset-resend-button.js";
-import { postErrorMessageOnOtpForm } from "./post-error-message.js";
-
-/** @typedef {{ resendButtonInterval: NodeJS.Timeout | undefined }} Result */
-
-const fallbackErrorMsg =
- "No can do. I'm afraid joeac.net is a bit broken right now - sorry about that.";
-
-/**
- * @param {Selectors} selectors
- * @param {NodeJS.Timeout | undefined} resetButtonInterval
- * @returns {Promise<Result>}
- */
-export async function resendOtp(selectors, resetButtonInterval) {
- const result = resetResendButton(selectors, resetButtonInterval);
- const name = selectors.contactForm.nameElem()?.value;
- const email = selectors.contactForm.emailElem().value;
-
- try {
- await actions.sendOtp({ type: "email", name, email });
- } catch (sendOtpError) {
- const errorMsg = sendOtpError?.toString() ?? fallbackErrorMsg;
- postErrorMessageOnOtpForm(selectors, errorMsg);
- throw sendOtpError;
- }
-
- return result;
-}
diff --git a/http/public/scripts/contact/reset-resend-button.js b/http/public/scripts/contact/reset-resend-button.js
deleted file mode 100644
index 47bc9ac..0000000
--- a/http/public/scripts/contact/reset-resend-button.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/** @typedef {import("./selectors.js").Selectors} Selectors */
-
-/** @typedef {{ resendButtonInterval: NodeJS.Timeout | undefined }} Result */
-
-/**
- * @param {Selectors} selectors
- * @param {NodeJS.Timeout | undefined} resetButtonInterval
- * @returns {Result}
- */
-export function resetResendButton({ otpDialog }, resendButtonInterval) {
- clearInterval(resendButtonInterval);
-
- const resendButton = otpDialog.resendButton();
- if (resendButton) {
- resendButton.setAttribute("data-countdown", "60");
- resendButton.setAttribute("disabled", "");
-
- resendButtonInterval = setInterval(() => {
- const countdown = +(resendButton.getAttribute("data-countdown") ?? 1) - 1;
- resendButton.setAttribute("data-countdown", countdown.toString());
- resendButton.textContent = `Resend (${countdown}s)`;
- }, 1000);
-
- setTimeout(() => {
- clearInterval(resendButtonInterval);
- resendButton.textContent = "Resend";
- resendButton.removeAttribute("disabled");
- }, 1000 * 60);
- }
-
- return { resendButtonInterval };
-}
diff --git a/http/public/scripts/contact/selectors.js b/http/public/scripts/contact/selectors.js
deleted file mode 100644
index 7676414..0000000
--- a/http/public/scripts/contact/selectors.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * @typedef {Object} Selectors
- * @property {Object} contactForm
- * @property {() => HTMLInputElement} contactForm.emailElem
- * @property {() => Element | null} contactForm.errorElem
- * @property {() => HTMLInputElement} contactForm.nameElem
- * @property {() => HTMLTextAreaElement} contactForm.messageElem
- * @property {() => HTMLFormElement | null} contactForm.self
- * @property {() => HTMLInputElement | null} contactForm.submitButton
- * @property {Object} otpDialog
- * @property {() => NodeListOf<HTMLInputElement>} otpDialog.allOtpInputs
- * @property {() => Element | null} otpDialog.errorElem
- * @property {() => HTMLInputElement | null} otpDialog.firstOtpInput
- * @property {() => HTMLFormElement | null} otpDialog.otpForm
- * @property {() => Element | null} otpDialog.otpRecipient
- * @property {() => Element | null} otpDialog.otpValidUntil
- * @property {() => HTMLButtonElement | null} otpDialog.resendButton
- * @property {() => HTMLDialogElement} otpDialog.self
- * @property {() => HTMLInputElement | null} otpDialog.submitButton
- * @property {Object} successSection
- * @property {() => Element | null} successSection.email
- * @property {() => Element | null} successSection.message
- * @property {() => Element | null} successSection.name
- * @property {() => Element | null} successSection.self
- */
diff --git a/http/public/scripts/contact/submit-contact-form.js b/http/public/scripts/contact/submit-contact-form.js
deleted file mode 100644
index a90f420..0000000
--- a/http/public/scripts/contact/submit-contact-form.js
+++ /dev/null
@@ -1,53 +0,0 @@
-import { actions } from "./actions.js";
-import { postErrorMessageOnContactForm } from "./post-error-message.js";
-import { resetResendButton } from "./reset-resend-button.js";
-
-/** @typedef {import("./selectors.js").Selectors} Selectors */
-
-const fallbackErrorMsg =
- "No can do. I'm afraid joeac.net is a bit broken right now - sorry about that.";
-
-/**
- * @param {Selectors} selectors
- * @param {NodeJS.Timeout | undefined} resetButtonInterval
- * @returns {Promise<Result>}
- */
-export async function submitContactForm(selectors, resendButtonInterval) {
- const { contactForm, otpDialog } = selectors;
-
- const name = contactForm.nameElem()?.value;
- const email = contactForm.emailElem().value;
-
- contactForm.submitButton()?.setAttribute("disabled", "");
- try {
- await actions.sendOtp({ type: "email", name, email });
- } catch (sendOtpError) {
- const errorMsg = sendOtpError?.toString() ?? fallbackErrorMsg;
- postErrorMessageOnContactForm(selectors, errorMsg);
- throw sendOtpError;
- }
-
- const otpRecipient = otpDialog.otpRecipient();
- email && otpRecipient && (otpRecipient.textContent = `<${email}>`);
- const otpValidUntil = otpDialog.otpValidUntil();
- const validUntil = new Date(Date.now() + 1000 * 60 * 5);
- otpValidUntil &&
- (otpValidUntil.textContent = `until ${validUntil.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })}`);
-
- const dialog = otpDialog.self();
- dialog.showModal();
- contactForm.submitButton()?.removeAttribute("disabled");
- dialog.addEventListener("click", function (event) {
- const rect = dialog.getBoundingClientRect();
- const isInDialog =
- rect.top <= event.clientY &&
- event.clientY <= rect.top + rect.height &&
- rect.left <= event.clientX &&
- event.clientX <= rect.left + rect.width;
- if (!isInDialog) {
- dialog.close();
- }
- });
-
- return resetResendButton(selectors, resendButtonInterval);
-}
diff --git a/http/public/scripts/contact/submit-otp-form.js b/http/public/scripts/contact/submit-otp-form.js
deleted file mode 100644
index 8c09314..0000000
--- a/http/public/scripts/contact/submit-otp-form.js
+++ /dev/null
@@ -1,77 +0,0 @@
-import { actions } from "./actions.js";
-import { postErrorMessageOnOtpForm } from "./post-error-message.js";
-
-/** @typedef {import("./selectors.js").Selectors} Selectors */
-
-const fallbackErrorMsg =
- "No can do. I'm afraid joeac.net is a bit broken right now - sorry about that.";
-
-/**
- * @param {Selectors} selectors
- */
-export async function submitOtpForm(selectors) {
- const { contactForm, otpDialog, successSection } = selectors;
- const otpForm = otpDialog.otpForm();
- otpDialog.submitButton()?.setAttribute("disabled", "");
-
- const otpFormData = new FormData(otpForm ?? undefined);
- const guess = [
- otpFormData.get("1"),
- otpFormData.get("2"),
- otpFormData.get("3"),
- otpFormData.get("4"),
- otpFormData.get("5"),
- otpFormData.get("6"),
- ].join("");
-
- const name = contactForm.nameElem()?.value;
- const email = contactForm.emailElem().value;
- const message = contactForm.messageElem()?.value;
-
- let verifyResult;
- try {
- verifyResult = await actions.verifyOtp({ guess, userId: email });
- } catch (verifyError) {
- otpDialog.submitButton()?.removeAttribute("disabled");
- postErrorMessageOnOtpForm(
- selectors,
- verifyError?.toString() ?? fallbackErrorMsg,
- );
- return;
- }
-
- if (verifyResult === false) {
- otpDialog.submitButton()?.removeAttribute("disabled");
- postErrorMessageOnOtpForm(selectors, "Incorrect OTP. Check your email?");
- otpDialog.firstOtpInput()?.focus();
- return;
- }
- const sendmailToken = verifyResult;
-
- try {
- await actions.sendEmail({
- email,
- message: message,
- name: name,
- userId: email,
- token: sendmailToken,
- });
- } catch (sendEmailError) {
- const errorMsg = sendEmailError?.toString() ?? fallbackErrorMsg;
- postErrorMessageOnOtpForm(selectors, errorMsg);
- otpDialog.submitButton()?.removeAttribute("disabled");
- return;
- }
-
- const sentName = successSection.name();
- const sentEmail = successSection.email();
- const sentMessage = successSection.message();
- sentName && (sentName.textContent = name ?? "???");
- sentEmail && (sentEmail.textContent = email ?? "???");
- sentMessage && (sentMessage.textContent = message ?? "???");
-
- contactForm.self()?.remove();
- successSection.self()?.removeAttribute("hidden");
- otpDialog.submitButton()?.removeAttribute("disabled");
- otpDialog.self().close();
-}
diff --git a/http/public/scripts/otp-form-wc.js b/http/public/scripts/otp-form-wc.js
deleted file mode 100644
index 49e1b02..0000000
--- a/http/public/scripts/otp-form-wc.js
+++ /dev/null
@@ -1,68 +0,0 @@
-class OtpForm extends HTMLElement {
- /** @type MutationObserver? */
- observer;
-
- constructor() {
- super();
- }
-
- connectedCallback() {
- this.observer = new MutationObserver(() => {
- this.clearInputs();
- this.configureInputs();
- });
- this.observer.observe(this, { childList: true, subtree: true });
- }
-
- disconnectedCallback() {
- this.observer?.disconnect();
- }
-
- clearInputs() {
- console.log("clearing all inputs");
- /** @type NodeListOf<HTMLInputElement> */
- const inputs = this.querySelectorAll('input:not([type="submit"])');
- for (const input of inputs) {
- input.value = "";
- }
- }
-
- configureInputs() {
- this.observer?.disconnect();
- /** @type NodeListOf<HTMLInputElement> */
- const inputs = this.querySelectorAll('input:not([type="submit"])');
- /** @type NodeListOf<HTMLFormElement> */
- const form = this.querySelector("form");
-
- for (const input of inputs) {
- input.addEventListener("focus", () => {
- input.select();
- });
-
- input.addEventListener("input", () => {
- if (input.value.length > 0) {
- input.value = input.value.slice(0, 1).toLocaleUpperCase();
- /** @type HTMLInputElement */
- const nextInput = input.nextElementSibling;
- if (nextInput) {
- nextInput.focus();
- return;
- }
-
- /** @type HTMLInputElement */
- const submitButton = form.querySelector('input[type="submit"]');
- submitButton.focus();
- let areAllInputsEntered = true;
- inputs.forEach((input) => {
- areAllInputsEntered = areAllInputsEntered && input.value.length > 0;
- });
- if (areAllInputsEntered) {
- form.requestSubmit(submitButton);
- }
- }
- });
- }
- }
-}
-
-customElements.define("otp-form", OtpForm);