]> git.ipfire.org Git - ipfire.org.git/commitdiff
users: Create a page to bulk-delete recently joined accounts master
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 13 Sep 2025 10:11:21 +0000 (10:11 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 13 Sep 2025 10:11:21 +0000 (10:11 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Makefile.am
src/templates/users/index.html
src/templates/users/recently-joined.html [new file with mode: 0644]
src/web/__init__.py
src/web/users.py

index d016ba8995919e0762f9adfce4f9d632b6f7e0c4..1b1415cce2f28dd8c686ee82339b5bfbdadf60e1 100644 (file)
@@ -331,6 +331,7 @@ templates_users_DATA = \
        src/templates/users/edit.html \
        src/templates/users/index.html \
        src/templates/users/passwd.html \
+       src/templates/users/recently-joined.html \
        src/templates/users/show.html \
        src/templates/users/subscribe.html \
        src/templates/users/subscribed.html \
index 7d1f4659d7c3bc2712f83340825b8023effbfca0..3a36693e243e88363595322585cd877bfdf69065 100644 (file)
                {% if recently_registered %}
                        <section class="section">
                                <div class="container">
-                                       <h4 class="title is-4">{{ _("Recently Joined") }}</h4>
+                                       <h4 class="title is-4">
+                                               <a href="/users/recently-joined">
+                                                       {{ _("Recently Joined") }}
+                                               </a>
+                                       </h4>
 
                                        {% module UsersList(recently_registered, show_created_at=True) %}
                                </div>
diff --git a/src/templates/users/recently-joined.html b/src/templates/users/recently-joined.html
new file mode 100644 (file)
index 0000000..43b9f58
--- /dev/null
@@ -0,0 +1,122 @@
+{% extends "../base.html" %}
+
+{% block title %}{{ _("Users") }} - {{ _("Recently Joined") }}{% end block %}
+
+{% block container %}
+       <section class="hero is-dark">
+               <div class="hero-body">
+                       <div class="container">
+                               <nav class="breadcrumb" aria-label="breadcrumbs">
+                                       <ul>
+                                               <li>
+                                                       <a href="/">
+                                                               {{ _("Home") }}
+                                                       </a>
+                                               </li>
+
+                                               <li>
+                                                       <a href="/users">
+                                                               {{ _("Users") }}
+                                                       </a>
+                                               </li>
+
+                                               <li class="is-active">
+                                                       <a href="#" aria-current="page">
+                                                               {{ _("Recently Joined") }}
+                                                       </a>
+                                               </li>
+                                       </ul>
+                               </nav>
+
+                               <h1 class="title">{{ _("Recently Joined Users") }}</h1>
+                       </div>
+               </div>
+       </section>
+
+       <section class="section">
+               <div class="container">
+                       <form method="POST" action="">
+                               {% raw xsrf_form_html() %}
+
+                               <table class="table is-fullwidth is-hover">
+                                       <thead>
+                                               <tr>
+                                                       <th>
+                                                               {{ _("Name") }}
+                                                       </th>
+
+                                                       <th>
+                                                               {{ _("Username") }}
+                                                       </th>
+
+                                                       <th>
+                                                               {{ _("Email") }}
+                                                       </th>
+
+                                                       <th>
+                                                               {{ _("Country") }}
+                                                       </th>
+
+                                                       <th>
+                                                               {{ _("Joined At") }}
+                                                       </th>
+
+                                                       <th>
+                                                               {{ _("Delete?") }}
+                                                       </th>
+                                               </tr>
+                                       </thead>
+
+                                       <tbody>
+                                               {% for account in accounts %}
+                                                       <tr>
+                                                               {# Name #}
+                                                               <th scope="row">
+                                                                       <a href="/users/{{ account.uid }}">
+                                                                               {{ account }}
+                                                                       </a>
+                                                               </th>
+
+                                                               {# Username #}
+                                                               <td>
+                                                                       {{ account.uid }}
+                                                               </td>
+
+                                                               {# Email #}
+                                                               <td>
+                                                                       {{ account.email }}
+                                                               </td>
+
+                                                               {# Country Code #}
+                                                               <td>
+                                                                       {% if account.country_code %}
+                                                                               {{ format_country_name(account.country_code) }}
+                                                                       {% else %}
+                                                                               <span class="has-text-grey">
+                                                                                       {{ _("N/A") }}
+                                                                               </span>
+                                                                       {% end %}
+                                                               </td>
+
+                                                               {# Joined At #}
+                                                               <td>
+                                                                       {{ locale.format_date(account.created_at, shorter=True) }}
+                                                               </td>
+
+                                                               {# Delete? #}
+                                                               <td>
+                                                                       <input type="checkbox" name="users" value="{{ account.uid }}"
+                                                                               {% if not account.can_be_deleted_by(current_user) %}disabled{% end %}>
+                                                               </td>
+                                                       </tr>
+                                               {% end %}
+                                       </tbody>
+                               </table>
+
+                               <button type="submit" class="button is-danger is-fullwidth">
+                                       {{ _("Delete") }}
+                               </button>
+                       </form>
+               </div>
+       </section>
+{% end block %}
index 94df83106122c0aac8b1c2d88c8a7c69c913fed4..7fd663aa36e975aab7ac49ae4d8dc9c3fed4a50a 100644 (file)
@@ -217,6 +217,7 @@ class Application(tornado.web.Application):
 
                        # Users
                        (r"/users", users.IndexHandler),
+                       (r"/users/recently\-joined", users.RecentlyJoinedHandler),
                        (r"/users/([a-z_][a-z0-9_-]{0,31})", users.ShowHandler),
                        (r"/users/([a-z_][a-z0-9_-]{0,31})\.jpg", users.AvatarHandler),
                        (r"/users/([a-z_][a-z0-9_-]{0,31})/delete", users.DeleteHandler),
index a1b78dc0f6d0e49a669168974ae8a9418a23f65a..79d51db25c1f8059d295c6bc529b570aa7235aff 100644 (file)
@@ -31,6 +31,47 @@ class IndexHandler(base.AnalyticsMixin, base.BaseHandler):
                self.render("users/index.html", q=q, results=results)
 
 
+class RecentlyJoinedHandler(base.BaseHandler):
+       @tornado.web.authenticated
+       def get(self):
+               # Only staff can view this page
+               if not self.current_user.is_staff():
+                       raise tornado.web.HTTPError(403)
+
+               # Fetch the most recently 100 registered accounts
+               accounts = self.backend.accounts.get_recently_registered(limit=100)
+
+               self.render("users/recently-joined.html", accounts=accounts)
+
+       @tornado.web.authenticated
+       async def post(self):
+               # Only staff can view this page
+               if not self.current_user.is_staff():
+                       raise tornado.web.HTTPError(403)
+
+               # Fetch all selected accounts
+               accounts = [
+                       self.backend.accounts.get_by_uid(uid) for uid in self.get_arguments("users")
+               ]
+
+               # Filter out all accounts that could not be found
+               accounts = [
+                       account for account in accounts if account
+               ]
+
+               # Filter out everything that cannot be deleted by this user
+               accounts = [
+                       account for account in accounts if account.can_be_deleted_by(self.current_user)
+               ]
+
+               # Delete them all!
+               for account in accounts:
+                       with self.db.transaction():
+                               await account.delete(self.current_user)
+
+               self.redirect("/users/recently-joined")
+
+
 class ShowHandler(base.AnalyticsMixin, base.BaseHandler):
        @tornado.web.authenticated
        async def get(self, uid):