]> git.ipfire.org Git - ipfire.org.git/commitdiff
people: Show some stats
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 21 Nov 2019 22:24:27 +0000 (22:24 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 21 Nov 2019 22:26:25 +0000 (22:26 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Makefile.am
src/backend/accounts.py
src/templates/base.html
src/templates/people/stats.html [new file with mode: 0644]
src/web/__init__.py
src/web/people.py

index 53574dff5a41edddbc6eb66aa45a01d1d17e66e5..2705ad26ba64d8ddcee5f034edd02ead6339a0d5 100644 (file)
@@ -275,6 +275,7 @@ templates_people_DATA = \
        src/templates/people/passwd.html \
        src/templates/people/search.html \
        src/templates/people/sip.html \
+       src/templates/people/stats.html \
        src/templates/people/subscribe.html \
        src/templates/people/subscribed.html \
        src/templates/people/unsubscribe.html \
index bc284bffc1063046953004505dab3c1ecb9b2162..ff2988c1a4879ae91fb5c3bd4ae2d965f64451eb 100644 (file)
@@ -5,6 +5,7 @@ import base64
 import datetime
 import hashlib
 import hmac
+import iso3166
 import json
 import ldap
 import ldap.modlist
@@ -164,6 +165,16 @@ class Accounts(Object):
        def init(self):
                self.search_base = self.settings.get("ldap_search_base")
 
+       def __len__(self):
+               count = self.memcache.get("accounts:count")
+
+               if count is None:
+                       count = self._count("(objectClass=person)")
+
+                       self.memcache.set("accounts:count", count, 300)
+
+               return count
+
        def __iter__(self):
                # Only return developers (group with ID 1000)
                accounts = self._search("(&(objectClass=posixAccount)(gidNumber=1000))")
@@ -206,6 +217,11 @@ class Accounts(Object):
 
                return results
 
+       def _count(self, query):
+               res = self._query(query, attrlist=["dn"])
+
+               return len(res)
+
        def _search(self, query, attrlist=None, limit=0):
                accounts = []
                for dn, attrs in self._query(query, attrlist=["dn"], limit=limit):
@@ -502,6 +518,18 @@ class Accounts(Object):
 
                return h.hexdigest()
 
+       @property
+       def countries(self):
+               ret = {}
+
+               for country in iso3166.countries:
+                       count = self._count("(&(objectClass=person)(st=%s))" % country.alpha2)
+
+                       if count:
+                               ret[country] = count
+
+               return ret
+
 
 class Account(LDAPObject):
        def __str__(self):
index 18ce5599d0231e03f32af58e9ac3e2735490bba9..b97712a66a3fd6f640a8202fcaac89204e8841d5 100644 (file)
                                                                                                {{ _("Groups") }}
                                                                                        </a>
                                                                                </li>
+
+                                                                               <li class="nav-item">
+                                                                                       <a class="nav-link {% if request.path == "/stats" %}active{% end %}" href="/stats">
+                                                                                               {{ _("Stats") }}
+                                                                                       </a>
+                                                                               </li>
                                                                        {% end %}
 
                                                                        {% if current_user.has_sip() %}
diff --git a/src/templates/people/stats.html b/src/templates/people/stats.html
new file mode 100644 (file)
index 0000000..6b92d14
--- /dev/null
@@ -0,0 +1,37 @@
+{% extends "../base.html" %}
+
+{% block title %}{{ _("Statistics") }}{% end block %}
+
+{% block content %}
+       <h1>{{ _("Statistics") }}</h1>
+
+       <div class="row">
+               <div class="col-12 col-lg-3">
+                       <div class="card">
+                               <div class="card-body text-center">
+                                       <h1>{{ len(backend.accounts) }}</h1>
+                                       <h5 class="mb-0">{{ _("Total Accounts") }}</h5>
+                               </div>
+                       </div>
+               </div>
+
+               <div class="col-12 col-lg-9">
+                       <div class="card">
+                               <div class="card-body">
+                                       <h4 class="mb-0">{{ _("By Country") }}</h4>
+                               </div>
+
+                               <ul class="list-group list-group-flush">
+                                       {% set countries = backend.accounts.countries %}
+
+                                       {% for country in sorted(countries, key=lambda c: countries[c], reverse=True) %}
+                                               <li class="list-group-item d-flex justify-content-between align-items-center">
+                                                       <span>{{ country.apolitical_name }}</span>
+                                                       <span>{{ countries[country] }}</span>
+                                               </li>
+                                       {% end %}
+                               </ul>
+                       </div>
+               </div>
+       </div>
+{% end block %}
index 9adb39cd064d8fb857f7d4b3f1a618648ab49dd6..6d6acf1138fbbd61693508bb76be44a64b8b6f6e 100644 (file)
@@ -296,6 +296,9 @@ class Application(tornado.web.Application):
                        (r"/password\-reset", auth.PasswordResetInitiationHandler),
                        (r"/password\-reset/([a-z_][a-z0-9_-]{0,31})/(\w+)", auth.PasswordResetHandler),
 
+                       # Stats
+                       (r"/stats", people.StatsHandler),
+
                        # API
                        (r"/api/check/uid", auth.APICheckUID),
                ]  + authentication_handlers)
index 1da6c27553cb3fb075097e7c23f0533cb2a37b93..1bd146d5b7b9b2e98149e90352e86ba7e85e257e 100644 (file)
@@ -221,6 +221,12 @@ class SearchHandler(auth.CacheMixin, base.BaseHandler):
                self.render("people/search.html", q=q, accounts=accounts)
 
 
+class StatsHandler(auth.CacheMixin, base.BaseHandler):
+       @tornado.web.authenticated
+       def get(self):
+               self.render("people/stats.html")
+
+
 class SubscribeHandler(auth.CacheMixin, base.BaseHandler):
        @tornado.web.authenticated
        def get(self):