mirror of
https://github.com/aljazceru/CTFd.git
synced 2025-12-17 22:14:25 +01:00
Some 2.1.0a1 bugfixes (#959)
* Fix admin's modifying their own team or own settings * Fix some links not working in the admin panel * Fix extensions with an extra space in `populate.py`
This commit is contained in:
@@ -54,6 +54,7 @@ class TeamSchema(ma.ModelSchema):
|
|||||||
return
|
return
|
||||||
|
|
||||||
existing_team = Teams.query.filter_by(name=name).first()
|
existing_team = Teams.query.filter_by(name=name).first()
|
||||||
|
current_team = get_current_team()
|
||||||
# Admins should be able to patch anyone but they cannot cause a collision.
|
# Admins should be able to patch anyone but they cannot cause a collision.
|
||||||
if is_admin():
|
if is_admin():
|
||||||
team_id = int(data.get('id', 0))
|
team_id = int(data.get('id', 0))
|
||||||
@@ -63,9 +64,12 @@ class TeamSchema(ma.ModelSchema):
|
|||||||
else:
|
else:
|
||||||
# If there's no Team ID it means that the admin is creating a team with no ID.
|
# If there's no Team ID it means that the admin is creating a team with no ID.
|
||||||
if existing_team:
|
if existing_team:
|
||||||
|
if current_team:
|
||||||
|
if current_team.id != existing_team.id:
|
||||||
|
raise ValidationError('Team name has already been taken', field_names=['name'])
|
||||||
|
else:
|
||||||
raise ValidationError('Team name has already been taken', field_names=['name'])
|
raise ValidationError('Team name has already been taken', field_names=['name'])
|
||||||
else:
|
else:
|
||||||
current_team = get_current_team()
|
|
||||||
# We need to allow teams to edit themselves and allow the "conflict"
|
# We need to allow teams to edit themselves and allow the "conflict"
|
||||||
if data['name'] == current_team.name:
|
if data['name'] == current_team.name:
|
||||||
return data
|
return data
|
||||||
@@ -135,7 +139,10 @@ class TeamSchema(ma.ModelSchema):
|
|||||||
|
|
||||||
if is_admin():
|
if is_admin():
|
||||||
team_id = data.get('id')
|
team_id = data.get('id')
|
||||||
|
if team_id:
|
||||||
target_team = Teams.query.filter_by(id=team_id).first()
|
target_team = Teams.query.filter_by(id=team_id).first()
|
||||||
|
else:
|
||||||
|
target_team = get_current_team()
|
||||||
captain = Users.query.filter_by(id=captain_id).first()
|
captain = Users.query.filter_by(id=captain_id).first()
|
||||||
if captain in target_team.members:
|
if captain in target_team.members:
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ class UserSchema(ma.ModelSchema):
|
|||||||
return
|
return
|
||||||
|
|
||||||
existing_user = Users.query.filter_by(name=name).first()
|
existing_user = Users.query.filter_by(name=name).first()
|
||||||
|
current_user = get_current_user()
|
||||||
if is_admin():
|
if is_admin():
|
||||||
user_id = data.get('id')
|
user_id = data.get('id')
|
||||||
if user_id:
|
if user_id:
|
||||||
@@ -69,9 +70,12 @@ class UserSchema(ma.ModelSchema):
|
|||||||
raise ValidationError('User name has already been taken', field_names=['name'])
|
raise ValidationError('User name has already been taken', field_names=['name'])
|
||||||
else:
|
else:
|
||||||
if existing_user:
|
if existing_user:
|
||||||
|
if current_user:
|
||||||
|
if current_user.id != existing_user.id:
|
||||||
|
raise ValidationError('User name has already been taken', field_names=['name'])
|
||||||
|
else:
|
||||||
raise ValidationError('User name has already been taken', field_names=['name'])
|
raise ValidationError('User name has already been taken', field_names=['name'])
|
||||||
else:
|
else:
|
||||||
current_user = get_current_user()
|
|
||||||
if name == current_user.name:
|
if name == current_user.name:
|
||||||
return data
|
return data
|
||||||
else:
|
else:
|
||||||
@@ -88,7 +92,7 @@ class UserSchema(ma.ModelSchema):
|
|||||||
return
|
return
|
||||||
|
|
||||||
existing_user = Users.query.filter_by(email=email).first()
|
existing_user = Users.query.filter_by(email=email).first()
|
||||||
|
current_user = get_current_user()
|
||||||
if is_admin():
|
if is_admin():
|
||||||
user_id = data.get('id')
|
user_id = data.get('id')
|
||||||
if user_id:
|
if user_id:
|
||||||
@@ -96,9 +100,12 @@ class UserSchema(ma.ModelSchema):
|
|||||||
raise ValidationError('Email address has already been used', field_names=['email'])
|
raise ValidationError('Email address has already been used', field_names=['email'])
|
||||||
else:
|
else:
|
||||||
if existing_user:
|
if existing_user:
|
||||||
|
if current_user:
|
||||||
|
if current_user.id != existing_user.id:
|
||||||
|
raise ValidationError('Email address has already been used', field_names=['email'])
|
||||||
|
else:
|
||||||
raise ValidationError('Email address has already been used', field_names=['email'])
|
raise ValidationError('Email address has already been used', field_names=['email'])
|
||||||
else:
|
else:
|
||||||
current_user = get_current_user()
|
|
||||||
if email == current_user.email:
|
if email == current_user.email:
|
||||||
return data
|
return data
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -36,5 +36,9 @@ $(function () {
|
|||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("tr a, button").click(function (e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
});
|
||||||
|
|
||||||
$('[data-toggle="tooltip"]').tooltip()
|
$('[data-toggle="tooltip"]').tooltip()
|
||||||
});
|
});
|
||||||
@@ -138,7 +138,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
<a href="mailto:{{ member.email }}">
|
<a href="mailto:{{ member.email }}" target="_blank">
|
||||||
{{ member.email }}
|
{{ member.email }}
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="modal-body clearfix">
|
<div class="modal-body clearfix">
|
||||||
<form id="team-info-form" method="POST">
|
<form id="team-info-form" method="POST">
|
||||||
<input type="hidden" name="id">
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="name">Team Name</label>
|
<label for="name">Team Name</label>
|
||||||
<input type="text" class="form-control" name="name" id="name"
|
<input type="text" class="form-control" name="name" id="name"
|
||||||
|
|||||||
16
populate.py
16
populate.py
@@ -168,20 +168,20 @@ emails = [
|
|||||||
]
|
]
|
||||||
extensions = [
|
extensions = [
|
||||||
'.doc', '.log', '.msg', '.rtf', '.txt', '.wpd', '.wps', '.123',
|
'.doc', '.log', '.msg', '.rtf', '.txt', '.wpd', '.wps', '.123',
|
||||||
'.csv', '.dat', '.db ', '.dll', '.mdb', '.pps', '.ppt', '.sql',
|
'.csv', '.dat', '.db', '.dll', '.mdb', '.pps', '.ppt', '.sql',
|
||||||
'.wks', '.xls', '.xml', '.mng', '.pct', '.bmp', '.gif', '.jpe',
|
'.wks', '.xls', '.xml', '.mng', '.pct', '.bmp', '.gif', '.jpe',
|
||||||
'.jpg', '.png', '.psd', '.psp', '.tif', '.ai ', '.drw', '.dxf',
|
'.jpg', '.png', '.psd', '.psp', '.tif', '.ai', '.drw', '.dxf',
|
||||||
'.eps', '.ps ', '.svg', '.3dm', '.3dm', '.ind', '.pdf', '.qxd',
|
'.eps', '.ps', '.svg', '.3dm', '.3dm', '.ind', '.pdf', '.qxd',
|
||||||
'.qxp', '.aac', '.aif', '.iff', '.m3u', '.mid', '.mid', '.mp3',
|
'.qxp', '.aac', '.aif', '.iff', '.m3u', '.mid', '.mid', '.mp3',
|
||||||
'.mpa', '.ra ', '.ram', '.wav', '.wma', '.3gp', '.asf', '.asx',
|
'.mpa', '.ra', '.ram', '.wav', '.wma', '.3gp', '.asf', '.asx',
|
||||||
'.avi', '.mov', '.mp4', '.mpg', '.qt ', '.rm ', '.swf', '.wmv',
|
'.avi', '.mov', '.mp4', '.mpg', '.qt', '.rm', '.swf', '.wmv',
|
||||||
'.asp', '.css', '.htm', '.htm', '.js ', '.jsp', '.php', '.xht',
|
'.asp', '.css', '.htm', '.htm', '.js', '.jsp', '.php', '.xht',
|
||||||
'.fnt', '.fon', '.otf', '.ttf', '.8bi', '.plu', '.xll', '.cab',
|
'.fnt', '.fon', '.otf', '.ttf', '.8bi', '.plu', '.xll', '.cab',
|
||||||
'.cpl', '.cur', '.dmp', '.drv', '.key', '.lnk', '.sys', '.cfg',
|
'.cpl', '.cur', '.dmp', '.drv', '.key', '.lnk', '.sys', '.cfg',
|
||||||
'.ini', '.reg', '.app', '.bat', '.cgi', '.com', '.exe', '.pif',
|
'.ini', '.reg', '.app', '.bat', '.cgi', '.com', '.exe', '.pif',
|
||||||
'.vb ', '.ws ', '.deb', '.gz ', '.pkg', '.rar', '.sea', '.sit',
|
'.vb', '.ws', '.deb', '.gz', '.pkg', '.rar', '.sea', '.sit',
|
||||||
'.sit', '.zip', '.bin', '.hqx', '.0 E', '.mim', '.uue', '.cpp',
|
'.sit', '.zip', '.bin', '.hqx', '.0 E', '.mim', '.uue', '.cpp',
|
||||||
'.jav', '.pl ', '.bak', '.gho', '.old', '.ori', '.tmp', '.dmg',
|
'.jav', '.pl', '.bak', '.gho', '.old', '.ori', '.tmp', '.dmg',
|
||||||
'.iso', '.toa', '.vcd', '.gam', '.nes', '.rom', '.sav', '.msi',
|
'.iso', '.toa', '.vcd', '.gam', '.nes', '.rom', '.sav', '.msi',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -345,6 +345,35 @@ def test_api_team_patch_me_logged_in_captain():
|
|||||||
destroy_ctfd(app)
|
destroy_ctfd(app)
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_team_patch_me_logged_in_admin_captain():
|
||||||
|
"""Can an admin patch /api/v1/teams/me if logged in as a team captain"""
|
||||||
|
app = create_ctfd(user_mode="teams")
|
||||||
|
with app.app_context():
|
||||||
|
admin = Users.query.filter_by(id=1).first()
|
||||||
|
user = gen_user(app.db)
|
||||||
|
team = gen_team(app.db)
|
||||||
|
team.members.append(user)
|
||||||
|
team.members.append(admin)
|
||||||
|
|
||||||
|
user.team_id = team.id
|
||||||
|
admin.team_id = team.id
|
||||||
|
|
||||||
|
# We want the admin to be the captain
|
||||||
|
team.captain_id = 1
|
||||||
|
|
||||||
|
app.db.session.commit()
|
||||||
|
with login_as_user(app, name="admin") as client:
|
||||||
|
r = client.patch('/api/v1/teams/me', json={
|
||||||
|
"name": "team_name",
|
||||||
|
"affiliation": "changed"
|
||||||
|
})
|
||||||
|
assert r.status_code == 200
|
||||||
|
|
||||||
|
team = Teams.query.filter_by(id=1).first()
|
||||||
|
assert team.name == "team_name"
|
||||||
|
destroy_ctfd(app)
|
||||||
|
|
||||||
|
|
||||||
def test_api_team_get_me_solves_not_logged_in():
|
def test_api_team_get_me_solves_not_logged_in():
|
||||||
"""Can a user get /api/v1/teams/me/solves if not logged in"""
|
"""Can a user get /api/v1/teams/me/solves if not logged in"""
|
||||||
app = create_ctfd(user_mode="teams")
|
app = create_ctfd(user_mode="teams")
|
||||||
|
|||||||
@@ -381,6 +381,30 @@ def test_api_user_patch_me_logged_in():
|
|||||||
destroy_ctfd(app)
|
destroy_ctfd(app)
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_admin_user_patch_me_logged_in():
|
||||||
|
"""Can an admin patch /api/v1/users/me"""
|
||||||
|
app = create_ctfd()
|
||||||
|
with app.app_context():
|
||||||
|
with login_as_user(app, name='admin') as client:
|
||||||
|
r = client.patch(
|
||||||
|
'/api/v1/users/me',
|
||||||
|
json={
|
||||||
|
"name": "user",
|
||||||
|
"email": "user@ctfd.io",
|
||||||
|
"password": "password",
|
||||||
|
"confirm": "password",
|
||||||
|
"country": "US"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
assert r.status_code == 200
|
||||||
|
assert r.get_json()['data']['country'] == 'US'
|
||||||
|
|
||||||
|
user = Users.query.filter_by(id=1).first()
|
||||||
|
assert user.name == 'user'
|
||||||
|
assert user.email == 'user@ctfd.io'
|
||||||
|
destroy_ctfd(app)
|
||||||
|
|
||||||
|
|
||||||
def test_api_user_change_name():
|
def test_api_user_change_name():
|
||||||
"""Can a user change their name via the API"""
|
"""Can a user change their name via the API"""
|
||||||
app = create_ctfd()
|
app = create_ctfd()
|
||||||
|
|||||||
Reference in New Issue
Block a user