Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Account migration command #429

Merged
merged 6 commits into from
Jul 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .flake8
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[flake8]
application-import-names = api,app,authentication,blossom,blossom_wiki,engineeringblog,ocr,payments,utils,website
ignore = ANN101, D100, D101, D105, D106, W503, E203
ignore = ANN101, ANN401, D100, D101, D105, D106, W503, E203
import-order-style = pycharm
max-complexity = 10
max-line-length = 90
Expand Down
4 changes: 3 additions & 1 deletion api/migrations/0007_source_id.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ class Migration(migrations.Migration):

operations = [
migrations.AddField(
model_name="source", name="id", field=models.IntegerField(default=0),
model_name="source",
name="id",
field=models.IntegerField(default=0),
),
]
5 changes: 4 additions & 1 deletion api/migrations/0008_remove_source_id.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,8 @@ class Migration(migrations.Migration):
]

operations = [
migrations.RemoveField(model_name="source", name="id",),
migrations.RemoveField(
model_name="source",
name="id",
),
]
9 changes: 7 additions & 2 deletions api/migrations/0010_auto_20200831_0335.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ class Migration(migrations.Migration):

operations = [
migrations.RenameField(
model_name="submission", old_name="image_url", new_name="content_url",
model_name="submission",
old_name="image_url",
new_name="content_url",
),
migrations.RemoveField(
model_name="submission",
name="is_image",
),
migrations.RemoveField(model_name="submission", name="is_image",),
]
77 changes: 77 additions & 0 deletions api/migrations/0025_accountmigration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Generated by Django 3.2.14 on 2022-07-18 00:07

import django.db.models.deletion
import django.utils.timezone
from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
("api", "0024_alter_transcriptioncheck_status"),
]

operations = [
migrations.CreateModel(
name="AccountMigration",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"create_time",
models.DateTimeField(default=django.utils.timezone.now),
),
(
"slack_channel_id",
models.CharField(
blank=True, default=None, max_length=50, null=True
),
),
(
"slack_message_ts",
models.CharField(
blank=True, default=None, max_length=50, null=True
),
),
("affected_submissions", models.ManyToManyField(to="api.Submission")),
(
"moderator",
models.ForeignKey(
default=None,
null=True,
on_delete=django.db.models.deletion.SET_DEFAULT,
to=settings.AUTH_USER_MODEL,
),
),
(
"new_user",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="new_user",
to=settings.AUTH_USER_MODEL,
),
),
(
"old_user",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="old_user",
to=settings.AUTH_USER_MODEL,
),
),
],
),
]
61 changes: 59 additions & 2 deletions api/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,10 @@ class TranscriptionCheckStatus(models.TextChoices):

# An internal note for the moderators
internal_note = models.CharField(
max_length=1000, null=True, blank=True, default=None,
max_length=1000,
null=True,
blank=True,
default=None,
)

# The time the check has been created.
Expand All @@ -400,10 +403,64 @@ def get_slack_url(self) -> Optional[str]:
return None

url_response = client.chat_getPermalink(
channel=self.slack_channel_id, message_ts=self.slack_message_ts,
channel=self.slack_channel_id,
message_ts=self.slack_message_ts,
)

if not url_response.get("ok"):
return None

return url_response.get("permalink")


class AccountMigration(models.Model):
create_time = models.DateTimeField(default=timezone.now)
old_user = models.ForeignKey(
"authentication.BlossomUser",
on_delete=models.SET_NULL,
related_name="old_user",
null=True,
blank=True,
)
new_user = models.ForeignKey(
"authentication.BlossomUser",
on_delete=models.SET_NULL,
related_name="new_user",
null=True,
blank=True,
)
# keep track of submissions that were modified in case we need to roll back
affected_submissions = models.ManyToManyField(Submission)
# who has approved this migration?
moderator = models.ForeignKey(
"authentication.BlossomUser",
default=None,
null=True,
on_delete=models.SET_DEFAULT,
)
# The info needed to update the Slack message of the check
slack_channel_id = models.CharField(
max_length=50, default=None, null=True, blank=True
)
slack_message_ts = models.CharField(
max_length=50, default=None, null=True, blank=True
)

def perform_migration(self) -> None:
"""Move all submissions attributed to one account to another."""
existing_submissions = Submission.objects.filter(completed_by=self.old_user)
self.affected_submissions.add(*existing_submissions)

existing_submissions.update(
claimed_by=self.new_user, completed_by=self.new_user
)

def get_number_affected(self) -> int:
"""Get the number of records that have been modified."""
return self.affected_submissions.count()

def revert(self) -> None:
"""Undo the account migration."""
self.affected_submissions.update(
claimed_by=self.old_user, completed_by=self.old_user
)
10 changes: 8 additions & 2 deletions api/slack/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

from api.models import Submission
from api.slack import client
from api.slack.commands.migrate_user import process_migrate_user
from api.slack.transcription_check.actions import process_check_action
from app.reddit_actions import approve_post, remove_post
from blossom.strings import translation
Expand All @@ -34,8 +35,12 @@ def process_action(data: Dict) -> None:
value: str = data["actions"][0].get("value")
if value.startswith("check"):
process_check_action(data)
elif "approve" in value or "remove" in value:
elif "submission" in value:
# buttons related to approving or removing submissions on the app and on Reddit
process_submission_report_update(data)
elif "migration" in value:
# buttons related to account gamma migrations
process_migrate_user(data)
else:
client.chat_postMessage(
channel=data["channel"]["id"],
Expand Down Expand Up @@ -151,7 +156,8 @@ def process_submission_report_update(data: dict) -> None:

# Find the submission corresponding to the message
submissions = Submission.objects.filter(
report_slack_channel_id=channel_id, report_slack_message_ts=message_ts,
report_slack_channel_id=channel_id,
report_slack_message_ts=message_ts,
)

if len(submissions) == 0:
Expand Down
2 changes: 2 additions & 0 deletions api/slack/commands/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from api.slack.commands.dadjoke import dadjoke_cmd
from api.slack.commands.help import help_cmd
from api.slack.commands.info import info_cmd
from api.slack.commands.migrate_user import migrate_user_cmd
from api.slack.commands.ping import ping_cmd
from api.slack.commands.reset import reset_cmd
from api.slack.commands.unwatch import unwatch_cmd
Expand Down Expand Up @@ -58,6 +59,7 @@ def process_command(data: Dict) -> None:
"dadjoke": dadjoke_cmd,
"help": help_cmd,
"info": info_cmd,
"migrate": migrate_user_cmd,
"ping": ping_cmd,
"reset": reset_cmd,
"unwatch": unwatch_cmd,
Expand Down
3 changes: 2 additions & 1 deletion api/slack/commands/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ def check_cmd(channel: str, message: str) -> None:

# Get the link for the check
response = client.chat_getPermalink(
channel=check.slack_channel_id, message_ts=check.slack_message_ts,
channel=check.slack_channel_id,
message_ts=check.slack_message_ts,
)
permalink = response.data.get("permalink")

Expand Down
Loading