mirror of
https://github.com/aljazceru/CTFd.git
synced 2025-12-17 14:04:20 +01:00
Loosen team password confirmation to also accept team captain password (#1598)
* Loosen team password confirmation to also accept team captain password * Make team settings modal larger in the core theme * Add help text in team settings form * Closes #1545
This commit is contained in:
@@ -20,12 +20,28 @@ class TeamRegisterForm(BaseForm):
|
|||||||
|
|
||||||
|
|
||||||
class TeamSettingsForm(BaseForm):
|
class TeamSettingsForm(BaseForm):
|
||||||
name = StringField("Team Name")
|
name = StringField(
|
||||||
confirm = PasswordField("Current Password")
|
"Team Name", description="Your team's public name shown to other competitors"
|
||||||
password = PasswordField("Team Password")
|
)
|
||||||
affiliation = StringField("Affiliation")
|
password = PasswordField(
|
||||||
website = URLField("Website")
|
"New Team Password", description="Set a new team join password"
|
||||||
country = SelectField("Country", choices=SELECT_COUNTRIES_LIST)
|
)
|
||||||
|
confirm = PasswordField(
|
||||||
|
"Confirm Password",
|
||||||
|
description="Provide your current team password (or your password) to update your team's password",
|
||||||
|
)
|
||||||
|
affiliation = StringField(
|
||||||
|
"Affiliation",
|
||||||
|
description="Your team's affiliation publicly shown to other competitors",
|
||||||
|
)
|
||||||
|
website = URLField(
|
||||||
|
"Website", description="Your team's website publicly shown to other competitors"
|
||||||
|
)
|
||||||
|
country = SelectField(
|
||||||
|
"Country",
|
||||||
|
choices=SELECT_COUNTRIES_LIST,
|
||||||
|
description="Your team's country publicly shown to other competitors",
|
||||||
|
)
|
||||||
submit = SubmitField("Submit")
|
submit = SubmitField("Submit")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -142,10 +142,13 @@ class TeamSchema(ma.ModelSchema):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if password and confirm:
|
if password and confirm:
|
||||||
test = verify_password(
|
test_team = verify_password(
|
||||||
plaintext=confirm, ciphertext=current_team.password
|
plaintext=confirm, ciphertext=current_team.password
|
||||||
)
|
)
|
||||||
if test is True:
|
test_captain = verify_password(
|
||||||
|
plaintext=confirm, ciphertext=current_user.password
|
||||||
|
)
|
||||||
|
if test_team is True or test_captain is True:
|
||||||
return data
|
return data
|
||||||
else:
|
else:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div id="team-edit-modal" class="modal fade">
|
<div id="team-edit-modal" class="modal fade">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog modal-lg">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h2 class="modal-action text-center w-100">Edit Team</h2>
|
<h2 class="modal-action text-center w-100">Edit Team</h2>
|
||||||
@@ -17,28 +17,46 @@
|
|||||||
{% with form = Forms.teams.TeamSettingsForm(obj=team) %}
|
{% with form = Forms.teams.TeamSettingsForm(obj=team) %}
|
||||||
<form id="team-info-form" method="POST">
|
<form id="team-info-form" method="POST">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
{{ form.name.label }}
|
<b>{{ form.name.label }}</b>
|
||||||
{{ form.name(class="form-control") }}
|
{{ form.name(class="form-control") }}
|
||||||
|
<small class="form-text text-muted">
|
||||||
|
{{ form.name.description }}
|
||||||
|
</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
{{ form.confirm.label }}
|
<b>{{ form.password.label }}</b>
|
||||||
{{ form.confirm(class="form-control") }}
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
{{ form.password.label }}
|
|
||||||
{{ form.password(class="form-control") }}
|
{{ form.password(class="form-control") }}
|
||||||
|
<small class="form-text text-muted">
|
||||||
|
{{ form.password.description }}
|
||||||
|
</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
{{ form.website.label }}
|
<b>{{ form.confirm.label }}</b>
|
||||||
|
{{ form.confirm(class="form-control") }}
|
||||||
|
<small class="form-text text-muted">
|
||||||
|
{{ form.confirm.description }}
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<b>{{ form.website.label }}</b>
|
||||||
{{ form.website(class="form-control") }}
|
{{ form.website(class="form-control") }}
|
||||||
|
<small class="form-text text-muted">
|
||||||
|
{{ form.website.description }}
|
||||||
|
</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
{{ form.affiliation.label }}
|
<b>{{ form.affiliation.label }}</b>
|
||||||
{{ form.affiliation(class="form-control") }}
|
{{ form.affiliation(class="form-control") }}
|
||||||
|
<small class="form-text text-muted">
|
||||||
|
{{ form.affiliation.description }}
|
||||||
|
</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
{{ form.country.label }}
|
<b>{{ form.country.label }}</b>
|
||||||
{{ form.country(class="form-control custom-select") }}
|
{{ form.country(class="form-control custom-select") }}
|
||||||
|
<small class="form-text text-muted">
|
||||||
|
{{ form.country.description }}
|
||||||
|
</small>
|
||||||
</div>
|
</div>
|
||||||
<div id="results">
|
<div id="results">
|
||||||
|
|
||||||
|
|||||||
@@ -633,7 +633,9 @@ def test_api_team_patch_password():
|
|||||||
"""Can a user change their team password /api/v1/teams/me if logged in as the captain"""
|
"""Can a user change their team password /api/v1/teams/me if logged in as the captain"""
|
||||||
app = create_ctfd(user_mode="teams")
|
app = create_ctfd(user_mode="teams")
|
||||||
with app.app_context():
|
with app.app_context():
|
||||||
user1 = gen_user(app.db, name="user1", email="user1@ctfd.io") # ID 2
|
user1 = gen_user(
|
||||||
|
app.db, name="user1", email="user1@ctfd.io", password="captain"
|
||||||
|
) # ID 2
|
||||||
user2 = gen_user(app.db, name="user2", email="user2@ctfd.io") # ID 3
|
user2 = gen_user(app.db, name="user2", email="user2@ctfd.io") # ID 3
|
||||||
team = gen_team(app.db)
|
team = gen_team(app.db)
|
||||||
team.members.append(user1)
|
team.members.append(user1)
|
||||||
@@ -660,16 +662,38 @@ def test_api_team_patch_password():
|
|||||||
is False
|
is False
|
||||||
)
|
)
|
||||||
|
|
||||||
with login_as_user(app, name="user1") as client:
|
with login_as_user(app, name="user1", password="captain") as client:
|
||||||
|
# Test that invalid passwords aren't accepted
|
||||||
|
r = client.patch(
|
||||||
|
"/api/v1/teams/me",
|
||||||
|
json={"confirm": "incorrect_password", "password": "new_password"},
|
||||||
|
)
|
||||||
|
assert r.status_code == 400
|
||||||
|
assert (
|
||||||
|
verify_password(plaintext="new_password", ciphertext=team.password)
|
||||||
|
is False
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test that the team's password is accepted
|
||||||
r = client.patch(
|
r = client.patch(
|
||||||
"/api/v1/teams/me",
|
"/api/v1/teams/me",
|
||||||
json={"confirm": "password", "password": "new_password"},
|
json={"confirm": "password", "password": "new_password"},
|
||||||
)
|
)
|
||||||
assert r.status_code == 200
|
assert r.status_code == 200
|
||||||
|
|
||||||
team = Teams.query.filter_by(id=1).first()
|
team = Teams.query.filter_by(id=1).first()
|
||||||
assert verify_password(plaintext="new_password", ciphertext=team.password)
|
assert verify_password(plaintext="new_password", ciphertext=team.password)
|
||||||
|
|
||||||
|
# Test that the captain's password is also accepted
|
||||||
|
r = client.patch(
|
||||||
|
"/api/v1/teams/me",
|
||||||
|
json={"confirm": "captain", "password": "captain_password"},
|
||||||
|
)
|
||||||
|
assert r.status_code == 200
|
||||||
|
team = Teams.query.filter_by(id=1).first()
|
||||||
|
assert verify_password(
|
||||||
|
plaintext="captain_password", ciphertext=team.password
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_api_accessing_hidden_banned_users():
|
def test_api_accessing_hidden_banned_users():
|
||||||
"""Hidden/Banned users should not be visible to normal users, only to admins"""
|
"""Hidden/Banned users should not be visible to normal users, only to admins"""
|
||||||
|
|||||||
Reference in New Issue
Block a user