103 lines
3.6 KiB
Python
103 lines
3.6 KiB
Python
"""
|
|
Project: PARTS Website
|
|
Author: Edward Middleton-Smith
|
|
Precision And Research Technology Systems Limited
|
|
|
|
Technology: Backend
|
|
Feature: Contact Us Form
|
|
|
|
Description:
|
|
Defines Flask-WTF form for handling user input on Contact Us page.
|
|
"""
|
|
|
|
# IMPORTS
|
|
# internal
|
|
from business_objects.base import Base
|
|
from business_objects.project_hub.contact_form import Contact_Form
|
|
# from models.model_view_store import Model_View_Store # circular
|
|
from models.model_view_base import Model_View_Base
|
|
from forms.base import Form_Base
|
|
# external
|
|
from flask import Flask, render_template, request, flash, redirect, url_for, current_app
|
|
from flask_wtf import FlaskForm
|
|
from wtforms import StringField, TextAreaField, SubmitField, HiddenField, BooleanField, Field, EmailField
|
|
from wtforms.validators import DataRequired, Email, ValidationError
|
|
import markupsafe
|
|
from flask_wtf.recaptcha import RecaptchaField
|
|
from abc import ABCMeta, abstractmethod
|
|
import json
|
|
from altcha import verify_solution
|
|
import base64
|
|
|
|
class AltchaValidator:
|
|
def __init__(self, message=None):
|
|
self.message = message or 'ALTCHA verification failed'
|
|
|
|
def __call__(self, form, field):
|
|
altcha_data = field.data
|
|
|
|
return True
|
|
|
|
if not altcha_data:
|
|
raise ValidationError(self.message)
|
|
|
|
try:
|
|
# The data is base64 encoded JSON
|
|
try:
|
|
# First try to decode it as JSON directly (if it's not base64 encoded)
|
|
altcha_payload = json.loads(altcha_data)
|
|
except json.JSONDecodeError:
|
|
# If direct JSON decoding fails, try base64 decoding first
|
|
decoded_data = base64.b64decode(altcha_data).decode('utf-8')
|
|
altcha_payload = json.loads(decoded_data)
|
|
|
|
ok, err = verify_solution(altcha_payload, current_app.app_config.ALTCHA_SECRET_KEY, check_expires=True)
|
|
|
|
if err or not ok:
|
|
raise ValidationError(self.message + ': ' + (err or 'Invalid solution'))
|
|
|
|
except Exception as e:
|
|
raise ValidationError(f'Invalid ALTCHA data: {str(e)}')
|
|
|
|
class AltchaField(Field):
|
|
def __init__(self, label='', validators=None, **kwargs):
|
|
validators = validators or []
|
|
validators.append(AltchaValidator())
|
|
|
|
super(AltchaField, self).__init__(label, validators, **kwargs)
|
|
|
|
def __call__(self, **kwargs):
|
|
html = f"""
|
|
<altcha-widget
|
|
challengeurl="/get-challenge"
|
|
auto="onload"
|
|
id="{self.id}"
|
|
name="{self.name}">
|
|
</altcha-widget>
|
|
"""
|
|
return markupsafe.Markup(html)
|
|
|
|
|
|
class Form_Contact(FlaskForm):
|
|
email = EmailField('Email')
|
|
contact_name = StringField('Name')
|
|
company_name = StringField('Company')
|
|
message = TextAreaField('Message')
|
|
receive_marketing = BooleanField('I would like to receive marketing emails.')
|
|
# recaptcha = RecaptchaField()
|
|
# altcha = HiddenField('ALTCHA') # , validators=[validate_altcha]
|
|
altcha = AltchaField('Verify you are human')
|
|
submit = SubmitField('Send Message')
|
|
|
|
def to_json(self):
|
|
return {
|
|
Base.FLAG_EMAIL: self.email.data
|
|
, Contact_Form.FLAG_NAME_CONTACT: self.contact_name.data
|
|
, Contact_Form.FLAG_NAME_COMPANY: self.company_name.data
|
|
, Contact_Form.FLAG_MESSAGE: self.message.data
|
|
, Contact_Form.FLAG_RECEIVE_MARKETING_COMMUNICATIONS: self.receive_marketing.data
|
|
, Contact_Form.FLAG_ALTCHA: self.altcha.data
|
|
, Base.FLAG_ACTIVE: True
|
|
, Base.FLAG_CREATED_ON: None
|
|
}
|