""" Project: PARTS Website Author: Edward Middleton-Smith Precision And Research Technology Systems Limited Technology: App Routing Feature: Core Routes Description: Initializes the Flask application, sets the configuration based on the environment, and defines two routes (/ and /about) that render templates with the specified titles. """ # IMPORTS # internal from datastores.datastore_base import DataStore_Base from forms.contact import Form_Contact from helpers.helper_app import Helper_App from models.model_view_contact import Model_View_Contact from models.model_view_home import Model_View_Home import lib.argument_validation as av # external from flask import Flask, render_template, jsonify, request, render_template_string, send_from_directory, redirect, url_for, session, Blueprint, current_app, flash from flask_mail import Mail, Message from extensions import db, oauth, mail from urllib.parse import quote_plus, urlencode from authlib.integrations.flask_client import OAuth from authlib.integrations.base_client import OAuthError from urllib.parse import quote, urlparse, parse_qs import json import base64 import hmac import hashlib import datetime from altcha import ChallengeOptions, create_challenge, verify_solution routes_core = Blueprint('routes_core', __name__) @routes_core.route(Model_View_Home.HASH_PAGE_HOME, methods=['GET']) def home(): try: model = Model_View_Home() html_body = render_template('pages/core/_home.html', model = model) except Exception as e: return jsonify(error=str(e)), 403 return html_body @routes_core.route(Model_View_Contact.HASH_PAGE_CONTACT, methods=['GET']) def contact(): try: form = Form_Contact() model = Model_View_Contact(form) html_body = render_template('pages/core/_contact.html', model = model) except Exception as e: return jsonify(error=str(e)), 403 return html_body @routes_core.route(Model_View_Contact.HASH_PAGE_CONTACT, methods=['POST']) def contact_post(): try: form = Form_Contact() Helper_App.console_log(f"Form submitted: {request.form}") Helper_App.console_log(f"ALTCHA data in request: {request.form.get('altcha')}") if form.validate_on_submit(): try: email = form.email.data # CC = form.CC.data # not in use contact_name = form.contact_name.data company_name = form.company_name.data message = form.message.data receive_marketing = form.receive_marketing.data receive_marketing_text = "I would like to receive marketing emails." if receive_marketing else "" # send email mailItem = Message("PARTS Website Contact Us Message", recipients=[current_app.config['MAIL_CONTACT_PUBLIC']]) mailItem.body = f"Dear Lord Edward Middleton-Smith,\n\n{message}\n{receive_marketing_text}\nKind regards,\n{contact_name}\n{company_name}\n{email}" mail.send(mailItem) flash('Thank you for your message. We will get back to you soon!', 'success') return "Submitted." except Exception as e: return f"Error: {e}" print(f"Form validation errors: {form.errors}") return "Invalid. Failed to submit." # html_body = render_template('pages/core/_contact.html', model = model) except Exception as e: return jsonify(error=str(e)), 403 @routes_core.route(Model_View_Contact.HASH_ALTCHA_CREATE_CHALLENGE, methods=['GET']) def create_altcha_challenge(): options = ChallengeOptions( expires = datetime.datetime.now() + datetime.timedelta(hours=1), max_number = 100000, # The maximum random number hmac_key = current_app.config["ALTCHA_SECRET_KEY"], ) challenge = create_challenge(options) print("Challenge created:", challenge) # return jsonify({"challenge": challenge}) return jsonify({ "algorithm": challenge.algorithm, "challenge": challenge.challenge, "salt": challenge.salt, "signature": challenge.signature, }) """ def verify_altcha_signature(payload): "" "Verify the ALTCHA signature"" " if 'algorithm' not in payload or 'signature' not in payload or 'verificationData' not in payload: return False algorithm = payload['algorithm'] signature = payload['signature'] verification_data = payload['verificationData'] # Calculate SHA hash of the verification data if algorithm == 'SHA-256': hash_func = hashlib.sha256 else: # Fallback to SHA-256 if algorithm not specified hash_func = hashlib.sha256 # Calculate the hash of verification_data data_hash = hash_func(verification_data.encode('utf-8')).digest() # Calculate the HMAC signature calculated_signature = hmac.new( current_app.config["ALTCHA_SECRET_KEY"].encode('utf-8'), data_hash, hash_func ).hexdigest() # Compare the calculated signature with the provided signature return hmac.compare_digest(calculated_signature, signature) def create_altcha_dummy_signature(challenge): # Example payload to verify payload = { "algorithm": challenge.algorithm, "challenge": challenge.challenge, "number": 12345, # Example number "salt": challenge.salt, "signature": challenge.signature, } return payload @routes_core.route(Model_View_Contact.HASH_ALTCHA_VERIFY_SOLUTION, methods=['POST']) def verify_altcha_challenge(): payload = request.json ok, err = verify_solution(payload, current_app.config["ALTCHA_SECRET_KEY"], check_expires=True) if err: return jsonify({"error": err}), 400 elif ok: return jsonify({"verified": True}) else: return jsonify({"verified": False}), 403 """