diff --git a/CTFd/api/v1/tokens.py b/CTFd/api/v1/tokens.py index 2c2011a4..975b8708 100644 --- a/CTFd/api/v1/tokens.py +++ b/CTFd/api/v1/tokens.py @@ -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") diff --git a/CTFd/forms/self.py b/CTFd/forms/self.py index c527138b..d325bc5d 100644 --- a/CTFd/forms/self.py +++ b/CTFd/forms/self.py @@ -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")) diff --git a/CTFd/models/__init__.py b/CTFd/models/__init__.py index 45f9d21b..a09bbc66 100644 --- a/CTFd/models/__init__.py +++ b/CTFd/models/__init__.py @@ -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") diff --git a/CTFd/schemas/tokens.py b/CTFd/schemas/tokens.py index d6ae4d36..094a01db 100644 --- a/CTFd/schemas/tokens.py +++ b/CTFd/schemas/tokens.py @@ -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): diff --git a/CTFd/themes/core/templates/settings.html b/CTFd/themes/core/templates/settings.html index 74b29cc4..1095786e 100644 --- a/CTFd/themes/core/templates/settings.html +++ b/CTFd/themes/core/templates/settings.html @@ -81,7 +81,10 @@ {{ form.expiration.label }} {{ form.expiration(class="form-control") }} - +
+ {{ form.description.label }} + {{ form.description(class="form-control", rows="3") }} +
{{ form.submit(class="btn btn-md btn-primary btn-outlined") }}
@@ -96,6 +99,7 @@ Created Expiration + Description Delete @@ -104,6 +108,7 @@ + {{ token.description | default('', true) }} diff --git a/CTFd/utils/security/auth.py b/CTFd/utils/security/auth.py index d098c4a3..6d62b5da 100644 --- a/CTFd/utils/security/auth.py +++ b/CTFd/utils/security/auth.py @@ -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 diff --git a/migrations/versions/9e6f6578ca84_add_description_column_to_tokens_table.py b/migrations/versions/9e6f6578ca84_add_description_column_to_tokens_table.py new file mode 100644 index 00000000..da2dbedf --- /dev/null +++ b/migrations/versions/9e6f6578ca84_add_description_column_to_tokens_table.py @@ -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")