mirror of https://gitlab.com/tildes/tildes.git
Browse Source
Close voting after 30 days, delete vote records
Close voting after 30 days, delete vote records
This makes it so that posts (both topics and comments) can no longer be voted on after they're over 30 days old. An hourly cronjob makes this "official" by updating a flag on the post indicating that voting is closed. The daily clean_private_data script then deletes all individual vote records for posts with closed voting, and the triggers on the voting tables have been updated to not decrement the vote totals when these deletions happen. The net result of this is that Tildes only stores users' votes for a maximum of 30 days, removing a lot of sensitive/private data that builds up over the long term.merge-requests/85/head
Deimos
5 years ago
15 changed files with 258 additions and 18 deletions
-
7salt/salt/cronjobs.sls
-
129tildes/alembic/versions/4d352e61a468_add_is_voting_closed_to_comments_.py
-
21tildes/scripts/clean_private_data.py
-
31tildes/scripts/close_voting_on_old_posts.py
-
1tildes/scss/modules/_btn.scss
-
3tildes/scss/modules/_comment.scss
-
5tildes/sql/init/triggers/comment_votes/comments.sql
-
5tildes/sql/init/triggers/topic_votes/topics.sql
-
2tildes/tildes/models/comment/__init__.py
-
27tildes/tildes/models/comment/comment.py
-
2tildes/tildes/models/comment/comment_vote.py
-
2tildes/tildes/models/topic/__init__.py
-
29tildes/tildes/models/topic/topic.py
-
2tildes/tildes/models/topic/topic_vote.py
-
6tildes/tildes/templates/macros/comments.jinja2
@ -0,0 +1,129 @@ |
|||
"""Add is_voting_closed to comments and topics |
|||
|
|||
Revision ID: 4d352e61a468 |
|||
Revises: 879588c5729d |
|||
Create Date: 2019-11-15 23:58:09.613684 |
|||
|
|||
""" |
|||
from alembic import op |
|||
import sqlalchemy as sa |
|||
|
|||
|
|||
# revision identifiers, used by Alembic. |
|||
revision = "4d352e61a468" |
|||
down_revision = "879588c5729d" |
|||
branch_labels = None |
|||
depends_on = None |
|||
|
|||
|
|||
def upgrade(): |
|||
op.add_column( |
|||
"comments", |
|||
sa.Column( |
|||
"is_voting_closed", sa.Boolean(), server_default="false", nullable=False |
|||
), |
|||
) |
|||
op.create_index( |
|||
op.f("ix_comments_is_voting_closed"), |
|||
"comments", |
|||
["is_voting_closed"], |
|||
unique=False, |
|||
) |
|||
op.add_column( |
|||
"topics", |
|||
sa.Column( |
|||
"is_voting_closed", sa.Boolean(), server_default="false", nullable=False |
|||
), |
|||
) |
|||
op.create_index( |
|||
op.f("ix_topics_is_voting_closed"), "topics", ["is_voting_closed"], unique=False |
|||
) |
|||
|
|||
op.execute( |
|||
""" |
|||
CREATE OR REPLACE FUNCTION update_comment_num_votes() RETURNS TRIGGER AS $$ |
|||
BEGIN |
|||
IF (TG_OP = 'INSERT') THEN |
|||
UPDATE comments |
|||
SET num_votes = num_votes + 1 |
|||
WHERE comment_id = NEW.comment_id; |
|||
ELSIF (TG_OP = 'DELETE') THEN |
|||
UPDATE comments |
|||
SET num_votes = num_votes - 1 |
|||
WHERE comment_id = OLD.comment_id |
|||
AND is_voting_closed = FALSE; |
|||
END IF; |
|||
|
|||
RETURN NULL; |
|||
END |
|||
$$ LANGUAGE plpgsql; |
|||
""" |
|||
) |
|||
|
|||
op.execute( |
|||
""" |
|||
CREATE OR REPLACE FUNCTION update_topic_num_votes() RETURNS TRIGGER AS $$ |
|||
BEGIN |
|||
IF (TG_OP = 'INSERT') THEN |
|||
UPDATE topics |
|||
SET num_votes = num_votes + 1 |
|||
WHERE topic_id = NEW.topic_id; |
|||
ELSIF (TG_OP = 'DELETE') THEN |
|||
UPDATE topics |
|||
SET num_votes = num_votes - 1 |
|||
WHERE topic_id = OLD.topic_id |
|||
AND is_voting_closed = FALSE; |
|||
END IF; |
|||
|
|||
RETURN NULL; |
|||
END |
|||
$$ LANGUAGE plpgsql; |
|||
""" |
|||
) |
|||
|
|||
|
|||
def downgrade(): |
|||
op.drop_index(op.f("ix_topics_is_voting_closed"), table_name="topics") |
|||
op.drop_column("topics", "is_voting_closed") |
|||
op.drop_index(op.f("ix_comments_is_voting_closed"), table_name="comments") |
|||
op.drop_column("comments", "is_voting_closed") |
|||
|
|||
op.execute( |
|||
""" |
|||
CREATE OR REPLACE FUNCTION update_comment_num_votes() RETURNS TRIGGER AS $$ |
|||
BEGIN |
|||
IF (TG_OP = 'INSERT') THEN |
|||
UPDATE comments |
|||
SET num_votes = num_votes + 1 |
|||
WHERE comment_id = NEW.comment_id; |
|||
ELSIF (TG_OP = 'DELETE') THEN |
|||
UPDATE comments |
|||
SET num_votes = num_votes - 1 |
|||
WHERE comment_id = OLD.comment_id; |
|||
END IF; |
|||
|
|||
RETURN NULL; |
|||
END |
|||
$$ LANGUAGE plpgsql; |
|||
""" |
|||
) |
|||
|
|||
op.execute( |
|||
""" |
|||
CREATE OR REPLACE FUNCTION update_topic_num_votes() RETURNS TRIGGER AS $$ |
|||
BEGIN |
|||
IF (TG_OP = 'INSERT') THEN |
|||
UPDATE topics |
|||
SET num_votes = num_votes + 1 |
|||
WHERE topic_id = NEW.topic_id; |
|||
ELSIF (TG_OP = 'DELETE') THEN |
|||
UPDATE topics |
|||
SET num_votes = num_votes - 1 |
|||
WHERE topic_id = OLD.topic_id; |
|||
END IF; |
|||
|
|||
RETURN NULL; |
|||
END |
|||
$$ LANGUAGE plpgsql; |
|||
""" |
|||
) |
@ -0,0 +1,31 @@ |
|||
# Copyright (c) 2019 Tildes contributors <code@tildes.net> |
|||
# SPDX-License-Identifier: AGPL-3.0-or-later |
|||
|
|||
"""Simple script to "officially" close voting on old posts. |
|||
|
|||
This script should be set up to run regularly (such as every hour). It's not totally |
|||
essential since the application can generally prevent voting using the same logic, but |
|||
the more often it's run, the more correct the is_voting_closed column will be. |
|||
""" |
|||
|
|||
from tildes.lib.database import get_session_from_config |
|||
from tildes.lib.datetime import utc_now |
|||
from tildes.models.comment import Comment, VOTING_PERIOD as COMMENT_VOTING_PERIOD |
|||
from tildes.models.topic import Topic, VOTING_PERIOD as TOPIC_VOTING_PERIOD |
|||
|
|||
|
|||
def close_voting_on_old_posts(config_path: str) -> None: |
|||
"""Update is_voting_closed column on all posts older than the voting period.""" |
|||
db_session = get_session_from_config(config_path) |
|||
|
|||
db_session.query(Comment).filter( |
|||
Comment.created_time < utc_now() - COMMENT_VOTING_PERIOD, |
|||
Comment._is_voting_closed == False, # noqa |
|||
).update({"_is_voting_closed": True}, synchronize_session=False) |
|||
|
|||
db_session.query(Topic).filter( |
|||
Topic.created_time < utc_now() - TOPIC_VOTING_PERIOD, |
|||
Topic._is_voting_closed == False, # noqa |
|||
).update({"_is_voting_closed": True}, synchronize_session=False) |
|||
|
|||
db_session.commit() |
Write
Preview
Loading…
Cancel
Save
Reference in new issue