Add doorboy admin view
All checks were successful
ci/woodpecker/manual/woodpecker Pipeline was successful

This commit is contained in:
Madis Mägi 2023-08-13 06:50:57 +03:00
parent 4b79a5e353
commit 73409d175a
3 changed files with 98 additions and 1 deletions

View File

@ -9,7 +9,7 @@ from wtforms import StringField, IntegerField, SelectField, BooleanField, DateTi
from wtforms.validators import DataRequired
import const
from common import spam, users_lookup, User
from common import spam, users_lookup, users, User
from oidc import login_required, read_user
page_doorboy = Blueprint("doorboy", __name__)
@ -194,6 +194,35 @@ def view_doorboy():
latest_swipes = db.inventory.find({"component": "doorboy", "type":"token"}).sort([("last_seen", -1)]).limit(10);
return render_template("doorboy.html", **locals())
@page_doorboy.route("/m/doorboy/admin")
@login_required(groups=["k-space:admins"])
def view_doorboy_admin():
results = db.inventory.aggregate([
{ "$match": {"component": "doorboy", "type": "token"} },
{
"$group": {
"_id": "$inventory.owner.username",
"cards": {
"$push" : {"$mergeObjects": [
"$token",
{"last_seen": "$last_seen"},
{"_id": "$_id"}
]}
}
}
},
{ "$sort": { "_id" : 1 } }
])
user_keyfobs = {r["_id"] : r["cards"] for r in results}
orphaned_keyfobs = user_keyfobs.pop(None)
no_keyfobs = [u for u in users if not user_keyfobs.get(u.username)]
last_seen = {key : max(card.get("last_seen") for card in value) for key, value in user_keyfobs.items()}
orphaned_keyfobs = sorted(orphaned_keyfobs, key = lambda o : (not bool(o.get("comment")), o.get("comment", "")))
no_keyfobs = sorted(no_keyfobs, key = lambda u : u.display_name or u.username)
last_seen = dict(sorted(last_seen.items(), key = lambda item: item[1], reverse=True))
return render_template("doorboy_admin.html", **locals())
@page_doorboy.route("/m/doorboy/swipes")
@login_required

View File

@ -99,6 +99,9 @@ body {
var elems = document.querySelectorAll('.materialboxed');
var instances = M.Materialbox.init(elems, {});
var elems = document.querySelectorAll('.collapsible.expandable');
var instances = M.Collapsible.init(elems, {accordion: false});
});
</script>
</body>

View File

@ -0,0 +1,65 @@
{% extends 'base.html' %}
{% block content %}
<ul class="collapsible expandable">
<li class="">
<div class="collapsible-header">
<i class="material-icons">access_time</i>Last seen
<div style="margin-left: auto;">
{{last_seen | length}}
</div>
</div>
<ul class="collapsible-body collection collapsible-collection">
{% for u, t in last_seen.items() %}
<li class="collection-item">
<i class="material-icons tiny">person</i>
{{u | display_name}}
<div class="secondary-content black-text">
<i class="material-icons tiny">access_time</i>
{{t | timeago}}
</div>
</li>
{% endfor %}
</ul>
</li>
<li>
<div class="red lighten-3 collapsible-header">
<i class="material-icons">error_outline</i>No keyfobs enrolled
<div style="margin-left: auto;">
{{no_keyfobs | length}}
</div>
</div>
<div class="collapsible-body collection collapsible-collection">
{% for u in no_keyfobs %}
<div class="collection-item">{{u.display_name or u.username}}</div>
{% endfor %}
</div>
</li>
<li>
<div class="red lighten-3 collapsible-header">
<i class="material-icons">error</i>Orphaned keyfobs
<div style="margin-left: auto;">
{{orphaned_keyfobs | length}}
</div>
</div>
<ul class="collapsible-body collection collapsible-collection">
{% for c in orphaned_keyfobs %}
<li class="collection-item">
{{c.comment or "unnamed"}}
<div class="secondary-content">
<a href="/m/doorboy/{{ c._id }}/events">{{ c.uid_hash[-6:] }}</a>
</div>
</li>
{% endfor %}
</ul>
</li>
</ul>
<style>
.collapsible-collection {
padding: 0;
}
</style>
{% endblock %}