mirror of https://github.com/JohnHammond/CTFd.git
Marking 1.2.0 (#628)
* Mark 1.2.0. * Update CHANGELOG. * Add `window.challenge.data` object. * Don't raise a 500 when an endpoint can't be found but was POST'ed too. Mostly from scanners... * Add test for not found endpoints. * Fixing issue with clearing logo on config update. * Truncate scoreboard team name to 50 characters.selenium-screenshot-testing 1.2.0
parent
36c83b59bc
commit
9cedf456b5
43
CHANGELOG.md
43
CHANGELOG.md
|
@ -1,3 +1,46 @@
|
|||
1.2.0 / 2018-05-04
|
||||
==================
|
||||
|
||||
**General**
|
||||
|
||||
* Updated to Flask 1.0 & switched documentation to suggest using `flask run` instead of `python serve.py`.
|
||||
* Added the ability to make static & regex flags case insensitive.
|
||||
* The `/chals` endpoint no longer lists the details of challenges.
|
||||
* The `/chals/:id` endpoint is now used to load challenge information before display.
|
||||
* Admins can now see what users have solved a given challenge from the admin panel.
|
||||
* Fixed issue with imports extracting files outside of the CTFd directory.
|
||||
* Added import zipfile validation and optional size restriction.
|
||||
* The ctftime, authentication, and admin restrictions have been converted to decorators to improve code reuse.
|
||||
* 403 is now a more common status code. Previously it only indicated CSRF failure, now it can indicate login failure
|
||||
or other Forbidden access situations.
|
||||
* Challenge previews now work consistently instead of occasionally failing to show.
|
||||
* Tests are now randomly ordered with `nose-randomly`.
|
||||
|
||||
**Themes**
|
||||
|
||||
* Admins now have the ability to upload a CTF logo from the config panel.
|
||||
* Switched from the `marked` library to `Markdown-It` for client side markdown rendering.
|
||||
* This will break Challenge type plugins that override the markdown renderer since we are no longer using the marked renderers.
|
||||
* Introduced the `ezpg()` JS function to make it easier to draw a progressbar modal.
|
||||
* Introduced the `$.patch()` AJAX wrapper.
|
||||
* Team names are truncated properly to 50 characters in `teams.html`.
|
||||
* The admin panel now uses Bootstrap badges instead of buttons to indicate properties such as `admin`, `verified`, `visible`.
|
||||
|
||||
**Plugins**
|
||||
|
||||
* Challenge type plugins now use a global challenge object with exposed functions to specify how to display a challenge.
|
||||
(`preRender()`, `render()`, `postRender()`, `submit()`).
|
||||
* Challenge type plugins also have access to window.challenge.data which allow for the previously mentioned functions to
|
||||
process challenge data and change logic accordingly.
|
||||
* Challenge type plugins now get full control over how a challenge is displayed via the nunjucks files.
|
||||
* Challenge plugins should now pass the entire flag/key object to a Custom flag type.
|
||||
* This allows the flag type to make use of the data column to decide how to operate on the flag. This is used to implement
|
||||
case insensitive flags.
|
||||
* Challenge modals (`modal.njk`) now use `{{ description }}` instead of `{{ desc }}` properly aligning with the database schema.
|
||||
* The update and create modals now inject data into the modal via nunjucks instead of client side Javascript.
|
||||
* The `utils.base64decode()` & `utils.base64encode()` functions no longer expose url encoding/decoding parameters.
|
||||
|
||||
|
||||
1.1.4 / 2018-04-05
|
||||
==================
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ if sys.version_info[0] < 3:
|
|||
reload(sys)
|
||||
sys.setdefaultencoding("utf-8")
|
||||
|
||||
__version__ = '1.1.4'
|
||||
__version__ = '1.2.0'
|
||||
|
||||
|
||||
class CTFdFlask(Flask):
|
||||
|
|
|
@ -147,8 +147,8 @@ def admin_config():
|
|||
utils.set_config("mail_username", None)
|
||||
utils.set_config("mail_password", None)
|
||||
|
||||
if request.files.get('ctf_logo', None):
|
||||
ctf_logo = request.files['ctf_logo']
|
||||
if request.files.get('ctf_logo_file', None):
|
||||
ctf_logo = request.files['ctf_logo_file']
|
||||
file_id, file_loc = utils.upload_file(ctf_logo, None)
|
||||
utils.set_config("ctf_logo", file_loc)
|
||||
elif request.form.get('ctf_logo') == '':
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
window.challenge.data = undefined;
|
||||
|
||||
window.challenge.renderer = new markdownit({
|
||||
html: true,
|
||||
});
|
||||
|
|
|
@ -37,6 +37,8 @@ function render_challenge_preview(chal_id){
|
|||
$.get(script_root + obj.type_data.templates.modal, function (template_data) {
|
||||
var template = nunjucks.compile(template_data);
|
||||
|
||||
window.challenge.data = obj;
|
||||
|
||||
window.challenge.preRender()
|
||||
|
||||
obj['description'] = window.challenge.render(obj['description']);
|
||||
|
|
|
@ -55,19 +55,20 @@
|
|||
<img id="ctf_logo_preview" class="img-responsive ctf_logo" src="{{ request.script_root }}/files/{{ ctf_logo }}"
|
||||
height="25">
|
||||
<button type="button" class="btn-sm btn-danger float-right" onclick="
|
||||
$('#ctf_logo').attr('type', 'text');
|
||||
$('#ctf_logo').attr('placeholder', 'Logo will be removed on next update');
|
||||
$('#ctf_logo').attr('value', '');
|
||||
$('#ctf_logo').attr('readonly', 'true');
|
||||
$('#ctf_logo_preview').css('visibility', 'hidden');
|
||||
$('#ctf_logo').attr('placeholder', 'Logo will be removed on next update');
|
||||
$('#ctf_logo').attr('value', '');
|
||||
$('#ctf_logo').attr('readonly', 'true');
|
||||
$('#ctf_logo_preview').css('visibility', 'hidden');
|
||||
$(this).text('Logo will be removed on next update');
|
||||
">
|
||||
Remove Logo
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<input class="form-control" id='ctf_logo' name='ctf_logo' type='file' placeholder="CTF Logo"
|
||||
{% if ctf_logo is defined and ctf_logo != None %}value="{{ ctf_logo }}"{% endif %}>
|
||||
<input class="form-control" id="ctf_logo_file" name='ctf_logo_file' type='file' placeholder="CTF Logo">
|
||||
<input id='ctf_logo' name='ctf_logo' type='hidden' value="{% if ctf_logo is defined %}{{ ctf_logo }}{% endif %}"
|
||||
placeholder="CTF Logo">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
|
|
|
@ -33,6 +33,8 @@ function updateChalWindow(obj) {
|
|||
|
||||
var nonce = $('#nonce').val();
|
||||
|
||||
window.challenge.data = challenge_data;
|
||||
|
||||
window.challenge.preRender();
|
||||
|
||||
challenge_data['description'] = window.challenge.render(challenge_data['description']);
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
{% for team in teams %}
|
||||
<tr>
|
||||
<th scope="row" class="text-center">{{ loop.index }}</th>
|
||||
<td><a href="{{ request.script_root }}/team/{{ team.teamid }}">{{ team.name }}</a></td>
|
||||
<td><a href="{{ request.script_root }}/team/{{ team.teamid }}">{{ team.name | truncate(50) }}</a></td>
|
||||
<td>{{ team.score }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
|
|
@ -192,7 +192,10 @@ def init_utils(app):
|
|||
|
||||
@app.before_request
|
||||
def csrf():
|
||||
func = app.view_functions[request.endpoint]
|
||||
try:
|
||||
func = app.view_functions[request.endpoint]
|
||||
except KeyError:
|
||||
abort(404)
|
||||
if hasattr(func, '_bypass_csrf'):
|
||||
return
|
||||
if not session.get('nonce'):
|
||||
|
|
|
@ -34,7 +34,7 @@ CTFd is a Capture The Flag framework focusing on ease of use and customizability
|
|||
## Install
|
||||
1. Run `./prepare.sh` to install dependencies using apt.
|
||||
2. Modify [CTFd/config.py](https://github.com/CTFd/CTFd/blob/master/CTFd/config.py) to your liking.
|
||||
3. Use `python serve.py` in a terminal to drop into debug mode.
|
||||
3. Use `flask run` in a terminal to drop into debug mode.
|
||||
|
||||
Or you can use Docker with the following command:
|
||||
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
"""Update regex flags to be case_insensitive
|
||||
|
||||
Revision ID: dab615389702
|
||||
Revises: d5a224bf5862
|
||||
Create Date: 2018-05-03 18:18:53.343075
|
||||
|
||||
"""
|
||||
from CTFd.models import db
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import mysql
|
||||
from sqlalchemy.sql import text, table, column, and_
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'dab615389702'
|
||||
down_revision = 'd5a224bf5862'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
keys_table = table('keys',
|
||||
column('id', db.Integer),
|
||||
column('type', db.Text),
|
||||
column('data', db.Text)
|
||||
)
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
connection = op.get_bind()
|
||||
connection.execute(
|
||||
keys_table.update().where(
|
||||
keys_table.c.type == 'regex'
|
||||
).values(
|
||||
data='case_insensitive'
|
||||
)
|
||||
)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
connection = op.get_bind()
|
||||
connection.execute(
|
||||
keys_table.update().where(
|
||||
keys_table.c.type == 'regex'
|
||||
).values(
|
||||
data=None
|
||||
)
|
||||
)
|
||||
# ### end Alembic commands ###
|
|
@ -20,6 +20,18 @@ def test_index():
|
|||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_not_found():
|
||||
"""Should return a 404 for pages that are not found"""
|
||||
app = create_ctfd()
|
||||
with app.app_context():
|
||||
with app.test_client() as client:
|
||||
r = client.get('/this-should-404')
|
||||
assert r.status_code == 404
|
||||
r = client.post('/this-should-404')
|
||||
assert r.status_code == 404
|
||||
destroy_ctfd(app)
|
||||
|
||||
|
||||
def test_page():
|
||||
"""Test that users can access pages that are created in the database"""
|
||||
app = create_ctfd()
|
||||
|
|
Loading…
Reference in New Issue