Merge branch 'master' into 1691-challenge-preview-improvements

This commit is contained in:
Kevin Chung
2023-06-26 19:29:13 -04:00
committed by GitHub
16 changed files with 153 additions and 25 deletions

View File

@@ -85,11 +85,14 @@ class TokenList(Resource):
def post(self):
req = request.get_json()
expiration = req.get("expiration")
description = req.get("description")
if expiration:
expiration = datetime.datetime.strptime(expiration, "%Y-%m-%d")
user = get_current_user()
token = generate_user_token(user, expiration=expiration)
token = generate_user_token(
user, expiration=expiration, description=description
)
# Explicitly use admin view so that user's can see the value of their token
schema = TokenSchema(view="admin")

View File

@@ -1,6 +1,6 @@
from flask import session
from flask_babel import lazy_gettext as _l
from wtforms import PasswordField, SelectField, StringField
from wtforms import PasswordField, SelectField, StringField, TextAreaField
from wtforms.fields.html5 import DateField, URLField
from CTFd.constants.languages import SELECT_LANGUAGE_LIST
@@ -50,4 +50,5 @@ def SettingsForm(*args, **kwargs):
class TokensForm(BaseForm):
expiration = DateField(_l("Expiration"))
description = TextAreaField("Usage Description")
submit = SubmitField(_l("Generate"))

View File

@@ -916,6 +916,7 @@ class Tokens(db.Model):
db.DateTime,
default=lambda: datetime.datetime.utcnow() + datetime.timedelta(days=30),
)
description = db.Column(db.Text)
value = db.Column(db.String(128), unique=True)
user = db.relationship("Users", foreign_keys="Tokens.user_id", lazy="select")

View File

@@ -9,8 +9,16 @@ class TokenSchema(ma.ModelSchema):
dump_only = ("id", "expiration", "type")
views = {
"admin": ["id", "type", "user_id", "created", "expiration", "value"],
"user": ["id", "type", "created", "expiration"],
"admin": [
"id",
"type",
"user_id",
"created",
"expiration",
"description",
"value",
],
"user": ["id", "type", "created", "expiration", "description"],
}
def __init__(self, view=None, *args, **kwargs):

View File

@@ -61,7 +61,55 @@ function deleteSelectedSubmissions(_event) {
});
}
function showFlagsToggle(_event) {
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.has("full")) {
urlParams.delete("full");
} else {
urlParams.set("full", "true");
}
window.location.href = `${window.location.pathname}?${urlParams.toString()}`;
}
function showFlag(event) {
let target = $(event.currentTarget);
let eye = target.find("i");
let flag = target.parent().find("pre");
if (!flag.hasClass("full-flag")) {
flag.text(flag.attr("title"));
flag.addClass("full-flag");
eye.addClass("fa-eye-slash");
eye.removeClass("fa-eye");
} else {
flag.text(flag.attr("title").substring(0, 42) + "...");
flag.removeClass("full-flag");
eye.addClass("fa-eye");
eye.removeClass("fa-eye-slash");
}
}
function copyFlag(event) {
let target = $(event.currentTarget);
let flag = target.parent().find("pre");
let text = flag.attr("title");
navigator.clipboard.writeText(text);
$(event.currentTarget).tooltip({
title: "Copied!",
trigger: "manual"
});
$(event.currentTarget).tooltip("show");
setTimeout(function() {
$(event.currentTarget).tooltip("hide");
}, 1500);
}
$(() => {
$("#show-full-flags-button").click(showFlagsToggle);
$("#show-short-flags-button").click(showFlagsToggle);
$(".show-flag").click(showFlag);
$(".copy-flag").click(copyFlag);
$(".delete-correct-submission").click(deleteCorrectSubmission);
$("#submission-delete-button").click(deleteSelectedSubmissions);
});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -48,7 +48,16 @@
<div class="col-md-12">
<div class="float-right pb-3">
<div class="btn-group" role="group">
<button type="button" class="btn btn-outline-danger" id="submission-delete-button">
{% if request.args.get("full") %}
<button type="button" class="btn btn-outline-primary" data-toggle="tooltip" title="Show truncated flags" id="show-short-flags-button">
<i class="btn-fa far fa-flag"></i>
</button>
{% else %}
<button type="button" class="btn btn-outline-primary" data-toggle="tooltip" title="Show full flags" id="show-full-flags-button">
<i class="btn-fa fas fa-flag"></i>
</button>
{% endif %}
<button type="button" class="btn btn-outline-danger" data-toggle="tooltip" title="Delete selected submissions" id="submission-delete-button">
<i class="btn-fa fas fa-trash-alt"></i>
</button>
</div>
@@ -109,7 +118,19 @@
{{ sub.type }}
</td>
<td class="flag" id="{{ sub.id }}">
<pre class="mb-0">{{ sub.provided }}</pre>
<button class="btn btn-link p-0 float-left copy-flag" type="button">
<i class="fas fa-clipboard"></i>
</button>
{% if request.args.get('full') %}
<pre class="mb-0 pl-2" title="{{ sub.provided }}">{{ sub.provided }}</pre>
{% else %}
<pre class="mb-0 pl-2 float-left" title="{{ sub.provided }}">{{ sub.provided | truncate(45, True) }}</pre>
{% if sub.provided | length > 50 %}
<button class="btn btn-link p-0 pl-1 float-left show-flag">
<i class="fas fa-eye"></i>
</button>
{% endif %}
{% endif %}
</td>
<td class="text-center solve-time">
<span data-time="{{ sub.date | isoformat }}"></span>

