diff options
| author | Pinapelz <yukais@pinapelz.com> | 2024-10-13 23:57:45 -0700 |
|---|---|---|
| committer | Pinapelz <yukais@pinapelz.com> | 2024-10-13 23:57:45 -0700 |
| commit | 6ced144db0441133701cb1982de0137a82a14698 (patch) | |
| tree | 6fe923480a227f471ecebbe4b8160f20cb3a75ca /api | |
| parent | e1c4f7ac903df58ae5f63c6f837af9f97426f5ad (diff) | |
fix server side captcha authentication
Diffstat (limited to 'api')
| -rw-r--r-- | api/app.py | 26 | ||||
| -rw-r--r-- | api/static/server_auth.js | 127 |
2 files changed, 82 insertions, 71 deletions
@@ -4,7 +4,9 @@ import psycopg2 from psycopg2 import Error import os import secrets +from dotenv import load_dotenv +load_dotenv() app = Flask(__name__) CORS(app) @@ -19,14 +21,14 @@ class PostgresHandler: } self._connection = psycopg2.connect(**db_params) print("Handler Success") - + def create_table(self, name: str, column: str): cursor = self._connection.cursor() cursor.execute(f"CREATE TABLE IF NOT EXISTS {name} ({column})") self._connection.commit() cursor.close() - + def clear_table(self, name: str): cursor = self._connection.cursor() cursor.execute(f"DELETE FROM {name}") @@ -44,7 +46,7 @@ class PostgresHandler: return True else: return False - + def insert_row(self, table_name, column, data): try: cursor = self._connection.cursor() @@ -60,7 +62,7 @@ class PostgresHandler: if "duplicate key" not in str(err).lower(): return False return True - + def get_rows(self, table_name: str, column: str, value: str): try: cursor = self._connection.cursor() @@ -73,7 +75,7 @@ class PostgresHandler: print(f"Failed to fetch row from {table_name} WHERE {column} is {value}") print(e) return False - + def get_random_row(self, table_name: str, count: int, condition: str = None): if condition is None: condition = "1 = 1" @@ -88,7 +90,7 @@ class PostgresHandler: print(f"Failed to select random rows from {table_name}") print(e) return False - + def check_health(self): cursor = self._connection.cursor() cursor.execute("SELECT 1") @@ -98,7 +100,7 @@ class PostgresHandler: return True else: return False - + def delete_row(self, table_name: str, column: str, value: str): try: cursor = self._connection.cursor() @@ -113,7 +115,7 @@ class PostgresHandler: return False return True - + def close_connection(self): self._connection.close() @@ -162,7 +164,8 @@ def generate_organization_captcha(org): solutions = [] for question in question_data: if question['affiliation'] == org: - solutions.append(question['id']) + solutions.append(str(question['id'])) + print(solutions) server.insert_row("sessions", "session_id, answer", (session_id, ",".join(solutions))) for question in question_data: del question["affiliation"] @@ -181,7 +184,7 @@ def generate_organization_captcha(org): if question['affiliation'] == org: question['answer'] = True else: - question['answer'] = False + question['answer'] = False return_data = { "category": "affiliation", "title": "Select all the VTubers affiliated with "+org, @@ -197,6 +200,7 @@ def generate_organization_captcha(org): def verify_answers(): session_id = request.form.get('session') answer = request.form.get('answer') + print("[Verify Answer] " + session_id + answer) server = create_database_connection() if server.check_health() is False: return jsonify({"error": "Cannot connect to verification database"}), 500 @@ -214,7 +218,7 @@ def verify_answers(): def clear_sessions(): auth = request.headers.get("Authorization") cron_secret = os.environ.get("CRON_SECRET") - print("Checking if " + auth + " matches " + cron_secret) + print("Recieved Request to Clear Session: Checking if " + auth + " matches " + cron_secret) if auth.strip() != cron_secret.strip(): return jsonify({"error": "Unauthorized"}), 401 server = create_database_connection() diff --git a/api/static/server_auth.js b/api/static/server_auth.js index ead24a7..34fd4fd 100644 --- a/api/static/server_auth.js +++ b/api/static/server_auth.js @@ -1,93 +1,100 @@ let captchaData; document.addEventListener("DOMContentLoaded", function () { - fetchCaptchaImages(); + fetchCaptchaImages(); }); function toggleSelection(element) { - element.classList.toggle("selected"); + element.classList.toggle("selected"); } function populateCaptcha(data) { - const container = document.getElementById("recaptcha-container"); - const title = document.getElementById("recaptcha-title"); - title.innerHTML = data.title; - const oldRows = container.getElementsByClassName("recaptcha-row"); - while (oldRows.length > 0) { - oldRows[0].parentNode.removeChild(oldRows[0]); - } + const container = document.getElementById("recaptcha-container"); + const title = document.getElementById("recaptcha-title"); + title.innerHTML = data.title; + const oldRows = container.getElementsByClassName("recaptcha-row"); + while (oldRows.length > 0) { + oldRows[0].parentNode.removeChild(oldRows[0]); + } - const images = data.questions; + const images = data.questions; - let rows = Math.ceil(images.length / 4); - let htmlContent = ""; - for (let r = 0; r < rows; r++) { - htmlContent += '<div class="recaptcha-row">'; - for (let i = 0; i < 4; i++) { - const index = r * 4 + i; - if (images[index]) { - htmlContent += ` + let rows = Math.ceil(images.length / 4); + let htmlContent = ""; + for (let r = 0; r < rows; r++) { + htmlContent += '<div class="recaptcha-row">'; + for (let i = 0; i < 4; i++) { + const index = r * 4 + i; + if (images[index]) { + htmlContent += ` <div class="recaptcha-image" style="background-image: url('${images[index].image}');" onclick="toggleSelection(this)"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M20.285 2l-1.272.02L6.72 15.466l-5.644-5.58L0 12.352l7.218 7.15L24 2.083z"/> </svg> </div> `; - } + } + } + htmlContent += "</div>"; } - htmlContent += "</div>"; - } - title.insertAdjacentHTML("afterend", htmlContent); - captchaData = data; - session_id = data.session_id; + title.insertAdjacentHTML("afterend", htmlContent); + captchaData = data; + session_id = data.session_id; } async function verifyCaptcha() { - const selectedImages = document.querySelectorAll(".recaptcha-image.selected"); - const answers = []; - selectedImages.forEach((img) => { - const backgroundImageURL = img.style.backgroundImage; - const imageURL = backgroundImageURL.slice(5, backgroundImageURL.length - 2); - answers.push( - captchaData.questions.find((question) => question.image === imageURL).id + const selectedImages = document.querySelectorAll( + ".recaptcha-image.selected", ); - }); - const captchaAnswer = { - session: captchaData.session, - answer: answers.join(","), - }; - try { - const response = await fetch("/api/verify", { - method: "POST", - headers: { - "Content-Type": "application/x-www-form-urlencoded", - }, - body: new URLSearchParams(captchaAnswer).toString(), // Convert JSON object to form-urlencoded data + const answers = []; + selectedImages.forEach((img) => { + const backgroundImageURL = img.style.backgroundImage; + const imageURL = backgroundImageURL.slice( + 5, + backgroundImageURL.length - 2, + ); + answers.push( + captchaData.questions.find( + (question) => question.image === imageURL, + ).id, + ); }); - const data = await response.json(); + const captchaAnswer = { + session: captchaData.session, + answer: answers.join(","), + }; + try { + const response = await fetch("/api/verify", { + method: "POST", + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + body: new URLSearchParams(captchaAnswer).toString(), // Convert JSON object to form-urlencoded data + }); + const data = await response.json(); - if (data.success) { - alert("Captcha verification successful!"); - } else { - alert("Sorry you got some wrong. Please try again.") - fetchCaptchaImages(); + if (data.success) { + alert("Captcha verification successful!"); + } else { + alert("Sorry you got some wrong. Please try again."); + fetchCaptchaImages(); + } + } catch (error) { + console.error("Error verifying captcha:", error); } - } catch (error) { - console.error("Error verifying captcha:", error); - } } const submitButton = document.querySelector(".submit-btn"); submitButton.addEventListener("click", verifyCaptcha); function fetchCaptchaImages() { - fetch("/api/affiliation/Nijisanji?auth=server") - .then((response) => response.json()) - .then((data) => { - populateCaptcha(data); - }) - .catch((error) => { - console.error("There was an error fetching the captcha:", error); - }); + fetch("/api/affiliation/Phase%20Connect?auth=server") + .then((response) => response.json()) + .then((data) => { + populateCaptcha(data); + }) + .catch((error) => { + console.error("There was an error fetching the captcha:", error); + }); } |
