|
@@ -1,218 +0,0 @@
|
|
|
-# Generated by Django 2.2.28 on 2022-07-26 03:45
|
|
|
-
|
|
|
-from enum import Enum
|
|
|
-
|
|
|
-from django.conf import settings
|
|
|
-from django.db import migrations
|
|
|
-from django.utils import timezone
|
|
|
-
|
|
|
-from sentry.new_migrations.migrations import CheckedMigration
|
|
|
-from sentry.utils.query import RangeQuerySetWrapperWithProgressBar
|
|
|
-
|
|
|
-
|
|
|
-class ExternalProviders(Enum):
|
|
|
- # only need Slack
|
|
|
- SLACK = 110
|
|
|
-
|
|
|
-
|
|
|
-class NotificationSettingOptionValues(Enum):
|
|
|
- """
|
|
|
- An empty row in the DB should be represented as
|
|
|
- NotificationSettingOptionValues.DEFAULT.
|
|
|
- """
|
|
|
-
|
|
|
- # Defer to a setting one level up.
|
|
|
- DEFAULT = 0
|
|
|
-
|
|
|
- # Mute this kind of notification.
|
|
|
- NEVER = 10
|
|
|
-
|
|
|
- # Un-mute this kind of notification.
|
|
|
- ALWAYS = 20
|
|
|
-
|
|
|
- # Workflow only. Only send notifications about Issues that the target has
|
|
|
- # explicitly or implicitly opted-into.
|
|
|
- SUBSCRIBE_ONLY = 30
|
|
|
-
|
|
|
- # Deploy only. Only send notifications when the set of changes in the deploy
|
|
|
- # included a commit authored by the target.
|
|
|
- COMMITTED_ONLY = 40
|
|
|
-
|
|
|
-
|
|
|
-class NotificationSettingTypes(Enum):
|
|
|
- """
|
|
|
- Each of these categories of Notification settings has at least an option for
|
|
|
- "on" or "off". Workflow also includes SUBSCRIBE_ONLY and Deploy also
|
|
|
- includes COMMITTED_ONLY and both of these values are described below.
|
|
|
- """
|
|
|
-
|
|
|
- # Control all notification types. Currently unused.
|
|
|
- DEFAULT = 0
|
|
|
-
|
|
|
- # When Sentry sees there is a new code deploy.
|
|
|
- DEPLOY = 10
|
|
|
-
|
|
|
- # When Sentry sees and issue that triggers an Alert Rule.
|
|
|
- ISSUE_ALERTS = 20
|
|
|
-
|
|
|
- # Notifications for changes in assignment, resolution, comments, etc.
|
|
|
- WORKFLOW = 30
|
|
|
- # Notification when an issue happens shortly after your release.
|
|
|
- ACTIVE_RELEASE = 31
|
|
|
-
|
|
|
- # Notifications that require approval like a request to invite a member
|
|
|
- APPROVAL = 40
|
|
|
-
|
|
|
- # Notifications about quotas
|
|
|
- QUOTA = 50
|
|
|
-
|
|
|
- # Sub category of quotas for each event category
|
|
|
- QUOTA_ERRORS = 51
|
|
|
- QUOTA_TRANSACTIONS = 52
|
|
|
- QUOTA_ATTACHMENTS = 53
|
|
|
-
|
|
|
- # Sub category of quotas for warnings before hitting the actual limit
|
|
|
- QUOTA_WARNINGS = 54
|
|
|
-
|
|
|
-
|
|
|
-class NotificationScopeType(Enum):
|
|
|
- USER = 0
|
|
|
- ORGANIZATION = 10
|
|
|
- PROJECT = 20
|
|
|
- TEAM = 30
|
|
|
-
|
|
|
-
|
|
|
-# these settings were defaulted to off for Slack
|
|
|
-SETTINGS_TO_BACKFILL = [
|
|
|
- NotificationSettingTypes.DEPLOY,
|
|
|
- NotificationSettingTypes.ISSUE_ALERTS,
|
|
|
- NotificationSettingTypes.WORKFLOW,
|
|
|
-]
|
|
|
-
|
|
|
-
|
|
|
-# backfill all entities for a given actor that's either a team or a user
|
|
|
-def backfill_one(apps, item_with_actor):
|
|
|
- NotificationSetting = apps.get_model("sentry", "NotificationSetting")
|
|
|
- Team = apps.get_model("sentry", "Team")
|
|
|
- # backfill to the scope of the entity
|
|
|
- scope_type = (
|
|
|
- NotificationScopeType.TEAM
|
|
|
- if isinstance(item_with_actor, Team)
|
|
|
- else NotificationScopeType.USER
|
|
|
- )
|
|
|
- for notification_type in SETTINGS_TO_BACKFILL:
|
|
|
- # find the setting for that user/teams
|
|
|
- settings = NotificationSetting.objects.filter(
|
|
|
- scope_type=scope_type.value,
|
|
|
- target_id=item_with_actor.actor_id,
|
|
|
- provider=ExternalProviders.SLACK.value,
|
|
|
- type=notification_type.value,
|
|
|
- scope_identifier=item_with_actor.id,
|
|
|
- )
|
|
|
- setting = settings.first()
|
|
|
- # if we have a setting that is not the default we can skip
|
|
|
- if setting and setting.value != NotificationSettingOptionValues.DEFAULT.value:
|
|
|
- continue
|
|
|
-
|
|
|
- # if we have a row it's set the default which we need to change
|
|
|
- if setting:
|
|
|
- setting.value = NotificationSettingOptionValues.NEVER.value
|
|
|
- setting.save(update_fields=["value"])
|
|
|
- else:
|
|
|
- # otherwise create the backfill
|
|
|
- NotificationSetting.objects.create(
|
|
|
- scope_type=scope_type.value,
|
|
|
- target_id=item_with_actor.actor_id,
|
|
|
- provider=ExternalProviders.SLACK.value,
|
|
|
- type=notification_type.value,
|
|
|
- scope_identifier=item_with_actor.id,
|
|
|
- value=NotificationSettingOptionValues.NEVER.value,
|
|
|
- )
|
|
|
-
|
|
|
-
|
|
|
-# backfill all users who joined after START_DATE_DEFAULT_SLACK_NOTIFICATION
|
|
|
-def backfill_users(apps):
|
|
|
- Identity = apps.get_model("sentry", "Identity")
|
|
|
- IdentityProvider = apps.get_model("sentry", "IdentityProvider")
|
|
|
-
|
|
|
- # users joining after this date will have slack enabled by default for notifications
|
|
|
- # default to the current time for self-hosted users
|
|
|
- START_DATE_DEFAULT_SLACK_NOTIFICATION = None
|
|
|
- try:
|
|
|
- START_DATE_DEFAULT_SLACK_NOTIFICATION = settings.START_DATE_DEFAULT_SLACK_NOTIFICATION
|
|
|
- except AttributeError:
|
|
|
- pass
|
|
|
- START_DATE_DEFAULT_SLACK_NOTIFICATION = START_DATE_DEFAULT_SLACK_NOTIFICATION or timezone.now()
|
|
|
-
|
|
|
- for identity_provider in RangeQuerySetWrapperWithProgressBar(IdentityProvider.objects.all()):
|
|
|
- if identity_provider.type != "slack":
|
|
|
- continue
|
|
|
- for identity in Identity.objects.filter(idp=identity_provider).select_related("user"):
|
|
|
- user = identity.user
|
|
|
- # skip users who joined after the cutoff date
|
|
|
- if user.date_joined >= START_DATE_DEFAULT_SLACK_NOTIFICATION:
|
|
|
- continue
|
|
|
-
|
|
|
- backfill_one(apps, user)
|
|
|
-
|
|
|
-
|
|
|
-# backfill all teams regardless of start date
|
|
|
-def backfill_teams(apps):
|
|
|
- ExternalActor = apps.get_model("sentry", "ExternalActor")
|
|
|
- Team = apps.get_model("sentry", "Team")
|
|
|
-
|
|
|
- for external_actor in RangeQuerySetWrapperWithProgressBar(ExternalActor.objects.all()):
|
|
|
- if external_actor.provider != ExternalProviders.SLACK.value:
|
|
|
- continue
|
|
|
- try:
|
|
|
- team = Team.objects.get(actor_id=external_actor.actor_id)
|
|
|
- except Team.DoesNotExist:
|
|
|
- # if team doesn't exist, move on
|
|
|
- continue
|
|
|
- backfill_one(apps, team)
|
|
|
-
|
|
|
-
|
|
|
-def backfill_slack_settings(apps, schema_editor):
|
|
|
- backfill_users(apps)
|
|
|
- backfill_teams(apps)
|
|
|
-
|
|
|
-
|
|
|
-class Migration(CheckedMigration):
|
|
|
- # This flag is used to mark that a migration shouldn't be automatically run in production. For
|
|
|
- # the most part, this should only be used for operations where it's safe to run the migration
|
|
|
- # after your code has deployed. So this should not be used for most operations that alter the
|
|
|
- # schema of a table.
|
|
|
- # Here are some things that make sense to mark as dangerous:
|
|
|
- # - Large data migrations. Typically we want these to be run manually by ops so that they can
|
|
|
- # be monitored and not block the deploy for a long period of time while they run.
|
|
|
- # - Adding indexes to large tables. Since this can take a long time, we'd generally prefer to
|
|
|
- # have ops run this and not block the deploy. Note that while adding an index is a schema
|
|
|
- # change, it's completely safe to run the operation after the code has deployed.
|
|
|
- is_dangerous = True
|
|
|
-
|
|
|
- # This flag is used to decide whether to run this migration in a transaction or not. Generally
|
|
|
- # we don't want to run in a transaction here, since for long running operations like data
|
|
|
- # back-fills this results in us locking an increasing number of rows until we finally commit.
|
|
|
- atomic = False
|
|
|
-
|
|
|
- dependencies = [
|
|
|
- ("sentry", "0310_sentry_functions_add_webhooks"),
|
|
|
- ]
|
|
|
-
|
|
|
- operations = [
|
|
|
- migrations.RunPython(
|
|
|
- backfill_slack_settings,
|
|
|
- migrations.RunPython.noop,
|
|
|
- hints={
|
|
|
- "tables": [
|
|
|
- "sentry_notificationsetting",
|
|
|
- "sentry_organization",
|
|
|
- "sentry_identity",
|
|
|
- "sentry_identityprovider",
|
|
|
- "sentry_organizationintegration",
|
|
|
- "sentry_externalactor",
|
|
|
- "sentry_team",
|
|
|
- ]
|
|
|
- },
|
|
|
- ),
|
|
|
- ]
|