finished dev version
This commit is contained in:
@@ -5,8 +5,10 @@ class Participant(db.Model):
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
name = db.Column(db.String(100), nullable=False)
|
||||
email = db.Column(db.String(120), unique=True, nullable=False)
|
||||
num_emails_sent = db.Column(db.Integer, default=0)
|
||||
looking_for_team = db.Column(db.Boolean, default=False)
|
||||
confirmed = db.Column(db.Boolean, default=False)
|
||||
on_waitlist = db.Column(db.Boolean, default=False)
|
||||
discord_token = db.Column(db.String(16), unique=True)
|
||||
discord_user_id = db.Column(db.String(50))
|
||||
|
||||
|
||||
@@ -9,14 +9,31 @@ bp = Blueprint('main', __name__)
|
||||
def get_confirmed_count():
|
||||
return Participant.query.filter_by(confirmed=True).count()
|
||||
|
||||
def send_verification_email(user_email):
|
||||
def add_user(name, email, looking_for_team, on_waitlist = False):
|
||||
new_user = Participant(name=name, email=email, looking_for_team=looking_for_team)
|
||||
if on_waitlist:
|
||||
new_user.on_waitlist = on_waitlist
|
||||
db.session.add(new_user)
|
||||
db.session.commit()
|
||||
return new_user
|
||||
|
||||
def send_verification_email(user):
|
||||
s = URLSafeTimedSerializer(current_app.config['SECRET_KEY'])
|
||||
token = s.dumps(user_email, salt='email-confirm-h4tum-ctf-2025')
|
||||
token = s.dumps(user.email, salt='email-confirm-h4tum-ctf-2025')
|
||||
link = url_for('main.verify_email', token=token, _external=True)
|
||||
logo = url_for('static', filename='h4tum_white.png', _external=True)
|
||||
|
||||
msg = Message('Verify your CTF Registration', recipients=[user_email])
|
||||
msg.html = render_template("email.html", user_email=user_email, link=link, logo_url=logo)
|
||||
msg = Message('Verify your CTF Registration', recipients=[user.email])
|
||||
msg.html = render_template("email.html", user_name=user.name, link=link, logo_url=logo)
|
||||
mail.send(msg)
|
||||
user.num_emails_sent += 1
|
||||
db.session.commit()
|
||||
return True
|
||||
|
||||
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)
|
||||
mail.send(msg)
|
||||
|
||||
@bp.route('/', methods=['GET', 'POST'])
|
||||
@@ -34,29 +51,35 @@ def index():
|
||||
if not email.endswith(f"@{tum_domain}"):
|
||||
flash(f"Error: You must use a @{tum_domain} email address.", "error")
|
||||
return redirect(url_for('main.index'))
|
||||
|
||||
if confirmed_count >= max_spots:
|
||||
flash("Sorry, the event is full!", "error")
|
||||
return redirect(url_for('main.index'))
|
||||
|
||||
existing_user = Participant.query.filter_by(email=email).first()
|
||||
|
||||
if existing_user:
|
||||
if existing_user.confirmed:
|
||||
flash("You are already registered and confirmed!", "info")
|
||||
elif existing_user.on_waitlist:
|
||||
flash("You are already on the waitlist", "info")
|
||||
else:
|
||||
flash("Confirmation email resent. Please check your inbox.", "info")
|
||||
send_verification_email(email)
|
||||
if existing_user.num_emails_sent < 5:
|
||||
flash("Confirmation email resent. Please check your inbox.", "info")
|
||||
send_verification_email(existing_user)
|
||||
else:
|
||||
flash("Email limit reached", "error")
|
||||
return redirect(url_for('main.index'))
|
||||
else:
|
||||
new_user = add_user(name, email, looking_for_team)
|
||||
|
||||
if confirmed_count < max_spots:
|
||||
send_verification_email(new_user)
|
||||
flash("Registration started! Check your email to confirm your spot.", "success")
|
||||
else:
|
||||
new_user.on_waitlist = True
|
||||
db.session.commit()
|
||||
send_waitlist_email(new_user)
|
||||
flash("The event is already full!\nYou have been placed on the waitlist", "info")
|
||||
return redirect(url_for('main.index'))
|
||||
|
||||
new_user = Participant(name=name, email=email, looking_for_team=looking_for_team)
|
||||
db.session.add(new_user)
|
||||
db.session.commit()
|
||||
|
||||
send_verification_email(email)
|
||||
flash("Registration started! Check your email to confirm your spot.", "success")
|
||||
return redirect(url_for('main.index'))
|
||||
|
||||
return render_template('index.html', spots_left=spots_left)
|
||||
return render_template('index.html', spots_left=spots_left, max_spots=max_spots)
|
||||
|
||||
@bp.route('/verify/<token>')
|
||||
def verify_email(token):
|
||||
|
||||
@@ -45,6 +45,10 @@ footer {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.status {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
h1 { font-size: 1.5rem; word-wrap: break-word; }
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<tr>
|
||||
<td align="center" style="padding-bottom: 30px; font-size: 16px; line-height: 1.5; text-align: center;">
|
||||
Thanks for registering <br>
|
||||
<strong style="color: #00ff00;">{{ user_email }}</strong><br><br>
|
||||
<strong style="color: #00ff00;">{{ user_name }}</strong><br><br>
|
||||
To secure your spot at the event, please confirm your attendance by clicking the button below.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
<hr style="border-color: #333; margin: 30px 0;"></hr>
|
||||
<h1>> Prizes</h1>
|
||||
<ul>
|
||||
<li>1st Place: 100€</li>
|
||||
<li>2nd Place: 75€</li>
|
||||
<li>3rd Place: 50€</li>
|
||||
<li>1st Place: 150€</li>
|
||||
<li>2nd Place: 110€</li>
|
||||
<li>3rd Place: 75€</li>
|
||||
</ul>
|
||||
<hr style="border-color: #333; margin: 30px 0;"></hr>
|
||||
<h1>> Format</h1>
|
||||
@@ -76,26 +76,27 @@
|
||||
{% endwith %}
|
||||
|
||||
<div class="status">
|
||||
<h2>Spots Remaining: {{ spots_left }} / 84</h2>
|
||||
{% if spots_left > 0 %}
|
||||
<h2>Spots Remaining: {{ spots_left }} / {{max_spots}}</h2>
|
||||
{% else %}
|
||||
<h2>Register for Waitlist</h2>
|
||||
<p>This event is currently full. Join the queue to be notified of openings.</p>
|
||||
{%endif %}
|
||||
</div>
|
||||
|
||||
{% if spots_left > 0 %}
|
||||
<form method="POST">
|
||||
<label>Name</label>
|
||||
<input type="text" name="name" required>
|
||||
<form method="POST">
|
||||
<label>Name</label>
|
||||
<input type="text" name="name" required>
|
||||
|
||||
<label>TUM Email</label>
|
||||
<input type="email" name="email" placeholder="@tum.de" required>
|
||||
<label>TUM Email</label>
|
||||
<input type="email" name="email" placeholder="@tum.de" required>
|
||||
|
||||
<label style="display:block; margin: 20px 0; line-height: 1.4;">
|
||||
<input type="checkbox" name="looking_for_team" style="transform: scale(1.2); margin-right: 10px;">
|
||||
I need a team / looking for group
|
||||
</label>
|
||||
<label style="display:block; margin: 20px 0; line-height: 1.4;">
|
||||
<input type="checkbox" name="looking_for_team" style="transform: scale(1.2); margin-right: 10px;">
|
||||
I need a team / looking for group
|
||||
</label>
|
||||
|
||||
<button type="submit">INITIALIZE_REGISTRATION</button>
|
||||
</form>
|
||||
{% else %}
|
||||
<h2 style="color:red">EVENT FULL</h2>
|
||||
{% endif %}
|
||||
</div>
|
||||
<button type="submit">INITIALIZE_REGISTRATION</button>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
<li>If something feels unintentionally easy, please report it.</li>
|
||||
<li>Do not share flags or solutions with other teams. We will not tolerate flag sharing.</li>
|
||||
<li>Each team may register only once, and each person may belong to only one team.</li>
|
||||
<li>A team has at maximum four members</li>
|
||||
<li>Only TUM Students are permitted to participate in the CTF.</li>
|
||||
<li>Attacking personnel, including participants and non-participants, or the competition system itself is forbidden.</li>
|
||||
<li>Every participant has to follow the Code of Conduct.</li>
|
||||
|
||||
39
app/templates/waitlist_email.html
Normal file
39
app/templates/waitlist_email.html
Normal file
@@ -0,0 +1,39 @@
|
||||
<html>
|
||||
<body style="margin: 0; padding: 0; background-color: #1a1a1a; font-family: 'Courier New', Courier, monospace; color: #ffffff;">
|
||||
<table width="100%" border="0" cellspacing="0" cellpadding="0" style="background-color: #1a1a1a; padding: 20px;">
|
||||
<tr>
|
||||
<td align="center">
|
||||
<table width="100%" border="0" cellspacing="0" cellpadding="0" style="max-width: 600px; background-color: #222222; border: 1px solid #00ff00; padding: 30px;">
|
||||
|
||||
<tr>
|
||||
<td align="center" style="padding-bottom: 20px;">
|
||||
<img src="{{ logo_url }}" alt="Club Logo" width="150" style="display: block; border: 0;">
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td align="center" style="padding-bottom: 20px;">
|
||||
<h1 style="color: #00ff00; font-size: 24px; margin: 0; text-transform: uppercase; text-align: center;">Registration Received</h1>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td align="center" style="padding-bottom: 30px; font-size: 16px; line-height: 1.5; text-align: center;">
|
||||
Thanks for registering <br>
|
||||
<strong style="color: #00ff00;">{{ user_name }}</strong><br><br>
|
||||
At this time, the event has reached maximum capacity. Your name has been placed on a waiting list; we will contact you in the event of any cancellations.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td align="center" style="padding-top: 20px; border-top: 1px solid #333333; font-size: 12px; color: #888888; text-align: center;">
|
||||
If you didn't request this, you can safely ignore this email.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user