From: Michael Tremer Date: Sat, 13 Sep 2025 10:11:21 +0000 (+0000) Subject: users: Create a page to bulk-delete recently joined accounts X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;ds=sidebyside;p=ipfire.org.git users: Create a page to bulk-delete recently joined accounts Signed-off-by: Michael Tremer --- diff --git a/Makefile.am b/Makefile.am index d016ba89..1b1415cc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 \ diff --git a/src/templates/users/index.html b/src/templates/users/index.html index 7d1f4659..3a36693e 100644 --- a/src/templates/users/index.html +++ b/src/templates/users/index.html @@ -78,7 +78,11 @@ {% if recently_registered %}
-

{{ _("Recently Joined") }}

+

+ + {{ _("Recently Joined") }} + +

{% module UsersList(recently_registered, show_created_at=True) %}
diff --git a/src/templates/users/recently-joined.html b/src/templates/users/recently-joined.html new file mode 100644 index 00000000..43b9f58d --- /dev/null +++ b/src/templates/users/recently-joined.html @@ -0,0 +1,122 @@ +{% extends "../base.html" %} + +{% block title %}{{ _("Users") }} - {{ _("Recently Joined") }}{% end block %} + +{% block container %} +
+
+
+ + +

{{ _("Recently Joined Users") }}

+
+
+
+ +
+
+
+ {% raw xsrf_form_html() %} + + + + + + + + + + + + + + + + + + + + {% for account in accounts %} + + {# Name #} + + + {# Username #} + + + {# Email #} + + + {# Country Code #} + + + {# Joined At #} + + + {# Delete? #} + + + {% end %} + +
+ {{ _("Name") }} + + {{ _("Username") }} + + {{ _("Email") }} + + {{ _("Country") }} + + {{ _("Joined At") }} + + {{ _("Delete?") }} +
+ + {{ account }} + + + {{ account.uid }} + + {{ account.email }} + + {% if account.country_code %} + {{ format_country_name(account.country_code) }} + {% else %} + + {{ _("N/A") }} + + {% end %} + + {{ locale.format_date(account.created_at, shorter=True) }} + + +
+ + +
+
+
+{% end block %} diff --git a/src/web/__init__.py b/src/web/__init__.py index 94df8310..7fd663aa 100644 --- a/src/web/__init__.py +++ b/src/web/__init__.py @@ -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), diff --git a/src/web/users.py b/src/web/users.py index a1b78dc0..79d51db2 100644 --- a/src/web/users.py +++ b/src/web/users.py @@ -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):