101 lines
3.2 KiB
Python
101 lines
3.2 KiB
Python
"""Submission routes - anonymous feedback submission"""
|
|||
|
|
from flask import Blueprint, render_template, request, redirect, url_for, flash, abort
|
||
|
|
from app.models.product import Product
|
||
|
|
from app.services.feedback_storage import FeedbackStorageService
|
||
|
|
from app.utils.file_validator import validate_file, scan_file_for_viruses
|
||
|
|
|
||
|
|
|
||
|
|
bp = Blueprint('submission', __name__, url_prefix='/submit')
|
||
|
|
|
||
|
|
|
||
|
|
@bp.route('/<product_slug>', methods=['GET'])
|
||
|
|
def form(product_slug):
|
||
|
|
"""Display feedback submission form
|
||
|
|
|
||
|
|
Args:
|
||
|
|
product_slug: Product submission URL slug
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
Rendered submission form template or 404
|
||
|
|
"""
|
||
|
|
# Load product by slug
|
||
|
|
product = Product.get_by_slug(product_slug)
|
||
|
|
|
||
|
|
if not product:
|
||
|
|
abort(404, description="Product not found")
|
||
|
|
|
||
|
|
# Check if product is archived
|
||
|
|
if product.is_archived():
|
||
|
|
abort(404, description="This product is no longer accepting feedback")
|
||
|
|
|
||
|
|
return render_template('submission/form.html', product=product)
|
||
|
|
|
||
|
|
|
||
|
|
@bp.route('/<product_slug>', methods=['POST'])
|
||
|
|
def submit(product_slug):
|
||
|
|
"""Process feedback submission
|
||
|
|
|
||
|
|
Args:
|
||
|
|
product_slug: Product submission URL slug
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
Redirect to success page or error page
|
||
|
|
"""
|
||
|
|
# Load product by slug
|
||
|
|
product = Product.get_by_slug(product_slug)
|
||
|
|
|
||
|
|
if not product:
|
||
|
|
abort(404, description="Product not found")
|
||
|
|
|
||
|
|
# Check if product is archived
|
||
|
|
if product.is_archived():
|
||
|
|
abort(404, description="This product is no longer accepting feedback")
|
||
|
|
|
||
|
|
# Get form data
|
||
|
|
feedback_text = request.form.get('feedback_text', '').strip()
|
||
|
|
|
||
|
|
# Get uploaded files
|
||
|
|
uploaded_files = request.files.getlist('files')
|
||
|
|
# Filter out empty file inputs
|
||
|
|
files = [f for f in uploaded_files if f and f.filename != '']
|
||
|
|
|
||
|
|
# Validation: Must provide either text or files
|
||
|
|
if not feedback_text and not files:
|
||
|
|
abort(400, description="Please provide either feedback text or attachments")
|
||
|
|
|
||
|
|
# Validation: Maximum 3 files
|
||
|
|
if len(files) > 3:
|
||
|
|
abort(400, description="Maximum 3 attachments allowed")
|
||
|
|
|
||
|
|
# Validate each file
|
||
|
|
for file in files:
|
||
|
|
is_valid, error_message = validate_file(file)
|
||
|
|
if not is_valid:
|
||
|
|
abort(400, description=error_message)
|
||
|
|
|
||
|
|
# Scan for viruses
|
||
|
|
is_clean, virus_message = scan_file_for_viruses(file)
|
||
|
|
if not is_clean:
|
||
|
|
abort(400, description=f"File rejected: {virus_message}")
|
||
|
|
|
||
|
|
# Save feedback
|
||
|
|
try:
|
||
|
|
feedback = FeedbackStorageService.save_complete_feedback(
|
||
|
|
product_id=product.product_id,
|
||
|
|
content_text=feedback_text if feedback_text else None,
|
||
|
|
files=files if files else None
|
||
|
|
)
|
||
|
|
|
||
|
|
return render_template('submission/success.html',
|
||
|
|
product=product,
|
||
|
|
feedback_id=feedback.feedback_id)
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
# Log error
|
||
|
|
from flask import current_app
|
||
|
|
current_app.logger.error(f"Error saving feedback: {e}")
|
||
|
|
|
||
|
|
return render_template('submission/error.html',
|
||
|
|
product=product,
|
||
|
|
error_message="An error occurred while saving your feedback. Please try again."), 500
|