diff --git a/app/__init__.py b/app/__init__.py
index 2b38c7e..999cabd 100644
--- a/app/__init__.py
+++ b/app/__init__.py
@@ -2,6 +2,7 @@ from flask import Flask
from app.config import Config
from app.extensions import db, mail, limiter
from werkzeug.middleware.proxy_fix import ProxyFix
+import logging
def create_app(config_class=Config):
app = Flask(__name__)
@@ -9,6 +10,10 @@ def create_app(config_class=Config):
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1)
+ gunicorn_logger = logging.getLogger("gunicorn.error")
+ app.logger.handlers = gunicorn_logger.handlers
+ app.logger.setLevel(gunicorn_logger.level)
+
# Initialize extensions
db.init_app(app)
mail.init_app(app)
diff --git a/app/routes.py b/app/routes.py
index e591631..048c6eb 100644
--- a/app/routes.py
+++ b/app/routes.py
@@ -30,6 +30,7 @@ def send_verification_email(user, is_new=True):
msg = Message('Verify your CTF Registration', recipients=[user.email])
msg.html = render_template("email.html", user_name=user.name, register_link=register_link, remove_link=remove_link, logo_url=logo)
mail.send(msg)
+ current_app.logger.info(f"Sent verification email to {user.email}")
user.num_emails_sent += 1
db.session.commit()
if is_new:
@@ -43,8 +44,24 @@ def send_waitlist_email(user):
msg = Message('h4tum CTF 2026 Registration', recipients=[user.email])
logo = url_for('static', filename='h4tum_white.png', _external=True)
msg.html = render_template("waitlist_email.html", logo_url=logo, user_name=user.name)
+ current_app.logger.info(msg)
mail.send(msg)
+def send_waitlist_newsletter():
+ results = db.session.query(Participant.email).filter(Participant.on_waitlist == True).all()
+ waitlist_emails = [r[0] for r in results]
+ logo = url_for('static', filename='h4tum_white.png', _external=True)
+ s = URLSafeTimedSerializer(current_app.config['SECRET_KEY'])
+ for email in waitlist_emails:
+ register_token = s.dumps(email, salt='email-confirm-h4tum-ctf-2025')
+ register_link = url_for('main.verify_email', token=register_token, _external=True)
+ remove_token = s.dumps(email, salt='email-remove-h4tum-ctf-2026')
+ remove_link = url_for('main.remove_registration', token=remove_token, _external=True)
+ msg = Message('h4tum CTF 2026 Free Spot available', recipients=[email])
+ msg.html = render_template("waitlist_maillist_email.html", logo_url=logo, register_link=register_link, remove_link=remove_link)
+ mail.send(msg)
+ current_app.logger.info(f"Sent waitlist newsletter email to {email}")
+
@bp.route('/', methods=['GET', 'POST'])
@limiter.limit("5 per hour", methods=["POST"])
def index():
@@ -109,9 +126,11 @@ def verify_email(token):
if user.confirmed:
return render_template('success.html', message="You are confirmed", discord_link=current_app.config['DISCORD_LINK'], discord_token=user.discord_token)
else:
- return render_template("error.html", error_message="Sorry! The event filled up while you were verifying.")
+ return render_template("error.html", error_message="Sorry! The event filled up while you were claiming the last spot.")
else:
user.confirmed = True
+ if user.on_waitlist:
+ user.on_waitlist = False
db.session.commit()
discord_link = current_app.config['DISCORD_LINK']
@@ -137,16 +156,14 @@ def remove_registration(token):
if not user:
return render_template("error.html", error_message="No user found.")
-
- try:
- db.session.delete(user)
- db.session.commit()
- return render_template("deregistered.html", message="Sad to see you go. Comeback next time :D")
- except:
- db.session.rollback()
- return render_template("error.html", error_message="Removing user did not work")
+ db.session.delete(user)
+ db.session.commit()
+
+ if get_confirmed_count() == current_app.config['MAX_SPOTS'] - 1:
+ send_waitlist_newsletter()
+
+ return render_template("deregistered.html", message="Sad to see you go. Comeback next time :D")
-
@bp.route('/dsgvo')
@limiter.exempt
def dsgvo():
diff --git a/app/templates/waitlist_maillist_email.html b/app/templates/waitlist_maillist_email.html
new file mode 100644
index 0000000..489f63e
--- /dev/null
+++ b/app/templates/waitlist_maillist_email.html
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+ Registration Received
+ |
+
+
+
+ |
+ A spot has just become available for h4tum CTF 2026! Be fast and claim it!
+ |
+
+
+
+ |
+
+ |
+
+
+
+ |
+ If you can not attend anymore / don't want to receive any further emails:
+ |
+
+
+ |
+
+ |
+
+
+ |
+ This email is sent automatically every time a place becomes available. You can unsubscribe by pressing the big red button.
+ |
+
+
+
+ |
+
+
+
+