From 888e2763f4ed6f851e01385de341b67dfdc01f2c Mon Sep 17 00:00:00 2001 From: Deimos Date: Thu, 28 Mar 2019 23:44:21 -0600 Subject: [PATCH] Add extremely minimal ban tool (admin only) This is very minimal and has some weird aspects, but at least it will let me be able to ban someone from my phone if it's necessary. --- tildes/tests/test_user.py | 8 ++++++++ tildes/tildes/models/user/user.py | 8 ++++++++ tildes/tildes/routes.py | 1 + tildes/tildes/templates/user.jinja2 | 16 ++++++++++++++++ tildes/tildes/views/api/web/user.py | 24 ++++++++++++++++++++++++ 5 files changed, 57 insertions(+) diff --git a/tildes/tests/test_user.py b/tildes/tests/test_user.py index ce278ad..8c77eef 100644 --- a/tildes/tests/test_user.py +++ b/tildes/tests/test_user.py @@ -134,3 +134,11 @@ def test_banned_user_no_message_permission(): principals = principals_allowed_by_permission(banned_user, "message") assert not principals + + +def test_only_admin_has_ban_permission(): + """Ensure only admins have ban permissions.""" + user = User("Test_User", "password") + + principals = principals_allowed_by_permission(user, "ban") + assert principals == {"admin"} diff --git a/tildes/tildes/models/user/user.py b/tildes/tildes/models/user/user.py index 6ef2233..7308e61 100644 --- a/tildes/tildes/models/user/user.py +++ b/tildes/tildes/models/user/user.py @@ -198,6 +198,14 @@ class User(DatabaseModel): acl.append((Deny, self.user_id, "message")) acl.append((Allow, Authenticated, "message")) + # ban: + # - admins can ban non-deleted users except themselves + if self.is_deleted: + acl.append((Deny, Everyone, "ban")) + + acl.append((Deny, self.user_id, "ban")) # required so users can't self-ban + acl.append((Allow, "admin", "ban")) + # grant the user all other permissions on themself acl.append((Allow, self.user_id, ALL_PERMISSIONS)) diff --git a/tildes/tildes/routes.py b/tildes/tildes/routes.py index 64b12c9..a805433 100644 --- a/tildes/tildes/routes.py +++ b/tildes/tildes/routes.py @@ -152,6 +152,7 @@ def add_intercooler_routes(config: Configurator) -> None: "/default_listing_options", factory=user_by_username, ) + add_ic_route("user_ban", "/ban", factory=user_by_username) class LoggedInFactory: diff --git a/tildes/tildes/templates/user.jinja2 b/tildes/tildes/templates/user.jinja2 index 4e05c24..68e971b 100644 --- a/tildes/tildes/templates/user.jinja2 +++ b/tildes/tildes/templates/user.jinja2 @@ -134,4 +134,20 @@ {% if request.has_permission('message', user) %} Send a private message {% endif %} + +{% if request.has_permission("ban", user) %} +
+ {% if user.is_banned %} + + {% else %} + + {% endif %} +{% endif %} + {% endblock %} diff --git a/tildes/tildes/views/api/web/user.py b/tildes/tildes/views/api/web/user.py index e071e0d..4686c96 100644 --- a/tildes/tildes/views/api/web/user.py +++ b/tildes/tildes/views/api/web/user.py @@ -329,3 +329,27 @@ def put_filtered_topic_tags(request: Request, tags: str) -> dict: request.user.filtered_topic_tags = result.data["tags"] return IC_NOOP + + +@ic_view_config(route_name="user_ban", request_method="PUT", permission="ban") +def put_user_ban(request: Request) -> Response: + """Ban a user.""" + user = request.context + + user.is_banned = True + + # delete all of the user's outstanding invite codes + request.query(UserInviteCode).filter( + UserInviteCode.user_id == user.user_id, + UserInviteCode.invitee_id == None, # noqa + ).delete(synchronize_session=False) + + return Response("Banned") + + +@ic_view_config(route_name="user_ban", request_method="DELETE", permission="ban") +def delete_user_ban(request: Request) -> Response: + """Unban a user.""" + request.context.is_banned = False + + return Response("Unbanned")