Skip to content

Commit

Permalink
Add search for users feature
Browse files Browse the repository at this point in the history
Closes #212
#239
  • Loading branch information
jdabtieu committed Dec 15, 2023
1 parent 3d6448d commit ec7dc81
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 65 deletions.
139 changes: 78 additions & 61 deletions src/templates/admin/users.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,67 +13,84 @@ <h1>Users</h1>
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
</form>
</div>
<div style="overflow-x: auto;">
<table class="table table-hover table-full-width">
<thead class="table-dark">
<tr>
<th scope="col" style="width: 10%;">ID</th>
<th scope="col" style="width: 20%;">Username</th>
<th scope="col" style="width: 20%;">Email</th>
<th scope="col" style="width: 20%;">Join Date</th>
<th scope="col" style="width: 15%;">Perms</th>
<th scope="col" style="width: 15%;">Actions</th>
</tr>
</thead>
<tbody>
{% for row in data %}
<tr>
<td class="userid">{{ row["id"] }}</td>
<td class="username
{{ 'user-ban' if row['banned'] }}">
<a href="/users/{{ row['username'] }}/profile"
class="username
{{ 'user-ban' if row['banned'] }}">
{{ row["username"] }}
</a>
</td>
<td>{{ row["email"] }}</td>
<td class="dt">{{ row["join_date"] }}</td>
<td>
<form method="POST" action="/admin/updateperms?user_id={{ row['id'] }}" class="perm-select">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
<select multiple name="perms" style="height: 0px; visibility: hidden;"
multiselect-hide-x = "false">
{% for name, id in perm_list.items() %}
<option value="{{ id }}"
{{ 'selected' if disp_perms.get(row['id']) and disp_perms[row['id']].get(id) }}>
{{ name }}
</option>
{% endfor %}
</select>
<input type="submit" value="Update">
</form>
</td>
<td data-id="{{ row['id'] }}" data-username="{{ row['username'] }}">
<a href="#">
<img src="/assets/images/restrict.svg"
onerror="this.src='/assets/images/restrict.png'"
class="svg-red icon users-ban"
alt="Ban/Unban user"
title="Ban/Unban user">
</a>
<a href="#">
<img src="/assets/images/key.svg"
onerror="this.src='/assets/images/key.png'"
class="icon users-resetpass"
alt="Reset password"
title="Reset password">
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="flex-desktop">
<div style="flex: 3; overflow-x: auto;">
<table class="table table-hover table-full-width">
<thead class="table-dark">
<tr>
<th scope="col" style="width: 10%;">ID</th>
<th scope="col" style="width: 20%;">Username</th>
<th scope="col" style="width: 20%;">Email</th>
<th scope="col" style="width: 20%;">Join Date</th>
<th scope="col" style="width: 15%;">Perms</th>
<th scope="col" style="width: 15%;">Actions</th>
</tr>
</thead>
<tbody>
{% for row in data %}
<tr>
<td class="userid">{{ row["id"] }}</td>
<td class="username
{{ 'user-ban' if row['banned'] }}">
<a href="/users/{{ row['username'] }}/profile"
class="username
{{ 'user-ban' if row['banned'] }}">
{{ row["username"] }}
</a>
</td>
<td>{{ row["email"] }}</td>
<td class="dt">{{ row["join_date"] }}</td>
<td>
<form method="POST" action="/admin/updateperms?user_id={{ row['id'] }}" class="perm-select">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
<select multiple name="perms" style="height: 0px; visibility: hidden;"
multiselect-hide-x = "false">
{% for name, id in perm_list.items() %}
<option value="{{ id }}"
{{ 'selected' if disp_perms.get(row['id']) and disp_perms[row['id']].get(id) }}>
{{ name }}
</option>
{% endfor %}
</select>
<input type="submit" value="Update">
</form>
</td>
<td data-id="{{ row['id'] }}" data-username="{{ row['username'] }}">
<a href="#">
<img src="/assets/images/restrict.svg"
onerror="this.src='/assets/images/restrict.png'"
class="svg-red icon users-ban"
alt="Ban/Unban user"
title="Ban/Unban user">
</a>
<a href="#">
<img src="/assets/images/key.svg"
onerror="this.src='/assets/images/key.png'"
class="icon users-resetpass"
alt="Reset password"
title="Reset password">
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div style="flex: 1; margin-left: 8px;">
<div class="card">
<h3>Search Users</h3>
<form>
<div class="form-floating">
<input class="form-control mb-3"
id="search-q"
name="q"
placeholder="Username / Email">
<label for="search-q">Username / Email</label>
</div>
<input class="btn btn-primary" type="submit" value="Search">
</form>
</div>
</div>
</div>
{% endblock %}
{% block script %}
Expand Down
6 changes: 6 additions & 0 deletions src/tests/test_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,12 @@ def test_admin(client, database):
database.execute("INSERT INTO user_perms VALUES(1, ?)", USER_PERM["SUPERADMIN"])
client.post('/login', data={'username': 'admin', 'password': 'CTFOJadmin'})

result = client.get('/admin/users?q=admin')
assert result.status_code == 200
assert b'e1' in result.data
assert b'normal_user' not in result.data


result = client.post('/admin/updateperms?user_id=2', follow_redirects=True)
assert result.status_code == 200
assert b"Revoked [&#39;ADMIN&#39;]" in result.data
Expand Down
17 changes: 13 additions & 4 deletions src/views/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,25 @@ def admin_submissions():
@api.route("/users")
@admin_required
def admin_users():
query = request.args.get("q")
modifier = ""
args = []
if query:
modifier = "WHERE username LIKE ? OR email LIKE ?"
query = '%' + query + '%'
args = [query, query]

page = request.args.get("page")
if not page:
page = "1"
page = (int(page) - 1) * 50

data = db.execute("SELECT * FROM users ORDER BY id ASC LIMIT 50 OFFSET ?", page)
length = db.execute("SELECT COUNT(*) AS cnt FROM users")[0]["cnt"]
data = db.execute((f"SELECT * FROM users {modifier} ORDER BY id ASC "
"LIMIT 50 OFFSET ?"), *args, page)
length = db.execute(f"SELECT COUNT(*) AS cnt FROM users {modifier}", *args)[0]["cnt"]

perms = db.execute(("SELECT * FROM user_perms WHERE user_id IN "
"(SELECT id FROM users ORDER BY id ASC LIMIT 50 OFFSET ?)"), page)
perms = db.execute("SELECT * FROM user_perms WHERE user_id IN (?)",
[u["id"] for u in data])
disp_perms = {}
for perm in perms:
if perm["user_id"] not in disp_perms:
Expand Down

0 comments on commit ec7dc81

Please sign in to comment.