From e87ba0d2a923d2111c44d8d6ae540d0a1a622c03 Mon Sep 17 00:00:00 2001 From: Deimos Date: Wed, 22 Aug 2018 18:24:52 -0600 Subject: [PATCH] Add admin tool for removing topics --- ...b6c5_add_admin_tool_for_removing_topics.py | 36 +++++++++++++++++++ tildes/tildes/enums.py | 2 ++ tildes/tildes/models/log/log.py | 5 +++ tildes/tildes/models/topic/topic.py | 2 ++ tildes/tildes/routes.py | 1 + tildes/tildes/templates/topic.jinja2 | 26 +++++++++++++- tildes/tildes/views/api/web/topic.py | 22 ++++++++++++ tildes/tildes/views/topic.py | 2 ++ 8 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 tildes/alembic/versions/bcf1406bb6c5_add_admin_tool_for_removing_topics.py diff --git a/tildes/alembic/versions/bcf1406bb6c5_add_admin_tool_for_removing_topics.py b/tildes/alembic/versions/bcf1406bb6c5_add_admin_tool_for_removing_topics.py new file mode 100644 index 0000000..dae0173 --- /dev/null +++ b/tildes/alembic/versions/bcf1406bb6c5_add_admin_tool_for_removing_topics.py @@ -0,0 +1,36 @@ +"""Add admin tool for removing topics + +Revision ID: bcf1406bb6c5 +Revises: 50c251c4a19c +Create Date: 2018-08-22 23:56:41.733065 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = "bcf1406bb6c5" +down_revision = "50c251c4a19c" +branch_labels = None +depends_on = None + + +def upgrade(): + # ALTER TYPE doesn't work from inside a transaction, disable it + connection = None + if not op.get_context().as_sql: + connection = op.get_bind() + connection.execution_options(isolation_level="AUTOCOMMIT") + + op.execute("ALTER TYPE logeventtype ADD VALUE IF NOT EXISTS 'TOPIC_REMOVE'") + op.execute("ALTER TYPE logeventtype ADD VALUE IF NOT EXISTS 'TOPIC_UNREMOVE'") + + # re-activate the transaction for any future migrations + if connection is not None: + connection.execution_options(isolation_level="READ_COMMITTED") + + +def downgrade(): + # no way to remove enum values, just do nothing + pass diff --git a/tildes/tildes/enums.py b/tildes/tildes/enums.py index 18c50ec..a7bfc92 100644 --- a/tildes/tildes/enums.py +++ b/tildes/tildes/enums.py @@ -51,9 +51,11 @@ class LogEventType(enum.Enum): TOPIC_LOCK = enum.auto() TOPIC_MOVE = enum.auto() TOPIC_POST = enum.auto() + TOPIC_REMOVE = enum.auto() TOPIC_TAG = enum.auto() TOPIC_TITLE_EDIT = enum.auto() TOPIC_UNLOCK = enum.auto() + TOPIC_UNREMOVE = enum.auto() class TopicSortOption(enum.Enum): diff --git a/tildes/tildes/models/log/log.py b/tildes/tildes/models/log/log.py index c44c98d..257dd91 100644 --- a/tildes/tildes/models/log/log.py +++ b/tildes/tildes/models/log/log.py @@ -112,6 +112,7 @@ class LogTopic(DatabaseModel, BaseLog): def __str__(self) -> str: """Return a string representation of the log event.""" + # pylint: disable=too-many-return-statements if self.event_type == LogEventType.TOPIC_TAG: return self._tag_event_description() elif self.event_type == LogEventType.TOPIC_MOVE: @@ -120,8 +121,12 @@ class LogTopic(DatabaseModel, BaseLog): return f"moved from ~{old_group} to ~{new_group}" elif self.event_type == LogEventType.TOPIC_LOCK: return "locked comments" + elif self.event_type == LogEventType.TOPIC_REMOVE: + return "removed" elif self.event_type == LogEventType.TOPIC_UNLOCK: return "unlocked comments" + elif self.event_type == LogEventType.TOPIC_UNREMOVE: + return "un-removed" elif self.event_type == LogEventType.TOPIC_TITLE_EDIT: old_title = self.info["old"] # noqa new_title = self.info["new"] # noqa diff --git a/tildes/tildes/models/topic/topic.py b/tildes/tildes/models/topic/topic.py index 137054f..46ac091 100644 --- a/tildes/tildes/models/topic/topic.py +++ b/tildes/tildes/models/topic/topic.py @@ -282,6 +282,8 @@ class Topic(DatabaseModel): # tools that require specifically granted permissions acl.append((Allow, "admin", "lock")) + acl.append((Allow, "admin", "remove")) + acl.append((Allow, "admin", "move")) acl.append((Allow, "topic.move", "move")) diff --git a/tildes/tildes/routes.py b/tildes/tildes/routes.py index f39b70f..6321b6c 100644 --- a/tildes/tildes/routes.py +++ b/tildes/tildes/routes.py @@ -115,6 +115,7 @@ def add_intercooler_routes(config: Configurator) -> None: ) add_ic_route("topic_group", "/topics/{topic_id36}/group", factory=topic_by_id36) add_ic_route("topic_lock", "/topics/{topic_id36}/lock", factory=topic_by_id36) + add_ic_route("topic_remove", "/topics/{topic_id36}/remove", factory=topic_by_id36) add_ic_route("topic_title", "/topics/{topic_id36}/title", factory=topic_by_id36) add_ic_route("topic_vote", "/topics/{topic_id36}/vote", factory=topic_by_id36) add_ic_route("topic_tags", "/topics/{topic_id36}/tags", factory=topic_by_id36) diff --git a/tildes/tildes/templates/topic.jinja2 b/tildes/tildes/templates/topic.jinja2 index 93791a7..7ca7daf 100644 --- a/tildes/tildes/templates/topic.jinja2 +++ b/tildes/tildes/templates/topic.jinja2 @@ -56,7 +56,7 @@ {% endif %} {% endif %} -{% if request.has_any_permission(('edit', 'delete', 'tag', 'lock', 'move', 'edit_title'), topic) %} +{% if request.has_any_permission(('edit', 'delete', 'tag', 'lock', 'move', 'edit_title', 'remove'), topic) %} {% if request.has_permission('edit', topic) %}
  • {% endif %} + + {% if request.has_permission("remove", topic) %} +
  • + {% if not topic.is_removed %} + Remove + {% else %} + Un-remove + {% endif %} +
  • + {% endif %}
    {% endif %} diff --git a/tildes/tildes/views/api/web/topic.py b/tildes/tildes/views/api/web/topic.py index 25052e1..33b74d4 100644 --- a/tildes/tildes/views/api/web/topic.py +++ b/tildes/tildes/views/api/web/topic.py @@ -230,6 +230,28 @@ def patch_move_topic(request: Request, path: str) -> dict: return Response("Moved") +@ic_view_config(route_name="topic_remove", request_method="PUT", permission="remove") +def put_topic_remove(request: Request) -> Response: + """Remove a topic with Intercooler.""" + topic = request.context + + topic.is_removed = True + request.db_session.add(LogTopic(LogEventType.TOPIC_REMOVE, request, topic)) + + return Response("Removed") + + +@ic_view_config(route_name="topic_remove", request_method="DELETE", permission="remove") +def delete_topic_remove(request: Request) -> Response: + """Un-remove a topic with Intercooler.""" + topic = request.context + + topic.is_removed = False + request.db_session.add(LogTopic(LogEventType.TOPIC_UNREMOVE, request, topic)) + + return Response("Un-removed") + + @ic_view_config(route_name="topic_lock", request_method="PUT", permission="lock") def put_topic_lock(request: Request) -> Response: """Lock a topic with Intercooler.""" diff --git a/tildes/tildes/views/topic.py b/tildes/tildes/views/topic.py index 3f22eba..2728b12 100644 --- a/tildes/tildes/views/topic.py +++ b/tildes/tildes/views/topic.py @@ -253,9 +253,11 @@ def get_topic(request: Request, comment_order: CommentSortOption) -> dict: visible_events = ( LogEventType.TOPIC_LOCK, LogEventType.TOPIC_MOVE, + LogEventType.TOPIC_REMOVE, LogEventType.TOPIC_TAG, LogEventType.TOPIC_TITLE_EDIT, LogEventType.TOPIC_UNLOCK, + LogEventType.TOPIC_UNREMOVE, ) log = ( request.query(LogTopic)