Skip to content

Commit fca37ea

Browse files
authored
UI Add /manage_users admin page with a list of users (#538)
1 parent a729de1 commit fca37ea

File tree

5 files changed

+153
-0
lines changed

5 files changed

+153
-0
lines changed

doc/whats_new/v0.9.rst

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Changelog
2121
...............
2222

2323
- The list of users to approve are sorted by newest first :pr:`537`
24+
- Add a ``/manage_users`` admin page with a list of all users, and a search input :pr:`538`
2425

2526

2627
`ramp-utils`

ramp-frontend/ramp_frontend/templates/base.html

+2
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ <h4 class="username">{{ current_user.name }}</h4>
142142
{% if admin %}
143143
<li><a href="/approve_users"><span class="icon fa fa-user-plus"></span><span
144144
class="title">Approve users</span></a></li>
145+
<li><a href="/manage_users"><span class="icon fa fa-user"></span><span
146+
class="title">Manage users</span></a></li>
145147
{% endif %}
146148
<li>
147149
<a href="/problems">
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
{% extends "base.html" %} {% block title %}List of users{% endblock %}
2+
3+
<!-- block separation -->
4+
{% block head %} {{ super() }}
5+
6+
<link
7+
rel="stylesheet"
8+
type="text/css"
9+
href="https://cdn.datatables.net/1.10.24/css/jquery.dataTables.min.css"
10+
/>
11+
<script src="https://cdn.datatables.net/1.10.24/js/jquery.dataTables.min.js"></script>
12+
{% endblock %} {% block content %} {% with messages = get_flashed_messages() %}
13+
{% if messages %}
14+
<div
15+
class="modal fade modal-warning"
16+
id="formerror"
17+
tabindex="-1"
18+
role="dialog"
19+
aria-labelledby="myModalLabel"
20+
aria-hidden="true"
21+
>
22+
<div class="modal-dialog">
23+
<div class="modal-content">
24+
<div class="modal-header">
25+
<button
26+
type="button"
27+
class="close"
28+
data-dismiss="modal"
29+
aria-label="Close"
30+
>
31+
<span aria-hidden="true">&times;</span>
32+
</button>
33+
<h4 class="modal-title" id="myModalLabel">Login Error</h4>
34+
</div>
35+
<div class="modal-body">
36+
<div class="modal-message">
37+
{% for message in messages %} {{ message }} {% endfor %}
38+
</div>
39+
</div>
40+
<div class="modal-footer">
41+
<button type="button" class="btn btn-warning" data-dismiss="modal">
42+
Close
43+
</button>
44+
</div>
45+
</div>
46+
</div>
47+
</div>
48+
{% endif %} {% endwith %}
49+
50+
<div class="container">
51+
<div class="row">
52+
<form method="post">
53+
<div class="card">
54+
<div class="card-header">
55+
<div class="card-title">
56+
<div class="title">List of all users<br /></div>
57+
</div>
58+
</div>
59+
<div class="card-body">
60+
<div class="row">
61+
<div class="col-sm-12 col-lg-12">
62+
<table
63+
id="user-table"
64+
class="display"
65+
style="width: 100%; font-size: 70%"
66+
>
67+
<thead>
68+
<tr>
69+
<th>id</th>
70+
<th>Username</th>
71+
<th>First name</th>
72+
<th>Last name</th>
73+
<th>Email</th>
74+
<th>Access level</th>
75+
<th>Signup date</th>
76+
</tr>
77+
</thead>
78+
<tbody>
79+
{% for user in all_users %}
80+
<tr>
81+
<td>{{ user.id }}</td>
82+
<td>{{ user.name }}</td>
83+
<td>{{ user.firstname }}</td>
84+
<td>{{ user.lastname }}</td>
85+
<td>{{ user.email }}</td>
86+
<td>{{ user.access_level }}</td>
87+
<td>{{ user.signup_timestamp }}</td>
88+
</tr>
89+
{% endfor %}
90+
</tbody>
91+
</table>
92+
</div>
93+
</div>
94+
</div>
95+
</div>
96+
</form>
97+
</div>
98+
</div>
99+
100+
{% endblock %}
101+
<!-- block separation -->
102+
{% block scripts %}
103+
<script>
104+
$(document).ready(function () {
105+
$("#user-table").DataTable({
106+
pageLength: 50,
107+
ordering: true,
108+
//order: [(9, "desc")],
109+
});
110+
});
111+
</script>
112+
{% endblock %}

ramp-frontend/ramp_frontend/tests/test_admin.py

+18
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ def client_session(database_connection):
5252
@pytest.mark.parametrize(
5353
"page",
5454
["/approve_users",
55+
"/manage_users",
5556
"/sign_up/test_user",
5657
"/events/iris_test/sign_up/test_user",
5758
"/events/iris_test/update",
@@ -71,6 +72,7 @@ def test_check_login_required(client_session, page):
7172
@pytest.mark.parametrize(
7273
"page, request_function",
7374
[("/approve_users", ["get", "post"]),
75+
('/manage_users', ['get']),
7476
("/sign_up/test_user", ["get"]),
7577
("/events/iris_test/sign_up/test_user", ["get"]),
7678
("/events/iris_test/update", ["get", "post"]),
@@ -243,6 +245,22 @@ def test_approve_sign_up_for_event(client_session):
243245
assert "is signed up for Event" in flash_message['Successful sign-up']
244246

245247

248+
def test_manage_users(client_session):
249+
client, session = client_session
250+
251+
# create 2 new users
252+
add_user(session, 'ff', 'ff', 'ff', 'ff', 'ff', access_level='user')
253+
add_user(session, 'll', 'll', 'll', 'll', 'll', access_level='asked')
254+
# ask for sign up for an event for the first user
255+
_, _, event_team = ask_sign_up_team(session, 'iris_test', 'xx')
256+
257+
with login_scope(client, 'test_iris_admin', 'test') as client:
258+
# GET check that we get all users
259+
rv = client.get('/manage_users')
260+
assert rv.status_code == 200
261+
# assert b'yy yy - yy' in rv.data
262+
263+
246264
def test_update_event(client_session):
247265
client, session = client_session
248266

ramp-frontend/ramp_frontend/views/admin.py

+20
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,26 @@ def approve_users():
119119
)
120120

121121

122+
@mod.route("/manage_users", methods=['GET'])
123+
@flask_login.login_required
124+
def manage_users():
125+
"""Get a list of users"""
126+
if not flask_login.current_user.access_level == 'admin':
127+
return redirect_to_user(
128+
(f'Sorry {flask_login.current_user.firstname}, '
129+
f'you do not have admin rights'),
130+
is_error=True
131+
)
132+
all_users = (
133+
User.query
134+
.order_by(User.signup_timestamp.desc())
135+
.all()
136+
)
137+
return render_template('manage_users.html',
138+
all_users=all_users,
139+
admin=True)
140+
141+
122142
@mod.route("/sign_up/<user_name>")
123143
@flask_login.login_required
124144
def approve_single_user(user_name):

0 commit comments

Comments
 (0)