aboutsummaryrefslogtreecommitdiffstats
path: root/api
diff options
context:
space:
mode:
authorPinapelz <yukais@pinapelz.com>2024-10-13 23:57:45 -0700
committerPinapelz <yukais@pinapelz.com>2024-10-13 23:57:45 -0700
commit6ced144db0441133701cb1982de0137a82a14698 (patch)
tree6fe923480a227f471ecebbe4b8160f20cb3a75ca /api
parente1c4f7ac903df58ae5f63c6f837af9f97426f5ad (diff)
fix server side captcha authentication
Diffstat (limited to 'api')
-rw-r--r--api/app.py26
-rw-r--r--api/static/server_auth.js127
2 files changed, 82 insertions, 71 deletions
diff --git a/api/app.py b/api/app.py
index 01febc2..090525d 100644
--- a/api/app.py
+++ b/api/app.py
@@ -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);
+ });
}
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage