Added logging, handled secrets better
This commit is contained in:
parent
197ae8d75b
commit
d8ceb50e9f
4 changed files with 69 additions and 29 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -1 +1,5 @@
|
||||||
credentials.json
|
credentials.json
|
||||||
|
.venv/
|
||||||
|
*.pyc
|
||||||
|
__pycache__/
|
||||||
|
.env
|
||||||
34
app.py
34
app.py
|
|
@ -2,11 +2,31 @@ import os
|
||||||
import yaml
|
import yaml
|
||||||
import gspread
|
import gspread
|
||||||
import secrets
|
import secrets
|
||||||
|
import logging
|
||||||
|
import sys
|
||||||
from flask import Flask, render_template, request, redirect, url_for, abort, session
|
from flask import Flask, render_template, request, redirect, url_for, abort, session
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
# Configure logging for Docker/Portainer
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.INFO,
|
||||||
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
||||||
|
handlers=[logging.StreamHandler(sys.stdout)]
|
||||||
|
)
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
app.secret_key = os.environ.get('SECRET_KEY', secrets.token_hex(32))
|
|
||||||
|
# Fail-fast secret requirement (allow bypass for pytest testing)
|
||||||
|
secret_key = os.environ.get('SECRET_KEY')
|
||||||
|
if not secret_key:
|
||||||
|
if os.environ.get('TESTING_NO_APPEND') or 'pytest' in sys.modules:
|
||||||
|
secret_key = 'test_secret_bypassed'
|
||||||
|
else:
|
||||||
|
logger.critical("No SECRET_KEY set! Exiting. Set it in .env or Portainer Stack secrets.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
app.secret_key = secret_key
|
||||||
|
|
||||||
def generate_csrf_token():
|
def generate_csrf_token():
|
||||||
if '_csrf_token' not in session:
|
if '_csrf_token' not in session:
|
||||||
|
|
@ -40,7 +60,7 @@ def get_google_sheet(sheet_id, tab_name=None):
|
||||||
# Default to first tab
|
# Default to first tab
|
||||||
return sh.sheet1
|
return sh.sheet1
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error connecting to Google Sheet (ID: {sheet_id}, Tab: {tab_name}): {e}")
|
logger.error(f"Error connecting to Google Sheet (ID: {sheet_id}, Tab: {tab_name}): {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# NEW: Fetch and filter participants for public display
|
# NEW: Fetch and filter participants for public display
|
||||||
|
|
@ -82,7 +102,7 @@ def get_public_participants(sheet_id, tab_name=None):
|
||||||
|
|
||||||
return public_list
|
return public_list
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error fetching participants: {e}")
|
logger.error(f"Error fetching participants: {e}")
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
|
|
@ -146,9 +166,15 @@ def event_form(event_slug):
|
||||||
sheet = get_google_sheet(sheet_id, tab_name)
|
sheet = get_google_sheet(sheet_id, tab_name)
|
||||||
if sheet:
|
if sheet:
|
||||||
if not os.environ.get('TESTING_NO_APPEND'):
|
if not os.environ.get('TESTING_NO_APPEND'):
|
||||||
sheet.append_row(form_data)
|
try:
|
||||||
|
sheet.append_row(form_data)
|
||||||
|
logger.info(f"Successfully appended registration for {form_data[7]} to {tab_name}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to append row to {tab_name}: {e}")
|
||||||
|
return f"Error appending data. Try again later."
|
||||||
return redirect(url_for('success', event_slug=event_slug))
|
return redirect(url_for('success', event_slug=event_slug))
|
||||||
else:
|
else:
|
||||||
|
logger.error(f"Could not connect to tab '{tab_name}' during POST.")
|
||||||
return f"Error: Could not connect to Google Sheet Tab '{tab_name}'. Check server logs."
|
return f"Error: Could not connect to Google Sheet Tab '{tab_name}'. Check server logs."
|
||||||
|
|
||||||
# GET Request: Fetch participants to show at bottom of form
|
# GET Request: Fetch participants to show at bottom of form
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ services:
|
||||||
build: .
|
build: .
|
||||||
container_name: sailing_forms
|
container_name: sailing_forms
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
ports:
|
ports:
|
||||||
- "5000:5000"
|
- "5000:5000"
|
||||||
volumes:
|
volumes:
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,37 @@
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import pytest
|
import pytest
|
||||||
from playwright.sync_api import Page, expect
|
from playwright.sync_api import sync_playwright, expect
|
||||||
|
|
||||||
def test_homepage_has_title(page: Page):
|
def test_homepage_has_title():
|
||||||
page.goto("http://localhost:5000/")
|
with sync_playwright() as p:
|
||||||
expect(page).to_have_title(re.compile("Zeilwedstrijden"))
|
browser = p.chromium.launch()
|
||||||
|
page = browser.new_page()
|
||||||
|
page.goto("http://localhost:5000/")
|
||||||
|
expect(page).to_have_title(re.compile("Zeilwedstrijden"))
|
||||||
|
browser.close()
|
||||||
|
|
||||||
def test_submission_flow(page: Page):
|
def test_submission_flow():
|
||||||
page.goto("http://localhost:5000/zomeravond")
|
with sync_playwright() as p:
|
||||||
|
browser = p.chromium.launch()
|
||||||
# Fill required fields
|
page = browser.new_page()
|
||||||
page.select_option("select[name='klasse']", label="Kajuitklasse")
|
page.goto("http://localhost:5000/zomeravond")
|
||||||
page.fill("input[name='zeilnummer']", "42")
|
|
||||||
page.fill("input[name='bootnaam']", "Vliegende Hollander")
|
# Fill required fields
|
||||||
page.fill("input[name='naam']", "Hendrik Test")
|
page.select_option("select[name='klasse']", label="Kajuitklasse")
|
||||||
page.fill("input[name='telefoonmobiel']", "0612345678")
|
page.fill("input[name='zeilnummer']", "42")
|
||||||
page.fill("input[name='email']", "hendrik@example.com")
|
page.fill("input[name='bootnaam']", "Vliegende Hollander")
|
||||||
|
page.fill("input[name='naam']", "Hendrik Test")
|
||||||
# Accept terms
|
page.fill("input[name='telefoonmobiel']", "0612345678")
|
||||||
page.check("input#terms")
|
page.fill("input[name='email']", "hendrik@example.com")
|
||||||
|
|
||||||
# Submit
|
# Accept terms
|
||||||
page.click("button[type='submit']")
|
page.check("input#terms")
|
||||||
|
|
||||||
# Expect success redirect
|
# Submit
|
||||||
expect(page).to_have_url(re.compile(r".*/zomeravond/success"))
|
page.click("button[type='submit']")
|
||||||
expect(page.locator("h1")).to_have_text("Bedankt!")
|
|
||||||
|
# Expect success redirect
|
||||||
|
expect(page).to_have_url(re.compile(r".*/zomeravond/success"))
|
||||||
|
expect(page.locator("h1")).to_have_text("Bedankt!")
|
||||||
|
browser.close()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue