mirror of
https://github.com/aljazceru/CTFd.git
synced 2026-02-05 06:14:29 +01:00
Add account searching to the user facing side (#1517)
* Add account searching to the user facing side of CTFd * Closes #1354
This commit is contained in:
@@ -38,7 +38,27 @@ class TeamCaptainForm(BaseForm):
|
||||
class TeamSearchForm(BaseForm):
|
||||
field = SelectField(
|
||||
"Search Field",
|
||||
choices=[("name", "Name"), ("id", "ID"), ("affiliation", "Affiliation")],
|
||||
choices=[
|
||||
("name", "Name"),
|
||||
("id", "ID"),
|
||||
("affiliation", "Affiliation"),
|
||||
("website", "Website"),
|
||||
],
|
||||
default="name",
|
||||
validators=[InputRequired()],
|
||||
)
|
||||
q = StringField("Parameter", validators=[InputRequired()])
|
||||
submit = SubmitField("Search")
|
||||
|
||||
|
||||
class PublicTeamSearchForm(BaseForm):
|
||||
field = SelectField(
|
||||
"Search Field",
|
||||
choices=[
|
||||
("name", "Name"),
|
||||
("affiliation", "Affiliation"),
|
||||
("website", "Website"),
|
||||
],
|
||||
default="name",
|
||||
validators=[InputRequired()],
|
||||
)
|
||||
|
||||
@@ -15,6 +15,7 @@ class UserSearchForm(BaseForm):
|
||||
("id", "ID"),
|
||||
("email", "Email"),
|
||||
("affiliation", "Affiliation"),
|
||||
("website", "Website"),
|
||||
("ip", "IP Address"),
|
||||
],
|
||||
default="name",
|
||||
@@ -24,6 +25,21 @@ class UserSearchForm(BaseForm):
|
||||
submit = SubmitField("Search")
|
||||
|
||||
|
||||
class PublicUserSearchForm(BaseForm):
|
||||
field = SelectField(
|
||||
"Search Field",
|
||||
choices=[
|
||||
("name", "Name"),
|
||||
("affiliation", "Affiliation"),
|
||||
("website", "Website"),
|
||||
],
|
||||
default="name",
|
||||
validators=[InputRequired()],
|
||||
)
|
||||
q = StringField("Parameter", validators=[InputRequired()])
|
||||
submit = SubmitField("Search")
|
||||
|
||||
|
||||
class UserEditForm(BaseForm):
|
||||
name = StringField("User Name", validators=[InputRequired()])
|
||||
email = EmailField("Email", validators=[InputRequired()])
|
||||
|
||||
@@ -20,15 +20,34 @@ teams = Blueprint("teams", __name__)
|
||||
@check_account_visibility
|
||||
@require_team_mode
|
||||
def listing():
|
||||
page = abs(request.args.get("page", 1, type=int))
|
||||
q = request.args.get("q")
|
||||
field = request.args.get("field", "name")
|
||||
filters = []
|
||||
|
||||
if field not in ("name", "affiliation", "website"):
|
||||
field = "name"
|
||||
|
||||
if q:
|
||||
filters.append(getattr(Teams, field).like("%{}%".format(q)))
|
||||
|
||||
teams = (
|
||||
Teams.query.filter_by(hidden=False, banned=False)
|
||||
.filter(*filters)
|
||||
.order_by(Teams.id.asc())
|
||||
.paginate(page=page, per_page=50)
|
||||
.paginate(per_page=50)
|
||||
)
|
||||
|
||||
return render_template("teams/teams.html", teams=teams)
|
||||
args = dict(request.args)
|
||||
args.pop("page", 1)
|
||||
|
||||
return render_template(
|
||||
"teams/teams.html",
|
||||
teams=teams,
|
||||
prev_page=url_for(request.endpoint, page=teams.prev_num, **args),
|
||||
next_page=url_for(request.endpoint, page=teams.next_num, **args),
|
||||
q=q,
|
||||
field=field,
|
||||
)
|
||||
|
||||
|
||||
@teams.route("/teams/join", methods=["GET", "POST"])
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
</h6>
|
||||
{% endif %}
|
||||
|
||||
{% with form = Forms.teams.TeamSearchForm() %}
|
||||
{% with form = Forms.teams.TeamSearchForm(field=field, q=q) %}
|
||||
<form method="GET" class="form-inline">
|
||||
<div class="form-group col-md-2">
|
||||
{{ form.field(class="form-control custom-select w-100") }}
|
||||
|
||||
@@ -10,6 +10,37 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
{% if q and field %}
|
||||
<h5 class="text-muted text-center">
|
||||
Searching for teams with <strong>{{ field }}</strong> matching <strong>{{ q }}</strong>
|
||||
</h5>
|
||||
<h6 class="text-muted text-center pb-3">
|
||||
Page {{ teams.page }} of {{ teams.total }} results
|
||||
</h6>
|
||||
{% endif %}
|
||||
|
||||
{% with form = Forms.teams.PublicTeamSearchForm(field=field, q=q) %}
|
||||
<form method="GET" class="form-inline">
|
||||
<div class="form-group col-md-2">
|
||||
{{ form.field(class="form-control custom-select w-100") }}
|
||||
</div>
|
||||
<div class="form-group col-md-8">
|
||||
{{ form.q(class="form-control w-100", placeholder="Search for matching teams") }}
|
||||
</div>
|
||||
<div class="form-group col-md-2">
|
||||
<button type="submit" class="btn btn-primary w-100">
|
||||
<i class="fas fa-search" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endwith %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<table class="table table-striped">
|
||||
@@ -76,9 +107,7 @@
|
||||
<div class="text-center">Page
|
||||
<br>
|
||||
{% if teams.page != 1 %}
|
||||
<a href="{{ url_for('teams.listing', page=teams.page - 1) }}">
|
||||
<<<
|
||||
</a>
|
||||
<a href="{{ prev_page }}"><<<</a>
|
||||
{% endif %}
|
||||
<select class="page-select">
|
||||
{% for page in range(1, teams.pages + 1) %}
|
||||
@@ -86,9 +115,7 @@
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% if teams.next_num %}
|
||||
<a href="{{ url_for('teams.listing', page=teams.page + 1) }}">
|
||||
>>>
|
||||
</a>
|
||||
<a href="{{ next_page }}">>>></a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -10,6 +10,37 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
{% if q and field %}
|
||||
<h5 class="text-muted text-center">
|
||||
Searching for users with <strong>{{ field }}</strong> matching <strong>{{ q }}</strong>
|
||||
</h5>
|
||||
<h6 class="text-muted text-center pb-3">
|
||||
Page {{ users.page }} of {{ users.total }} results
|
||||
</h6>
|
||||
{% endif %}
|
||||
|
||||
{% with form = Forms.users.PublicUserSearchForm(field=field, q=q) %}
|
||||
<form method="GET" class="form-inline">
|
||||
<div class="form-group col-md-2">
|
||||
{{ form.field(class="form-control custom-select w-100") }}
|
||||
</div>
|
||||
<div class="form-group col-md-8">
|
||||
{{ form.q(class="form-control w-100", placeholder="Search for matching users") }}
|
||||
</div>
|
||||
<div class="form-group col-md-2">
|
||||
<button type="submit" class="btn btn-primary w-100">
|
||||
<i class="fas fa-search" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endwith %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<table class="table table-striped">
|
||||
@@ -79,9 +110,7 @@
|
||||
<div class="text-center">Page
|
||||
<br>
|
||||
{% if users.page != 1 %}
|
||||
<a href="{{ url_for('users.listing', page=users.page - 1) }}">
|
||||
<<<
|
||||
</a>
|
||||
<a href="{{ prev_page }}"><<<</a>
|
||||
{% endif %}
|
||||
<select class="page-select">
|
||||
{% for page in range(1, users.pages + 1) %}
|
||||
@@ -89,9 +118,7 @@
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% if users.next_num %}
|
||||
<a href="{{ url_for('users.listing', page=users.page + 1) }}">
|
||||
>>>
|
||||
</a>
|
||||
<a href="{{ next_page }}">>>></a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from flask import Blueprint, render_template, request
|
||||
from flask import Blueprint, render_template, request, url_for
|
||||
|
||||
from CTFd.models import Users
|
||||
from CTFd.utils import config
|
||||
@@ -16,15 +16,33 @@ users = Blueprint("users", __name__)
|
||||
@users.route("/users")
|
||||
@check_account_visibility
|
||||
def listing():
|
||||
page = abs(request.args.get("page", 1, type=int))
|
||||
q = request.args.get("q")
|
||||
field = request.args.get("field", "name")
|
||||
if field not in ("name", "affiliation", "website"):
|
||||
field = "name"
|
||||
|
||||
filters = []
|
||||
if q:
|
||||
filters.append(getattr(Users, field).like("%{}%".format(q)))
|
||||
|
||||
users = (
|
||||
Users.query.filter_by(banned=False, hidden=False)
|
||||
.filter(*filters)
|
||||
.order_by(Users.id.asc())
|
||||
.paginate(page=page, per_page=50)
|
||||
.paginate(per_page=50)
|
||||
)
|
||||
|
||||
return render_template("users/users.html", users=users)
|
||||
args = dict(request.args)
|
||||
args.pop("page", 1)
|
||||
|
||||
return render_template(
|
||||
"users/users.html",
|
||||
users=users,
|
||||
prev_page=url_for(request.endpoint, page=users.prev_num, **args),
|
||||
next_page=url_for(request.endpoint, page=users.next_num, **args),
|
||||
q=q,
|
||||
field=field,
|
||||
)
|
||||
|
||||
|
||||
@users.route("/profile")
|
||||
|
||||
Reference in New Issue
Block a user