View File

@@ -15,6 +15,10 @@ git subtree add --prefix CTFd/themes/core-beta git@github.com:CTFd/core-beta.git
git subtree pull --prefix CTFd/themes/core-beta git@github.com:CTFd/core-beta.git main --squash
```
### Subtree Gotcha
Make sure to use Merge Commits when dealing with the subtree here. For some reason Github's squash and commit uses the wrong line ending which causes issues with the subtree script: https://stackoverflow.com/a/47190256.
## Todo
- Document how we are using Vite

View File

@@ -164,6 +164,11 @@
{{ form.expiration(class="form-control") }}
</div>
<div class="mb-3">
<b>{{ form.description.label(class="form-label") }}</b>
{{ form.description(class="form-control", rows="3") }}
</div>
<div class="row">
<div class="col">
{{ form.submit(class="btn btn-block btn-primary float-end px-4") }}
@@ -218,6 +223,7 @@
<tr>
<td class="text-center"><b>{% trans %}Created{% endtrans %}</b></td>
<td><b>{% trans %}Expiration{% endtrans %}</b></td>
<td><b>{% trans %}Description{% endtrans %}</b></td>
<td><b>{% trans %}Delete{% endtrans %}</b></td>
</tr>
</thead>
@@ -230,6 +236,9 @@
<td>
<span data-time="{{ token.expiration | isoformat }}"></span>
</td>
<td>
<span>{{ token.description | default('', true) }}</span>
</td>
<td class="text-center">
<span
class="delete-token" role="button"

View File

@@ -82,7 +82,7 @@
<table class="table table-striped">
<thead>
<tr>
<td><b>{% trans %}User Name{% trans %}</b></td>
<td><b>{% trans %}User Name{% endtrans %}</b></td>
<td><b>{% trans %}Score{% endtrans %}</b></td>
</tr>
</thead>
@@ -169,15 +169,15 @@
<div class="row" x-data="TeamGraphs">
<div class="col-md-6 d-none d-md-block d-lg-block py-4">
<div class="progress">
<div
class="progress-bar"
role="progressbar"
:style="{ width: `${getSolvePercentage()}%`, 'background-color': 'rgb(0, 209, 64)' }"
<div
class="progress-bar"
role="progressbar"
:style="{ width: `${getSolvePercentage()}%`, 'background-color': 'rgb(0, 209, 64)' }"
>
</div>
<div
class="progress-bar"
role="progressbar"
<div
class="progress-bar"
role="progressbar"
:style="{ width: `${getFailPercentage()}%`, 'background-color': 'rgb(207, 38, 0)' }"
>
</div>
@@ -198,9 +198,9 @@
<div class="col-md-6 d-none d-md-block d-lg-block py-4">
<div class="progress">
<template x-for="category in getCategoryBreakdown()" :key="category.name">
<div
class="progress-bar"
role="progressbar"
<div
class="progress-bar"
role="progressbar"
:style="{ width: `${category.percent}%`, 'background-color': category.color }"
>
</div>

View File

@@ -81,7 +81,10 @@
<b>{{ form.expiration.label }}</b>
{{ form.expiration(class="form-control") }}
</div>
<div class="form-group">
<b>{{ form.description.label }}</b>
{{ form.description(class="form-control", rows="3") }}
</div>
<div class="form-group text-right">
{{ form.submit(class="btn btn-md btn-primary btn-outlined") }}
</div>
@@ -96,6 +99,7 @@
<tr>
<td class="text-center"><b>Created</b></td>
<td class="text-center"><b>Expiration</b></td>
<td class="text-center"><b>Description</b></td>
<td class="text-center"><b>Delete</b></td>
</tr>
</thead>
@@ -104,6 +108,7 @@
<tr>
<td><span data-time="{{ token.created | isoformat }}"></span></td>
<td><span data-time="{{ token.expiration | isoformat }}"></span></td>
<td><span>{{ token.description | default('', true) }}</span></td>
<td class="text-center">
<span class="delete-token" role="button" data-token-id="{{ token.id }}">
<i class="btn-fa fas fa-times"></i>

View File

@@ -34,13 +34,15 @@ def logout_user():
session.clear()
def generate_user_token(user, expiration=None):
def generate_user_token(user, expiration=None, description=None):
temp_token = True
while temp_token is not None:
value = hexencode(os.urandom(32))
value = "ctfd_" + hexencode(os.urandom(32))
temp_token = UserTokens.query.filter_by(value=value).first()
token = UserTokens(user_id=user.id, expiration=expiration, value=value)
token = UserTokens(
user_id=user.id, expiration=expiration, description=description, value=value
)
db.session.add(token)
db.session.commit()
return token

View File

@@ -0,0 +1,23 @@
"""Add description column to tokens table
Revision ID: 9e6f6578ca84
Revises: 0def790057c1
Create Date: 2023-06-21 23:22:34.179636
"""
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision = "9e6f6578ca84"
down_revision = "0def790057c1"
branch_labels = None
depends_on = None
def upgrade():
op.add_column("tokens", sa.Column("description", sa.Text(), nullable=True))
def downgrade():
op.drop_column("tokens", "description")

View File

@@ -11,7 +11,7 @@ passlib==1.7.4
bcrypt==4.0.1
itsdangerous==1.1.0
requests==2.28.1
PyMySQL==0.9.3
PyMySQL[rsa]==0.9.3
gunicorn==20.1.0
dataset==1.3.1
cmarkgfm==2022.10.27

View File

@@ -29,6 +29,7 @@ certifi==2022.12.7
cffi==1.15.0
# via
# cmarkgfm
# cryptography
# pybluemonday
charset-normalizer==2.0.12
# via requests
@@ -36,6 +37,8 @@ click==7.1.2
# via flask
cmarkgfm==2022.10.27
# via -r requirements.in
cryptography==40.0.2
# via pymysql
dataset==1.3.1
# via -r requirements.in
docutils==0.15.2
@@ -117,7 +120,7 @@ pycparser==2.20
# via cffi
pydantic==1.6.2
# via -r requirements.in
pymysql==0.9.3
pymysql[rsa]==0.9.3
# via -r requirements.in
pyrsistent==0.17.3
# via jsonschema