mirror of
https://github.com/aljazceru/CTFd.git
synced 2025-12-19 06:54:20 +01:00
1569 submission filter by challenge (#1590)
* Allow the Admin Panel Submissions page to filter by Account IDs, Challenge IDs, and Challenge Names * Deprecate `CTFd.api.v1.helpers.models.build_model_filters` and wrap it to `CTFd.utils.helpers.models.build_model_filters` * Clean up some miscellaneous Submissions code * Closes #1569
This commit is contained in:
@@ -3,6 +3,7 @@ from flask import render_template, request, url_for
|
|||||||
from CTFd.admin import admin
|
from CTFd.admin import admin
|
||||||
from CTFd.models import Challenges, Submissions
|
from CTFd.models import Challenges, Submissions
|
||||||
from CTFd.utils.decorators import admins_only
|
from CTFd.utils.decorators import admins_only
|
||||||
|
from CTFd.utils.helpers.models import build_model_filters
|
||||||
from CTFd.utils.modes import get_model
|
from CTFd.utils.modes import get_model
|
||||||
|
|
||||||
|
|
||||||
@@ -19,12 +20,15 @@ def submissions_listing(submission_type):
|
|||||||
field = request.args.get("field")
|
field = request.args.get("field")
|
||||||
page = abs(request.args.get("page", 1, type=int))
|
page = abs(request.args.get("page", 1, type=int))
|
||||||
|
|
||||||
if q:
|
filters = build_model_filters(
|
||||||
submissions = []
|
model=Submissions,
|
||||||
if Submissions.__mapper__.has_property(
|
query=q,
|
||||||
field
|
field=field,
|
||||||
): # The field exists as an exposed column
|
extra_columns={
|
||||||
filters.append(getattr(Submissions, field).like("%{}%".format(q)))
|
"challenge_name": Challenges.name,
|
||||||
|
"account_id": Submissions.account_id,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
Model = get_model()
|
Model = get_model()
|
||||||
|
|
||||||
@@ -37,7 +41,7 @@ def submissions_listing(submission_type):
|
|||||||
Submissions.account_id,
|
Submissions.account_id,
|
||||||
Submissions.date,
|
Submissions.date,
|
||||||
Challenges.name.label("challenge_name"),
|
Challenges.name.label("challenge_name"),
|
||||||
Model.name.label("team_name"),
|
Model.name.label("account_name"),
|
||||||
)
|
)
|
||||||
.filter_by(**filters_by)
|
.filter_by(**filters_by)
|
||||||
.filter(*filters)
|
.filter(*filters)
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ from typing import List
|
|||||||
from flask import request
|
from flask import request
|
||||||
from flask_restx import Namespace, Resource
|
from flask_restx import Namespace, Resource
|
||||||
|
|
||||||
from CTFd.api.v1.helpers.models import build_model_filters
|
|
||||||
from CTFd.api.v1.helpers.request import validate_args
|
from CTFd.api.v1.helpers.request import validate_args
|
||||||
from CTFd.api.v1.helpers.schemas import sqlalchemy_to_pydantic
|
from CTFd.api.v1.helpers.schemas import sqlalchemy_to_pydantic
|
||||||
from CTFd.api.v1.schemas import APIDetailedSuccessResponse, APIListSuccessResponse
|
from CTFd.api.v1.schemas import APIDetailedSuccessResponse, APIListSuccessResponse
|
||||||
@@ -13,6 +12,7 @@ from CTFd.models import Awards, Users, db
|
|||||||
from CTFd.schemas.awards import AwardSchema
|
from CTFd.schemas.awards import AwardSchema
|
||||||
from CTFd.utils.config import is_teams_mode
|
from CTFd.utils.config import is_teams_mode
|
||||||
from CTFd.utils.decorators import admins_only
|
from CTFd.utils.decorators import admins_only
|
||||||
|
from CTFd.utils.helpers.models import build_model_filters
|
||||||
|
|
||||||
awards_namespace = Namespace("awards", description="Endpoint to retrieve Awards")
|
awards_namespace = Namespace("awards", description="Endpoint to retrieve Awards")
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ from flask import abort, render_template, request, url_for
|
|||||||
from flask_restx import Namespace, Resource
|
from flask_restx import Namespace, Resource
|
||||||
from sqlalchemy.sql import and_
|
from sqlalchemy.sql import and_
|
||||||
|
|
||||||
from CTFd.api.v1.helpers.models import build_model_filters
|
|
||||||
from CTFd.api.v1.helpers.request import validate_args
|
from CTFd.api.v1.helpers.request import validate_args
|
||||||
from CTFd.api.v1.helpers.schemas import sqlalchemy_to_pydantic
|
from CTFd.api.v1.helpers.schemas import sqlalchemy_to_pydantic
|
||||||
from CTFd.api.v1.schemas import APIDetailedSuccessResponse, APIListSuccessResponse
|
from CTFd.api.v1.schemas import APIDetailedSuccessResponse, APIListSuccessResponse
|
||||||
@@ -44,6 +43,7 @@ from CTFd.utils.decorators.visibility import (
|
|||||||
check_challenge_visibility,
|
check_challenge_visibility,
|
||||||
check_score_visibility,
|
check_score_visibility,
|
||||||
)
|
)
|
||||||
|
from CTFd.utils.helpers.models import build_model_filters
|
||||||
from CTFd.utils.logging import log
|
from CTFd.utils.logging import log
|
||||||
from CTFd.utils.modes import generate_account_url, get_model
|
from CTFd.utils.modes import generate_account_url, get_model
|
||||||
from CTFd.utils.security.signing import serialize
|
from CTFd.utils.security.signing import serialize
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ from typing import List
|
|||||||
from flask import request
|
from flask import request
|
||||||
from flask_restx import Namespace, Resource
|
from flask_restx import Namespace, Resource
|
||||||
|
|
||||||
from CTFd.api.v1.helpers.models import build_model_filters
|
|
||||||
from CTFd.api.v1.helpers.request import validate_args
|
from CTFd.api.v1.helpers.request import validate_args
|
||||||
from CTFd.api.v1.helpers.schemas import sqlalchemy_to_pydantic
|
from CTFd.api.v1.helpers.schemas import sqlalchemy_to_pydantic
|
||||||
from CTFd.api.v1.schemas import APIDetailedSuccessResponse, APIListSuccessResponse
|
from CTFd.api.v1.schemas import APIDetailedSuccessResponse, APIListSuccessResponse
|
||||||
@@ -13,6 +12,7 @@ from CTFd.models import Configs, db
|
|||||||
from CTFd.schemas.config import ConfigSchema
|
from CTFd.schemas.config import ConfigSchema
|
||||||
from CTFd.utils import set_config
|
from CTFd.utils import set_config
|
||||||
from CTFd.utils.decorators import admins_only
|
from CTFd.utils.decorators import admins_only
|
||||||
|
from CTFd.utils.helpers.models import build_model_filters
|
||||||
|
|
||||||
configs_namespace = Namespace("configs", description="Endpoint to retrieve Configs")
|
configs_namespace = Namespace("configs", description="Endpoint to retrieve Configs")
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ from typing import List
|
|||||||
from flask import request
|
from flask import request
|
||||||
from flask_restx import Namespace, Resource
|
from flask_restx import Namespace, Resource
|
||||||
|
|
||||||
from CTFd.api.v1.helpers.models import build_model_filters
|
|
||||||
from CTFd.api.v1.helpers.request import validate_args
|
from CTFd.api.v1.helpers.request import validate_args
|
||||||
from CTFd.api.v1.helpers.schemas import sqlalchemy_to_pydantic
|
from CTFd.api.v1.helpers.schemas import sqlalchemy_to_pydantic
|
||||||
from CTFd.api.v1.schemas import APIDetailedSuccessResponse, APIListSuccessResponse
|
from CTFd.api.v1.schemas import APIDetailedSuccessResponse, APIListSuccessResponse
|
||||||
@@ -12,6 +11,7 @@ from CTFd.models import Files, db
|
|||||||
from CTFd.schemas.files import FileSchema
|
from CTFd.schemas.files import FileSchema
|
||||||
from CTFd.utils import uploads
|
from CTFd.utils import uploads
|
||||||
from CTFd.utils.decorators import admins_only
|
from CTFd.utils.decorators import admins_only
|
||||||
|
from CTFd.utils.helpers.models import build_model_filters
|
||||||
|
|
||||||
files_namespace = Namespace("files", description="Endpoint to retrieve Files")
|
files_namespace = Namespace("files", description="Endpoint to retrieve Files")
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ from typing import List
|
|||||||
from flask import request
|
from flask import request
|
||||||
from flask_restx import Namespace, Resource
|
from flask_restx import Namespace, Resource
|
||||||
|
|
||||||
from CTFd.api.v1.helpers.models import build_model_filters
|
|
||||||
from CTFd.api.v1.helpers.request import validate_args
|
from CTFd.api.v1.helpers.request import validate_args
|
||||||
from CTFd.api.v1.helpers.schemas import sqlalchemy_to_pydantic
|
from CTFd.api.v1.helpers.schemas import sqlalchemy_to_pydantic
|
||||||
from CTFd.api.v1.schemas import APIDetailedSuccessResponse, APIListSuccessResponse
|
from CTFd.api.v1.schemas import APIDetailedSuccessResponse, APIListSuccessResponse
|
||||||
@@ -12,6 +11,7 @@ from CTFd.models import Flags, db
|
|||||||
from CTFd.plugins.flags import FLAG_CLASSES, get_flag_class
|
from CTFd.plugins.flags import FLAG_CLASSES, get_flag_class
|
||||||
from CTFd.schemas.flags import FlagSchema
|
from CTFd.schemas.flags import FlagSchema
|
||||||
from CTFd.utils.decorators import admins_only
|
from CTFd.utils.decorators import admins_only
|
||||||
|
from CTFd.utils.helpers.models import build_model_filters
|
||||||
|
|
||||||
flags_namespace = Namespace("flags", description="Endpoint to retrieve Flags")
|
flags_namespace = Namespace("flags", description="Endpoint to retrieve Flags")
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
|
# This file is no longer used. If you're importing the function from here please update your imports
|
||||||
|
|
||||||
|
from CTFd.utils.helpers.models import build_model_filters as _build_model_filters
|
||||||
|
|
||||||
|
|
||||||
def build_model_filters(model, query, field):
|
def build_model_filters(model, query, field):
|
||||||
filters = []
|
print("CTFd.api.v1.helpers.models.build_model_filters has been deprecated.")
|
||||||
if query:
|
print("Please switch to using CTFd.utils.helpers.models.build_model_filters")
|
||||||
# The field exists as an exposed column
|
print(
|
||||||
if model.__mapper__.has_property(field):
|
"This function will raise an exception in a future minor release of CTFd and then be removed in a major release."
|
||||||
filters.append(getattr(model, field).like("%{}%".format(query)))
|
)
|
||||||
return filters
|
return _build_model_filters(model, query, field)
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ from typing import List
|
|||||||
from flask import request
|
from flask import request
|
||||||
from flask_restx import Namespace, Resource
|
from flask_restx import Namespace, Resource
|
||||||
|
|
||||||
from CTFd.api.v1.helpers.models import build_model_filters
|
|
||||||
from CTFd.api.v1.helpers.request import validate_args
|
from CTFd.api.v1.helpers.request import validate_args
|
||||||
from CTFd.api.v1.helpers.schemas import sqlalchemy_to_pydantic
|
from CTFd.api.v1.helpers.schemas import sqlalchemy_to_pydantic
|
||||||
from CTFd.api.v1.schemas import APIDetailedSuccessResponse, APIListSuccessResponse
|
from CTFd.api.v1.schemas import APIDetailedSuccessResponse, APIListSuccessResponse
|
||||||
@@ -11,6 +10,7 @@ from CTFd.constants import RawEnum
|
|||||||
from CTFd.models import Hints, HintUnlocks, db
|
from CTFd.models import Hints, HintUnlocks, db
|
||||||
from CTFd.schemas.hints import HintSchema
|
from CTFd.schemas.hints import HintSchema
|
||||||
from CTFd.utils.decorators import admins_only, authed_only, during_ctf_time_only
|
from CTFd.utils.decorators import admins_only, authed_only, during_ctf_time_only
|
||||||
|
from CTFd.utils.helpers.models import build_model_filters
|
||||||
from CTFd.utils.user import get_current_user, is_admin
|
from CTFd.utils.user import get_current_user, is_admin
|
||||||
|
|
||||||
hints_namespace = Namespace("hints", description="Endpoint to retrieve Hints")
|
hints_namespace = Namespace("hints", description="Endpoint to retrieve Hints")
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ from typing import List
|
|||||||
from flask import current_app, request
|
from flask import current_app, request
|
||||||
from flask_restx import Namespace, Resource
|
from flask_restx import Namespace, Resource
|
||||||
|
|
||||||
from CTFd.api.v1.helpers.models import build_model_filters
|
|
||||||
from CTFd.api.v1.helpers.request import validate_args
|
from CTFd.api.v1.helpers.request import validate_args
|
||||||
from CTFd.api.v1.helpers.schemas import sqlalchemy_to_pydantic
|
from CTFd.api.v1.helpers.schemas import sqlalchemy_to_pydantic
|
||||||
from CTFd.api.v1.schemas import APIDetailedSuccessResponse, APIListSuccessResponse
|
from CTFd.api.v1.schemas import APIDetailedSuccessResponse, APIListSuccessResponse
|
||||||
@@ -11,6 +10,7 @@ from CTFd.constants import RawEnum
|
|||||||
from CTFd.models import Notifications, db
|
from CTFd.models import Notifications, db
|
||||||
from CTFd.schemas.notifications import NotificationSchema
|
from CTFd.schemas.notifications import NotificationSchema
|
||||||
from CTFd.utils.decorators import admins_only
|
from CTFd.utils.decorators import admins_only
|
||||||
|
from CTFd.utils.helpers.models import build_model_filters
|
||||||
|
|
||||||
notifications_namespace = Namespace(
|
notifications_namespace = Namespace(
|
||||||
"notifications", description="Endpoint to retrieve Notifications"
|
"notifications", description="Endpoint to retrieve Notifications"
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ from typing import List
|
|||||||
from flask import request
|
from flask import request
|
||||||
from flask_restx import Namespace, Resource
|
from flask_restx import Namespace, Resource
|
||||||
|
|
||||||
from CTFd.api.v1.helpers.models import build_model_filters
|
|
||||||
from CTFd.api.v1.helpers.request import validate_args
|
from CTFd.api.v1.helpers.request import validate_args
|
||||||
from CTFd.api.v1.helpers.schemas import sqlalchemy_to_pydantic
|
from CTFd.api.v1.helpers.schemas import sqlalchemy_to_pydantic
|
||||||
from CTFd.api.v1.schemas import APIDetailedSuccessResponse, APIListSuccessResponse
|
from CTFd.api.v1.schemas import APIDetailedSuccessResponse, APIListSuccessResponse
|
||||||
@@ -12,6 +11,7 @@ from CTFd.constants import RawEnum
|
|||||||
from CTFd.models import Pages, db
|
from CTFd.models import Pages, db
|
||||||
from CTFd.schemas.pages import PageSchema
|
from CTFd.schemas.pages import PageSchema
|
||||||
from CTFd.utils.decorators import admins_only
|
from CTFd.utils.decorators import admins_only
|
||||||
|
from CTFd.utils.helpers.models import build_model_filters
|
||||||
|
|
||||||
pages_namespace = Namespace("pages", description="Endpoint to retrieve Pages")
|
pages_namespace = Namespace("pages", description="Endpoint to retrieve Pages")
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ from typing import List
|
|||||||
|
|
||||||
from flask_restx import Namespace, Resource
|
from flask_restx import Namespace, Resource
|
||||||
|
|
||||||
from CTFd.api.v1.helpers.models import build_model_filters
|
|
||||||
from CTFd.api.v1.helpers.request import validate_args
|
from CTFd.api.v1.helpers.request import validate_args
|
||||||
from CTFd.api.v1.helpers.schemas import sqlalchemy_to_pydantic
|
from CTFd.api.v1.helpers.schemas import sqlalchemy_to_pydantic
|
||||||
from CTFd.api.v1.schemas import (
|
from CTFd.api.v1.schemas import (
|
||||||
@@ -14,6 +13,7 @@ from CTFd.constants import RawEnum
|
|||||||
from CTFd.models import Submissions, db
|
from CTFd.models import Submissions, db
|
||||||
from CTFd.schemas.submissions import SubmissionSchema
|
from CTFd.schemas.submissions import SubmissionSchema
|
||||||
from CTFd.utils.decorators import admins_only
|
from CTFd.utils.decorators import admins_only
|
||||||
|
from CTFd.utils.helpers.models import build_model_filters
|
||||||
|
|
||||||
submissions_namespace = Namespace(
|
submissions_namespace = Namespace(
|
||||||
"submissions", description="Endpoint to retrieve Submission"
|
"submissions", description="Endpoint to retrieve Submission"
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ from typing import List
|
|||||||
from flask import request
|
from flask import request
|
||||||
from flask_restx import Namespace, Resource
|
from flask_restx import Namespace, Resource
|
||||||
|
|
||||||
from CTFd.api.v1.helpers.models import build_model_filters
|
|
||||||
from CTFd.api.v1.helpers.request import validate_args
|
from CTFd.api.v1.helpers.request import validate_args
|
||||||
from CTFd.api.v1.helpers.schemas import sqlalchemy_to_pydantic
|
from CTFd.api.v1.helpers.schemas import sqlalchemy_to_pydantic
|
||||||
from CTFd.api.v1.schemas import APIDetailedSuccessResponse, APIListSuccessResponse
|
from CTFd.api.v1.schemas import APIDetailedSuccessResponse, APIListSuccessResponse
|
||||||
@@ -11,6 +10,7 @@ from CTFd.constants import RawEnum
|
|||||||
from CTFd.models import Tags, db
|
from CTFd.models import Tags, db
|
||||||
from CTFd.schemas.tags import TagSchema
|
from CTFd.schemas.tags import TagSchema
|
||||||
from CTFd.utils.decorators import admins_only
|
from CTFd.utils.decorators import admins_only
|
||||||
|
from CTFd.utils.helpers.models import build_model_filters
|
||||||
|
|
||||||
tags_namespace = Namespace("tags", description="Endpoint to retrieve Tags")
|
tags_namespace = Namespace("tags", description="Endpoint to retrieve Tags")
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ from typing import List
|
|||||||
from flask import abort, request, session
|
from flask import abort, request, session
|
||||||
from flask_restx import Namespace, Resource
|
from flask_restx import Namespace, Resource
|
||||||
|
|
||||||
from CTFd.api.v1.helpers.models import build_model_filters
|
|
||||||
from CTFd.api.v1.helpers.request import validate_args
|
from CTFd.api.v1.helpers.request import validate_args
|
||||||
from CTFd.api.v1.helpers.schemas import sqlalchemy_to_pydantic
|
from CTFd.api.v1.helpers.schemas import sqlalchemy_to_pydantic
|
||||||
from CTFd.api.v1.schemas import (
|
from CTFd.api.v1.schemas import (
|
||||||
@@ -22,6 +21,7 @@ from CTFd.utils.decorators.visibility import (
|
|||||||
check_account_visibility,
|
check_account_visibility,
|
||||||
check_score_visibility,
|
check_score_visibility,
|
||||||
)
|
)
|
||||||
|
from CTFd.utils.helpers.models import build_model_filters
|
||||||
from CTFd.utils.user import get_current_team, get_current_user_type, is_admin
|
from CTFd.utils.user import get_current_team, get_current_user_type, is_admin
|
||||||
|
|
||||||
teams_namespace = Namespace("teams", description="Endpoint to retrieve Teams")
|
teams_namespace = Namespace("teams", description="Endpoint to retrieve Teams")
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ from typing import List
|
|||||||
from flask import request
|
from flask import request
|
||||||
from flask_restx import Namespace, Resource
|
from flask_restx import Namespace, Resource
|
||||||
|
|
||||||
from CTFd.api.v1.helpers.models import build_model_filters
|
|
||||||
from CTFd.api.v1.helpers.request import validate_args
|
from CTFd.api.v1.helpers.request import validate_args
|
||||||
from CTFd.api.v1.helpers.schemas import sqlalchemy_to_pydantic
|
from CTFd.api.v1.helpers.schemas import sqlalchemy_to_pydantic
|
||||||
from CTFd.api.v1.schemas import APIDetailedSuccessResponse, APIListSuccessResponse
|
from CTFd.api.v1.schemas import APIDetailedSuccessResponse, APIListSuccessResponse
|
||||||
@@ -18,6 +17,7 @@ from CTFd.utils.decorators import (
|
|||||||
during_ctf_time_only,
|
during_ctf_time_only,
|
||||||
require_verified_emails,
|
require_verified_emails,
|
||||||
)
|
)
|
||||||
|
from CTFd.utils.helpers.models import build_model_filters
|
||||||
from CTFd.utils.user import get_current_user
|
from CTFd.utils.user import get_current_user
|
||||||
|
|
||||||
unlocks_namespace = Namespace("unlocks", description="Endpoint to retrieve Unlocks")
|
unlocks_namespace = Namespace("unlocks", description="Endpoint to retrieve Unlocks")
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ from typing import List
|
|||||||
from flask import abort, request, session
|
from flask import abort, request, session
|
||||||
from flask_restx import Namespace, Resource
|
from flask_restx import Namespace, Resource
|
||||||
|
|
||||||
from CTFd.api.v1.helpers.models import build_model_filters
|
|
||||||
from CTFd.api.v1.helpers.request import validate_args
|
from CTFd.api.v1.helpers.request import validate_args
|
||||||
from CTFd.api.v1.helpers.schemas import sqlalchemy_to_pydantic
|
from CTFd.api.v1.helpers.schemas import sqlalchemy_to_pydantic
|
||||||
from CTFd.api.v1.schemas import (
|
from CTFd.api.v1.schemas import (
|
||||||
@@ -32,6 +31,7 @@ from CTFd.utils.decorators.visibility import (
|
|||||||
check_score_visibility,
|
check_score_visibility,
|
||||||
)
|
)
|
||||||
from CTFd.utils.email import sendmail, user_created_notification
|
from CTFd.utils.email import sendmail, user_created_notification
|
||||||
|
from CTFd.utils.helpers.models import build_model_filters
|
||||||
from CTFd.utils.security.auth import update_user
|
from CTFd.utils.security.auth import update_user
|
||||||
from CTFd.utils.user import get_current_user, get_current_user_type, is_admin
|
from CTFd.utils.user import get_current_user, get_current_user_type, is_admin
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,13 @@ from CTFd.forms.fields import SubmitField
|
|||||||
class SubmissionSearchForm(BaseForm):
|
class SubmissionSearchForm(BaseForm):
|
||||||
field = SelectField(
|
field = SelectField(
|
||||||
"Search Field",
|
"Search Field",
|
||||||
choices=[("provided", "Provided"), ("id", "ID")],
|
choices=[
|
||||||
|
("provided", "Provided"),
|
||||||
|
("id", "ID"),
|
||||||
|
("account_id", "Account ID"),
|
||||||
|
("challenge_id", "Challenge ID"),
|
||||||
|
("challenge_name", "Challenge Name"),
|
||||||
|
],
|
||||||
default="provided",
|
default="provided",
|
||||||
validators=[InputRequired()],
|
validators=[InputRequired()],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -617,9 +617,7 @@ class Submissions(db.Model):
|
|||||||
return child_classes[type]
|
return child_classes[type]
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<Submission {}, {}, {}, {}>".format(
|
return f"<Submission id={self.id}, challenge_id={self.challenge_id}, ip={self.ip}, provided={self.provided}>"
|
||||||
self.team_id, self.challenge_id, self.ip, self.provided
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class Solves(Submissions):
|
class Solves(Submissions):
|
||||||
|
|||||||
@@ -29,6 +29,10 @@
|
|||||||
<i class="btn-fa fas fa-file-alt fa-2x px-2" data-toggle="tooltip" data-placement="top"
|
<i class="btn-fa fas fa-file-alt fa-2x px-2" data-toggle="tooltip" data-placement="top"
|
||||||
title="Preview Challenge"></i>
|
title="Preview Challenge"></i>
|
||||||
</a>
|
</a>
|
||||||
|
<a class="no-decoration" href="{{ url_for('admin.submissions_listing', submission_type='correct', field='challenge_id', q=challenge.id) }}">
|
||||||
|
<i class="btn-fa fas fa-check-circle fa-2x px-2" data-toggle="tooltip" data-placement="top"
|
||||||
|
title="Correct Submissions"></i>
|
||||||
|
</a>
|
||||||
<a class="delete-challenge">
|
<a class="delete-challenge">
|
||||||
<i class="btn-fa fas fa-trash-alt fa-2x px-2" data-toggle="tooltip" data-placement="top"
|
<i class="btn-fa fas fa-trash-alt fa-2x px-2" data-toggle="tooltip" data-placement="top"
|
||||||
title="Delete Challenge"></i>
|
title="Delete Challenge"></i>
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
{% with form = Forms.submissions.SubmissionSearchForm(field=field, q=q) %}
|
{% with form = Forms.submissions.SubmissionSearchForm(field=field, q=q) %}
|
||||||
<form method="GET" class="form-inline">
|
<form method="GET" class="form-inline">
|
||||||
<div class="form-group col-md-2">
|
<div class="form-group col-md-2 pr-0">
|
||||||
{{ form.field(class="form-control custom-select w-100") }}
|
{{ form.field(class="form-control custom-select w-100") }}
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group col-md-8">
|
<div class="form-group col-md-8">
|
||||||
@@ -66,7 +66,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
<th class="text-center sort-col"><b>ID</b></th>
|
<th class="text-center sort-col"><b>ID</b></th>
|
||||||
<th class="sort-col"><b>Team</b></th>
|
<th class="sort-col"><b>{{ get_mode_as_word(capitalize=True) }}</b></th>
|
||||||
<th class="sort-col"><b>Challenge</b></th>
|
<th class="sort-col"><b>Challenge</b></th>
|
||||||
<th class="sort-col"><b>Type</b></th>
|
<th class="sort-col"><b>Type</b></th>
|
||||||
<th class="sort-col"><b>Provided</b></th>
|
<th class="sort-col"><b>Provided</b></th>
|
||||||
@@ -84,8 +84,10 @@
|
|||||||
<td class="text-center" id="{{ sub.id }}">
|
<td class="text-center" id="{{ sub.id }}">
|
||||||
{{ sub.id }}
|
{{ sub.id }}
|
||||||
</td>
|
</td>
|
||||||
<td class="team" id="{{ sub.team_id }}">
|
<td class="team" id="{{ sub.account_id }}">
|
||||||
<a href="{{ generate_account_url(sub.account_id, admin=True) }}">{{ sub.team_name }}</a>
|
<a href="{{ generate_account_url(sub.account_id, admin=True) }}">
|
||||||
|
{{ sub.account_name }}
|
||||||
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td class="chal" id="{{ sub.challenge_id }}">
|
<td class="chal" id="{{ sub.challenge_id }}">
|
||||||
<a href="{{ url_for('admin.challenges_detail', challenge_id=sub.challenge_id) }}">
|
<a href="{{ url_for('admin.challenges_detail', challenge_id=sub.challenge_id) }}">
|
||||||
|
|||||||
23
CTFd/utils/helpers/models.py
Normal file
23
CTFd/utils/helpers/models.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import sqlalchemy
|
||||||
|
|
||||||
|
|
||||||
|
def build_model_filters(model, query, field, extra_columns=None):
|
||||||
|
if extra_columns is None:
|
||||||
|
extra_columns = {}
|
||||||
|
filters = []
|
||||||
|
if query:
|
||||||
|
# The field exists as an exposed column
|
||||||
|
if model.__mapper__.has_property(field):
|
||||||
|
column = getattr(model, field)
|
||||||
|
|
||||||
|
if type(column.type) == sqlalchemy.sql.sqltypes.Integer:
|
||||||
|
_filter = column.op("==")(query)
|
||||||
|
else:
|
||||||
|
_filter = column.like(f"%{query}%")
|
||||||
|
filters.append(_filter)
|
||||||
|
else:
|
||||||
|
if field in extra_columns:
|
||||||
|
column = extra_columns[field]
|
||||||
|
_filter = column.op("==")(query)
|
||||||
|
filters.append(_filter)
|
||||||
|
return filters
|
||||||
Reference in New Issue
Block a user