Render hints on server side and don't render them client side (#1564)

* Render hints on the server side inline with challenge descriptions and Pages
* Clean up some of the API responses for hints to include the right data
* Closes #1563
This commit is contained in:
Kevin Chung
2020-07-22 16:04:45 -04:00
committed by GitHub
parent bea74c2068
commit ded612d46b
10 changed files with 20 additions and 25 deletions

View File

@@ -68,7 +68,7 @@ class HintList(Resource):
filters = build_model_filters(model=Hints, query=q, field=field) filters = build_model_filters(model=Hints, query=q, field=field)
hints = Hints.query.filter_by(**query_args).filter(*filters).all() hints = Hints.query.filter_by(**query_args).filter(*filters).all()
response = HintSchema(many=True).dump(hints) response = HintSchema(many=True, view="locked").dump(hints)
if response.errors: if response.errors:
return {"success": False, "errors": response.errors}, 400 return {"success": False, "errors": response.errors}, 400
@@ -88,7 +88,7 @@ class HintList(Resource):
) )
def post(self): def post(self):
req = request.get_json() req = request.get_json()
schema = HintSchema("admin") schema = HintSchema(view="admin")
response = schema.load(req, session=db.session) response = schema.load(req, session=db.session)
if response.errors: if response.errors:
@@ -155,7 +155,7 @@ class Hint(Resource):
hint = Hints.query.filter_by(id=hint_id).first_or_404() hint = Hints.query.filter_by(id=hint_id).first_or_404()
req = request.get_json() req = request.get_json()
schema = HintSchema() schema = HintSchema(view="admin")
response = schema.load(req, instance=hint, partial=True, session=db.session) response = schema.load(req, instance=hint, partial=True, session=db.session)
if response.errors: if response.errors:

View File

@@ -134,6 +134,13 @@ class Hints(db.Model):
def description(self): def description(self):
return "Hint for {name}".format(name=self.challenge.name) return "Hint for {name}".format(name=self.challenge.name)
@property
def html(self):
from CTFd.utils.config.pages import build_html
from CTFd.utils.helpers import markup
return markup(build_html(self.content))
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(Hints, self).__init__(**kwargs) super(Hints, self).__init__(**kwargs)

View File

@@ -1,12 +1,4 @@
CTFd.plugin.run((_CTFd) => { CTFd.plugin.run((_CTFd) => {
const $ = _CTFd.lib.$ const $ = _CTFd.lib.$
const md = _CTFd.lib.markdown() const md = _CTFd.lib.markdown()
$('a[href="#new-desc-preview"]').on('shown.bs.tab', function (event) {
if (event.target.hash == '#new-desc-preview') {
var editor_value = $('#new-desc-editor').val();
$(event.target.hash).html(
md.render(editor_value)
);
}
});
}) })

View File

@@ -6,12 +6,12 @@ class HintSchema(ma.ModelSchema):
class Meta: class Meta:
model = Hints model = Hints
include_fk = True include_fk = True
dump_only = ("id", "type") dump_only = ("id", "type", "html")
views = { views = {
"locked": ["id", "type", "challenge", "cost"], "locked": ["id", "type", "challenge", "cost"],
"unlocked": ["id", "type", "challenge", "content", "cost"], "unlocked": ["id", "type", "challenge", "content", "html", "cost"],
"admin": ["id", "type", "challenge", "content", "cost", "requirements"], "admin": ["id", "type", "challenge", "content", "html", "cost", "requirements"],
} }
def __init__(self, view=None, *args, **kwargs): def __init__(self, view=None, *args, **kwargs):

View File

@@ -23,12 +23,10 @@ import {
flagTypeSelect flagTypeSelect
} from "../challenges/flags"; } from "../challenges/flags";
const md = CTFd.lib.markdown();
const displayHint = data => { const displayHint = data => {
ezAlert({ ezAlert({
title: "Hint", title: "Hint",
body: md.render(data.content), body: data.html,
button: "Got it!" button: "Got it!"
}); });
}; };

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -12,8 +12,6 @@ const api_func = {
users: x => CTFd.api.get_user_solves({ userId: x }) users: x => CTFd.api.get_user_solves({ userId: x })
}; };
const md = CTFd.lib.markdown();
CTFd._internal.challenge = {}; CTFd._internal.challenge = {};
let challenges = []; let challenges = [];
let solves = []; let solves = [];
@@ -393,7 +391,7 @@ setInterval(update, 300000); // Update every 5 minutes.
const displayHint = data => { const displayHint = data => {
ezAlert({ ezAlert({
title: "Hint", title: "Hint",
body: md.render(data.content), body: data.html,
button: "Got it!" button: "Got it!"
}); });
}; };
@@ -418,7 +416,7 @@ const displayUnlock = id => {
ezAlert({ ezAlert({
title: "Error", title: "Error",
body: md.render(response.errors.score), body: response.errors.score,
button: "Got it!" button: "Got it!"
}); });
}); });

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long