From 1cd4d7d35c5f0dc7fff33e7ee5c75444bc1cf043 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Wed, 28 Jun 2023 10:43:54 +0000 Subject: [PATCH] users: Add controls to delete a user Signed-off-by: Michael Tremer --- Makefile.am | 2 ++ src/backend/accounts.py | 4 +-- src/templates/users/delete.html | 44 ++++++++++++++++++++++++++++++++ src/templates/users/deleted.html | 19 ++++++++++++++ src/templates/users/show.html | 9 +++++-- src/web/__init__.py | 1 + src/web/users.py | 30 ++++++++++++++++++++++ 7 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 src/templates/users/delete.html create mode 100644 src/templates/users/deleted.html diff --git a/Makefile.am b/Makefile.am index 85762aef..fbf9d3bd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -307,6 +307,8 @@ templates_static_DATA = \ templates_staticdir = $(templatesdir)/static templates_users_DATA = \ + src/templates/users/delete.html \ + src/templates/users/deleted.html \ src/templates/users/edit.html \ src/templates/users/index.html \ src/templates/users/passwd.html \ diff --git a/src/backend/accounts.py b/src/backend/accounts.py index d6e2d749..a8269764 100644 --- a/src/backend/accounts.py +++ b/src/backend/accounts.py @@ -869,7 +869,7 @@ class Account(LDAPObject): Deletes this user """ # Check if this user can be deleted - if not self.can_be_deleted(user): + if not self.can_be_deleted_by(user): raise RuntimeError("Cannot delete user %s" % self) async with asyncio.TaskGroup() as tasks: @@ -884,7 +884,7 @@ class Account(LDAPObject): # XXX Delete on LDAP - def can_be_deleted(self, user): + def can_be_deleted_by(self, user): """ Return True if the user can be deleted by user """ diff --git a/src/templates/users/delete.html b/src/templates/users/delete.html new file mode 100644 index 00000000..9b0367a0 --- /dev/null +++ b/src/templates/users/delete.html @@ -0,0 +1,44 @@ +{% extends "../base.html" %} + +{% block title %}{{ _("Delete %s") % account }}{% end block %} + +{% block container %} +
+
+
+
+

+ {{ _("Delete User") }} +

+

{{ account }}

+ +
+
+ {% raw xsrf_form_html() %} + + {% if next %}{% end %} + +
+

+ {{ _("Are you sure you want to delete %s?") % account }} +

+ +

+ {{ _("This cannot be undone.") }} +

+
+ +
+
+ +
+
+
+
+
+
+
+
+{% end block %} diff --git a/src/templates/users/deleted.html b/src/templates/users/deleted.html new file mode 100644 index 00000000..d277928f --- /dev/null +++ b/src/templates/users/deleted.html @@ -0,0 +1,19 @@ +{% extends "../base.html" %} + +{% block title %}{{ _("%s Deleted") % account }}{% end block %} + +{% block container %} +
+
+
+
+
+

+ {{ _("%s has been successfully deleted") % account }} +

+
+
+
+
+
+{% end block %} diff --git a/src/templates/users/show.html b/src/templates/users/show.html index 644a95bf..842f11ed 100644 --- a/src/templates/users/show.html +++ b/src/templates/users/show.html @@ -95,12 +95,17 @@ {% end %} + + {{ _("Change Password") }} + + {{ _("Edit") }} - - {{ _("Change Password") }} + + {{ _("Delete") }} {% end %} diff --git a/src/web/__init__.py b/src/web/__init__.py index 024f84c6..72e22ab2 100644 --- a/src/web/__init__.py +++ b/src/web/__init__.py @@ -168,6 +168,7 @@ class Application(tornado.web.Application): (r"/users", users.IndexHandler), (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), (r"/users/([a-z_][a-z0-9_-]{0,31})/edit", users.EditHandler), (r"/users/([a-z_][a-z0-9_-]{0,31})/passwd", users.PasswdHandler), diff --git a/src/web/users.py b/src/web/users.py index a1572d83..6dee34b9 100644 --- a/src/web/users.py +++ b/src/web/users.py @@ -203,6 +203,36 @@ class EditHandler(base.BaseHandler): self.redirect("/users/%s" % account.uid) +class DeleteHandler(base.BaseHandler): + @tornado.web.authenticated + def get(self, uid): + account = self.backend.accounts.get_by_uid(uid) + if not account: + raise tornado.web.HTTPError(404, "Could not find account %s" % uid) + + # Check for permissions + if not account.can_be_deleted_by(self.current_user): + raise tornado.web.HTTPError(403, "%s cannot delete %s" % (self.current_user, account)) + + self.render("users/delete.html", account=account) + + @tornado.web.authenticated + async def post(self, uid): + account = self.backend.accounts.get_by_uid(uid) + if not account: + raise tornado.web.HTTPError(404, "Could not find account %s" % uid) + + # Check for permissions + if not account.can_be_deleted_by(self.current_user): + raise tornado.web.HTTPError(403, "%s cannot delete %s" % (self.current_user, account)) + + # Delete! + with self.db.transaction(): + await account.delete(self.current_user) + + self.render("users/deleted.html", account=account) + + class PasswdHandler(base.BaseHandler): @tornado.web.authenticated def get(self, uid): -- 2.39.2