add /tu/ (get) index

This commit implements the '/tu' Trusted User index page.

In addition to this functionality, this commit introduces
the following jinja2 filters:

- dt: util.timestamp_to_datetime
- as_timezone: util.as_timezone
- dedupe_qs: util.dedupe_qs
- urlencode: urllib.parse.quote_plus

There's also a new decorator that can be used to enforce
permissions: `account_type_required`. If a user does not
meet account type requirements, they are redirected to '/'.

```
@auth_required(True)
@account_type_required({"Trusted User"})
async def some_route(request: fastapi.Request):
    return Response("You are a Trusted User!")
```

Routes added:

- `GET /tu`: aurweb.routers.trusted_user.trusted_user

Signed-off-by: Kevin Morris <kevr@0cost.org>
This commit is contained in:
Kevin Morris 2021-06-18 04:33:48 -07:00
parent a6bba601a9
commit d674aaf736
10 changed files with 808 additions and 3 deletions

View file

@ -7,11 +7,29 @@
{% endif %}
<li><a href="/packages/">{% trans %}Packages{% endtrans %}</a></li>
{% if request.user.is_authenticated() %}
{% if request.user.is_trusted_user() or request.user.is_developer() %}
<li>
<a href="/requests/">{% trans %}Requests{% endtrans %}</a>
</li>
<li>
<a href="/accounts/">{% trans %}Accounts{% endtrans %}</a>
</li>
{% endif %}
<li>
<a href="/account/{{ request.user.Username }}/edit">
{% trans %}My Account{% endtrans %}
</a>
</li>
{% if request.user.is_trusted_user() %}
<li>
<a href="/tu">{% trans %}Trusted User{% endtrans %}</a>
</li>
{% endif %}
<li>
<a href="/logout/?next={{ next }}">
{% trans %}Logout{% endtrans %}

View file

@ -0,0 +1,33 @@
<div class="box">
<h2>{% trans %}{{ title }}{% endtrans %}</h2>
<table class="results last-votes">
<thead>
<th>{{ "User" | tr }}</th>
<th>{{ "Last vote" | tr }}</th>
</thead>
<tbody>
{% if not votes %}
<tr>
<td align="center" colspan="0">
{{ "No results found." | tr }}
</td>
<td></td>
</tr>
{% else %}
{% for vote in votes %}
<tr>
<td>{{ vote.User.Username }}</td>
<td>
<a href="/tu/{{ vote.VoteID }}">
{{ vote.VoteID }}
</a>
</td>
</tr>
{% endfor %}
{% endif %}
</tbody>
</table>
</div>

View file

@ -0,0 +1,120 @@
<div class="box">
<h2>{% trans %}{{ title }}{% endtrans %}</h2>
{% if title == "Current Votes" %}
<ul class="admin-actions">
<li>
<a href="/addvote/">
{% trans %}Add Proposal{% endtrans %}
</a>
</li>
</ul>
{% endif %}
{% if not results %}
<p>
{% trans %}No results found.{% endtrans %}
</p>
{% else %}
<table class="results {{ table_class }}">
<thead>
<tr>
<th>{{ "Proposal" | tr }}</th>
<th>
{% set off_qs = "%s=%d" | format(off_param, off) %}
{% set by_qs = "%s=%s" | format(by_param, by_next | urlencode) %}
<a href="?{{ q | dedupe_qs(off_qs, by_qs) }}">
{{ "Start" | tr }}
</a>
</th>
<th>{{ "End" | tr }}</th>
<th>{{ "User" | tr }}</th>
{% if title != "Current Votes" %}
<th>{{ "Yes" | tr }}</th>
<th>{{ "No" | tr }}</th>
{% endif %}
<th>{{ "Voted" | tr }}</th>
</tr>
</thead>
<tbody>
{% for result in results %}
<tr>
<td>
<!-- Truncate the agenda back to prev_len. -->
{% set agenda = result.Agenda[:prev_len] %}
<a href="/tu/{{ result.ID }}">{{ agenda }}</a>
</td>
<!-- Convert result.Submitted (timestamp) to datetime,
then apply the request's timezone to it. -->
{% set submitted = result.Submitted | dt | as_timezone(timezone) %}
<td>{{ submitted.strftime("%Y-%m-%d") }}</td>
<!-- Convert result.End (timestamp) to datetime,
then apply the request's timezone to it. -->
{% set end = result.End | dt | as_timezone(timezone) %}
<td>{{ end.strftime("%Y-%m-%d") }}</td>
<td>
{% if not result.User %}
N/A
{% else %}
<a href="/packages/?K={{ result.User }}&amp;SeB=m">
{{ result.User }}
</a>
{% endif %}
</td>
{% if title != "Current Votes" %}
<td>{{ result.Yes }}</td>
<td>{{ result.No }}</td>
{% endif %}
{% set vote = (result | get_vote(request)) %}
<td>
{% if vote %}
<span style="color: green; font-weight: bold">
{{ "Yes" | tr }}
</span>
{% else %}
<span style="color: red; font-weight: bold">
{{ "No" | tr }}
</span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pkglist-stats">
<p class="pkglist-nav">
{% if total_votes > pp %}
{% if off > 0 %}
{% set off_qs = "%s=%d" | format(off_param, off - 10) %}
{% set by_qs = "%s=%s" | format(by_param, by | urlencode) %}
<a class="page"
href="?{{ q | dedupe_qs(off_qs, by_qs) }}">
Back
</a>
{% endif %}
{% if off < total_votes - pp %}
{% set off_qs = "%s=%d" | format(off_param, off + 10) %}
{% set by_qs = "%s=%s" | format(by_param, by | urlencode) %}
<a class="page"
href="?{{ q | dedupe_qs(off_qs, by_qs) }}">
Next
</a>
{% endif %}
{% endif %}
</p>
</div>
{% endif %}
</div>

35
templates/tu/index.html Normal file
View file

@ -0,0 +1,35 @@
{% extends "partials/layout.html" %}
{% block pageContent %}
{%
with table_class = "current-votes",
total_votes = current_votes_count,
results = current_votes,
off_param = "coff",
by_param = "cby",
by_next = current_by_next,
title = "Current Votes",
off = current_off,
by = current_by
%}
{% include "partials/tu/proposals.html" %}
{% endwith %}
{%
with table_class = "past-votes",
total_votes = past_votes_count,
results = past_votes,
off_param = "poff",
by_param = "pby",
by_next = past_by_next,
title = "Past Votes",
off = past_off,
by = past_by
%}
{% include "partials/tu/proposals.html" %}
{% endwith %}
{% with title = "Last Votes by TU", votes = last_votes_by_tu %}
{% include "partials/tu/last_votes.html" %}
{% endwith %}
{% endblock %}