diff --git a/src/olympia/abuse/migrations/0070_alter_cinderpolicy_expose_in_reviewer_tools_and_more.py b/src/olympia/abuse/migrations/0070_alter_cinderpolicy_expose_in_reviewer_tools_and_more.py new file mode 100644 index 000000000000..d71c05b51841 --- /dev/null +++ b/src/olympia/abuse/migrations/0070_alter_cinderpolicy_expose_in_reviewer_tools_and_more.py @@ -0,0 +1,28 @@ +# Generated by Django 5.2.16 on 2026-07-15 15:20 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('abuse', '0069_auto_20260625_1600'), + ] + + operations = [ + migrations.AlterField( + model_name='cinderpolicy', + name='expose_in_reviewer_tools', + field=models.SmallIntegerField(choices=[(0, 'Not exposed'), (1, 'All add-ons'), (2, 'Extensions'), (3, 'Themes')], default=0), + ), + migrations.AlterField( + model_name='contentdecision', + name='action', + field=models.PositiveSmallIntegerField(choices=[(1, 'User ban'), (2, 'Add-on disable'), (3, '(Obsolete) Forward add-on to reviewers'), (5, 'Rating delete'), (6, 'Collection delete'), (7, 'Approved'), (8, 'Add-on version reject'), (9, 'Add-on version delayed reject warning'), (10, 'Approved (new version approval)'), (11, 'Invalid report, so ignored'), (12, 'Content already moderated (no action)'), (13, 'Forward add-on to legal'), (14, 'Pending rejection date changed'), (15, 'No action - internal requeue'), (16, 'Add-on disable and block'), (17, 'Add-on listing content rejection'), (18, '[Follow-up] Short-delayed soft block'), (19, '[Follow-up] Mid-delayed soft block'), (20, '[Follow-up] Long-delayed soft block'), (21, '[Follow-up] Short-delayed hard block'), (22, '[Follow-up] Mid-delayed hard block'), (23, '[Follow-up] Long-delayed hard block'), (24, 'Add-on disable, due to legal takedown')]), + ), + migrations.AlterField( + model_name='contentdecisionfollowupaction', + name='action', + field=models.PositiveSmallIntegerField(choices=[(1, 'User ban'), (2, 'Add-on disable'), (3, '(Obsolete) Forward add-on to reviewers'), (5, 'Rating delete'), (6, 'Collection delete'), (7, 'Approved'), (8, 'Add-on version reject'), (9, 'Add-on version delayed reject warning'), (10, 'Approved (new version approval)'), (11, 'Invalid report, so ignored'), (12, 'Content already moderated (no action)'), (13, 'Forward add-on to legal'), (14, 'Pending rejection date changed'), (15, 'No action - internal requeue'), (16, 'Add-on disable and block'), (17, 'Add-on listing content rejection'), (18, '[Follow-up] Short-delayed soft block'), (19, '[Follow-up] Mid-delayed soft block'), (20, '[Follow-up] Long-delayed soft block'), (21, '[Follow-up] Short-delayed hard block'), (22, '[Follow-up] Mid-delayed hard block'), (23, '[Follow-up] Long-delayed hard block'), (24, 'Add-on disable, due to legal takedown')]), + ), + ] diff --git a/src/olympia/abuse/models.py b/src/olympia/abuse/models.py index 0e9d7a778812..e0d011939c29 100644 --- a/src/olympia/abuse/models.py +++ b/src/olympia/abuse/models.py @@ -26,6 +26,7 @@ DECISION_SOURCES, ILLEGAL_CATEGORIES, ILLEGAL_SUBCATEGORIES, + POLICY_EXPOSURE, ) from olympia.ratings.models import Rating from olympia.users.models import UserProfile @@ -935,7 +936,9 @@ class POLICY_STATUSES(EnumChoices): on_delete=models.SET_NULL, related_name='children', ) - expose_in_reviewer_tools = models.BooleanField(default=False) + expose_in_reviewer_tools = models.SmallIntegerField( + default=POLICY_EXPOSURE.NONE, choices=POLICY_EXPOSURE.choices + ) enforcement_actions = models.JSONField(default=list) status_in_cinder = models.SmallIntegerField(null=True, choices=POLICY_STATUSES) diff --git a/src/olympia/abuse/tasks.py b/src/olympia/abuse/tasks.py index 0e254e77268e..247ef86ab39e 100644 --- a/src/olympia/abuse/tasks.py +++ b/src/olympia/abuse/tasks.py @@ -16,7 +16,7 @@ from olympia.amo.celery import task from olympia.amo.decorators import use_primary_db from olympia.amo.utils import to_language -from olympia.constants.abuse import DECISION_ACTIONS +from olympia.constants.abuse import DECISION_ACTIONS, POLICY_EXPOSURE from olympia.reviewers.models import NeedsHumanReview, UsageTier from olympia.users.models import UserProfile @@ -216,7 +216,9 @@ def remove_unused_deleted_policies(orphaned_policies): qs.delete() def mark_inactive_and_orphaned_policies(orphaned_policies): - reviewer_qs = orphaned_policies.filter(expose_in_reviewer_tools=True) + reviewer_qs = orphaned_policies.exclude( + expose_in_reviewer_tools=POLICY_EXPOSURE.NONE + ) if reviewer_qs.exists(): log.info( 'Marking orphaned Cinder Policy still in use in reviewer tools as ' @@ -225,7 +227,7 @@ def mark_inactive_and_orphaned_policies(orphaned_policies): ) reviewer_qs.update( status_in_cinder=CinderPolicy.POLICY_STATUSES.DELETED_WAS_REVIEWER, - expose_in_reviewer_tools=False, + expose_in_reviewer_tools=POLICY_EXPOSURE.NONE, ) deleted_qs = ( @@ -251,14 +253,14 @@ def mark_inactive_and_orphaned_policies(orphaned_policies): inactive_qs = CinderPolicy.objects.exclude( status_in_cinder=CinderPolicy.POLICY_STATUSES.PUBLISHED - ).filter(expose_in_reviewer_tools=True) + ).exclude(expose_in_reviewer_tools=POLICY_EXPOSURE.NONE) if inactive_qs.exists(): log.info( 'Marking Cinder Policy not published as not exposed in reviewer tools: ' '%s', list(inactive_qs.values_list('uuid', flat=True)), ) - inactive_qs.update(expose_in_reviewer_tools=False) + inactive_qs.update(expose_in_reviewer_tools=POLICY_EXPOSURE.NONE) url = f'{settings.CINDER_SERVER_URL}v1/policies' headers = { diff --git a/src/olympia/abuse/tests/test_admin.py b/src/olympia/abuse/tests/test_admin.py index b07d910ff6b9..6be5258453f1 100644 --- a/src/olympia/abuse/tests/test_admin.py +++ b/src/olympia/abuse/tests/test_admin.py @@ -19,6 +19,7 @@ grant_permission, user_factory, ) +from olympia.constants.abuse import POLICY_EXPOSURE from olympia.ratings.models import Rating from olympia.reviewers.models import AutoApprovalSummary from olympia.versions.models import VersionPreview @@ -626,11 +627,9 @@ def _make_list_request(self, *, read_only=False): 'id': 'abuse_sync_cinder_policies', 'value': 'Sync from Cinder', } - assert len( - doc( - 'input[id^="id_form-"][id$="-expose_in_reviewer_tools"][type="checkbox"]' - ) - ) == (CinderPolicy.objects.count() if not read_only else 0) + assert len(doc('select[id^="id_form-"][id$="-expose_in_reviewer_tools"]')) == ( + CinderPolicy.objects.count() if not read_only else 0 + ) def test_list_no_permission(self): self.login(permission=None) @@ -647,11 +646,11 @@ def test_list_with_view_permission(self): def _make_edit_request(self, expected_status_code): policy = CinderPolicy.objects.create( - name='Bar', uuid=uuid.uuid4(), expose_in_reviewer_tools=False + name='Bar', uuid=uuid.uuid4(), expose_in_reviewer_tools=POLICY_EXPOSURE.NONE ) detail_url = reverse('admin:abuse_cinderpolicy_change', args=(policy.id,)) response = self.client.post( - detail_url, {'expose_in_reviewer_tools': True}, follow=True + detail_url, {'expose_in_reviewer_tools': POLICY_EXPOSURE.BOTH}, follow=True ) assert response.status_code == expected_status_code return policy @@ -659,17 +658,17 @@ def _make_edit_request(self, expected_status_code): def test_edit_policies(self): self.login() policy = self._make_edit_request(200) - assert policy.reload().expose_in_reviewer_tools is True + assert policy.reload().expose_in_reviewer_tools == POLICY_EXPOSURE.BOTH def test_edit_policies_cannot_with_no_permission(self): self.login(permission=None) policy = self._make_edit_request(403) - assert policy.reload().expose_in_reviewer_tools is False + assert policy.reload().expose_in_reviewer_tools == POLICY_EXPOSURE.NONE def test_edit_policies_cannot_with_view_permission(self): self.login(permission='CinderPolicies:View') policy = self._make_edit_request(403) - assert policy.reload().expose_in_reviewer_tools is False + assert policy.reload().expose_in_reviewer_tools == POLICY_EXPOSURE.NONE def test_sync_policies_no_permission(self): self.login(permission=None) diff --git a/src/olympia/abuse/tests/test_tasks.py b/src/olympia/abuse/tests/test_tasks.py index 1c9a25a4076a..c81043a48342 100644 --- a/src/olympia/abuse/tests/test_tasks.py +++ b/src/olympia/abuse/tests/test_tasks.py @@ -19,6 +19,7 @@ DECISION_ACTIONS, ILLEGAL_CATEGORIES, ILLEGAL_SUBCATEGORIES, + POLICY_EXPOSURE, ) from olympia.files.models import File from olympia.reviewers.models import NeedsHumanReview, ReviewActionReason, UsageTier @@ -1168,7 +1169,7 @@ def test_orphaned_policies_deleted_or_marked_as_deleted(self): uuid=uuid.uuid4().hex, name='Existing policy', text='Existing policy with no decision or ReviewActionReason but exposed', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, ) # This policy should be kept because it's still present in Cinder @@ -1183,13 +1184,13 @@ def test_orphaned_policies_deleted_or_marked_as_deleted(self): name='Now archived', text='Existing policy but now archived', status_in_cinder=CinderPolicy.POLICY_STATUSES.PUBLISHED, - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, ) existing_reviewer_policy = CinderPolicy.objects.create( uuid=uuid.uuid4().hex, name='Reviewers', text='Existing policy in reviewer tools', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, ) # we're returning 4 policies data = [ @@ -1245,7 +1246,10 @@ def test_orphaned_policies_deleted_or_marked_as_deleted(self): updated_policy_but_now_archived.reload().status_in_cinder == CinderPolicy.POLICY_STATUSES.ARCHIVED ) - assert updated_policy_but_now_archived.expose_in_reviewer_tools is False + assert ( + updated_policy_but_now_archived.expose_in_reviewer_tools + == POLICY_EXPOSURE.NONE + ) # all the policies deleted from Cinder remain but are marked deleted assert ( @@ -1265,9 +1269,16 @@ def test_orphaned_policies_deleted_or_marked_as_deleted(self): == CinderPolicy.POLICY_STATUSES.DELETED_WAS_REVIEWER ) # And they're all not exposed in reviewer tools now - assert CinderPolicy.objects.filter(expose_in_reviewer_tools=True).count() == 1 assert ( - CinderPolicy.objects.filter(expose_in_reviewer_tools=True).get() + CinderPolicy.objects.filter( + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH + ).count() + == 1 + ) + assert ( + CinderPolicy.objects.filter( + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH + ).get() == existing_reviewer_policy ) diff --git a/src/olympia/constants/abuse.py b/src/olympia/constants/abuse.py index ad0fbc7217c4..3e8eef2ceff9 100644 --- a/src/olympia/constants/abuse.py +++ b/src/olympia/constants/abuse.py @@ -369,3 +369,14 @@ class DECISION_SOURCES(StrEnum): LEGAL = 'Legal' TASKUS = 'TaskUs' MANUAL = 'Manual' + + +class POLICY_EXPOSURE(EnumChoices): + NONE = 0, 'Not exposed' + BOTH = 1, 'All add-ons' + EXTENSION = 2, 'Extensions' + THEME = 3, 'Themes' + + +POLICY_EXPOSURE.add_subset('FOR_EXTENSIONS', ('BOTH', 'EXTENSION')) +POLICY_EXPOSURE.add_subset('FOR_THEMES', ('BOTH', 'THEME')) diff --git a/src/olympia/reviewers/forms.py b/src/olympia/reviewers/forms.py index 7d5b9e5d4575..ad6c3fce6cd9 100644 --- a/src/olympia/reviewers/forms.py +++ b/src/olympia/reviewers/forms.py @@ -23,7 +23,7 @@ from olympia.access import acl from olympia.addons.models import Addon from olympia.amo.forms import AMOModelForm -from olympia.constants.abuse import DECISION_ACTIONS +from olympia.constants.abuse import DECISION_ACTIONS, POLICY_EXPOSURE from olympia.constants.reviewers import ( HELD_DECISION_CHOICES, REVIEWER_DELAYED_REJECTION_PERIOD_DAYS_DEFAULT, @@ -842,8 +842,13 @@ def __init__(self, *args, **kw): ].queryset = self.helper.unresolved_cinderjob_qs # Set the queryset for policies to show as options + policy_choices = ( + POLICY_EXPOSURE.FOR_THEMES + if self.helper.addon.type == amo.ADDON_STATICTHEME + else POLICY_EXPOSURE.FOR_EXTENSIONS + ) self.fields['cinder_policies'].queryset = CinderPolicy.objects.filter( - expose_in_reviewer_tools=True + expose_in_reviewer_tools__in=policy_choices ).select_related('parent') # Pass on the reviewer tools actions so we can set the show/hide on policies diff --git a/src/olympia/reviewers/tests/test_commands.py b/src/olympia/reviewers/tests/test_commands.py index e26bed13891a..d9811b4784ac 100644 --- a/src/olympia/reviewers/tests/test_commands.py +++ b/src/olympia/reviewers/tests/test_commands.py @@ -29,7 +29,7 @@ version_review_flags_factory, ) from olympia.amo.utils import days_ago -from olympia.constants.abuse import DECISION_ACTIONS +from olympia.constants.abuse import DECISION_ACTIONS, POLICY_EXPOSURE from olympia.constants.promoted import PROMOTED_GROUP_CHOICES from olympia.constants.scanners import DELAY_AUTO_APPROVAL, NARC, YARA from olympia.files.models import FileManifest, FileValidation @@ -772,7 +772,7 @@ def check_assertions(): reject_policy = CinderPolicy.objects.create( enforcement_actions=[DECISION_ACTIONS.AMO_REJECT_VERSION_ADDON.api_value], name='Reject Policy', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, uuid=uuid.uuid4().hex, ) ScannerRule.objects.create( @@ -824,7 +824,7 @@ def check_assertions(): reject_policy = CinderPolicy.objects.create( enforcement_actions=[DECISION_ACTIONS.AMO_DISABLE_ADDON.api_value], name='Disable Policy', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, uuid=uuid.uuid4().hex, ) ScannerRule.objects.create( diff --git a/src/olympia/reviewers/tests/test_forms.py b/src/olympia/reviewers/tests/test_forms.py index e7867c12c19f..7dfaf6fa1c89 100644 --- a/src/olympia/reviewers/tests/test_forms.py +++ b/src/olympia/reviewers/tests/test_forms.py @@ -25,7 +25,7 @@ version_factory, ) from olympia.bandwagon.models import Collection -from olympia.constants.abuse import DECISION_ACTIONS +from olympia.constants.abuse import DECISION_ACTIONS, POLICY_EXPOSURE from olympia.files.models import File from olympia.ratings.models import Rating from olympia.users.models import UserProfile @@ -234,7 +234,7 @@ def test_policies_required_with_cinder_jobs(self): policy = CinderPolicy.objects.create( uuid='x', name='ok', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_IGNORE.api_value], ) form = self.get_form() @@ -258,7 +258,7 @@ def test_comments_optional_for_actions_with_enforcement_actions(self): policy = CinderPolicy.objects.create( uuid='xxx', name='ok', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_DISABLE_ADDON.api_value], ) self.grant_permission(self.request.user, 'Addons:Review') @@ -287,14 +287,14 @@ def test_policy_values_parsed(self): policy = CinderPolicy.objects.create( uuid='xxx', name='ok', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_DISABLE_ADDON.api_value], text='Blah blah {SOME-PLACEHOLDER} blah blah.', ) unselected_policy = CinderPolicy.objects.create( uuid='yyy', name='not okay', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_DISABLE_ADDON.api_value], text='policy text {UNSELECTED}', ) @@ -366,24 +366,24 @@ def test_policy_actions(self): job_id='1', resolvable_in_reviewer_tools=True, target_addon=self.addon ) no_action_policy = CinderPolicy.objects.create( - uuid='no', name='no action', expose_in_reviewer_tools=True + uuid='no', name='no action', expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH ) action_policy_a = CinderPolicy.objects.create( uuid='a', name='disable', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_DISABLE_ADDON.api_value], ) action_policy_b = CinderPolicy.objects.create( uuid='b', name='disable again', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_DISABLE_ADDON.api_value], ) action_policy_c = CinderPolicy.objects.create( uuid='c', name='reject', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_REJECT_VERSION_ADDON.api_value], ) form = self.get_form() @@ -447,13 +447,13 @@ def test_policy_actions_multiple_positive(self): action_policy_approve = CinderPolicy.objects.create( uuid='approve', name='approve', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_APPROVE.api_value], ) action_policy_ignore = CinderPolicy.objects.create( uuid='ignore', name='ignore', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_IGNORE.api_value], ) data = { @@ -479,30 +479,30 @@ def test_policy_actions_with_policy_enforcement(self): job_id='1', resolvable_in_reviewer_tools=True, target_addon=self.addon ) no_action_policy = CinderPolicy.objects.create( - uuid='no', name='no action', expose_in_reviewer_tools=True + uuid='no', name='no action', expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH ) action_policy_disable = CinderPolicy.objects.create( uuid='disable', name='disable', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_DISABLE_ADDON.api_value], ) action_policy_reject = CinderPolicy.objects.create( uuid='reject', name='reject', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_REJECT_VERSION_ADDON.api_value], ) action_policy_approve = CinderPolicy.objects.create( uuid='approve', name='approve', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_APPROVE.api_value], ) action_policy_ignore = CinderPolicy.objects.create( uuid='ignore', name='ignore', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_IGNORE.api_value], ) form = self.get_form() @@ -536,7 +536,7 @@ def test_policy_actions_with_policy_enforcement(self): action_policy_multiple_primary = CinderPolicy.objects.create( uuid='multi', name='multi', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[ DECISION_ACTIONS.AMO_DISABLE_ADDON.api_value, DECISION_ACTIONS.AMO_REJECT_VERSION_ADDON.api_value, @@ -575,13 +575,13 @@ def test_versions_required_when_enforcement_is_on_versions(self): disable_policy = CinderPolicy.objects.create( uuid='a', name='disable', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_DISABLE_ADDON.api_value], ) reject_policy = CinderPolicy.objects.create( uuid='c', name='reject', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_REJECT_VERSION_ADDON.api_value], ) @@ -651,7 +651,7 @@ def test_cinder_jobs_filtered_for_resolve_reports_job_and_appeal_deny(self): policy = CinderPolicy.objects.create( uuid='a', name='ignore', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_IGNORE.api_value], ) @@ -723,7 +723,7 @@ def test_cinder_jobs_filtered_for_reject_or_reject_multiple_versions(self): policy = CinderPolicy.objects.create( uuid='a', name='ignore', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_REJECT_VERSION_ADDON.api_value], ) @@ -804,7 +804,7 @@ def test_action_required_by_default(self): CinderPolicy.objects.create( uuid='1', name='policy 1', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[ DECISION_ACTIONS.AMO_REJECT_VERSION_ADDON.api_value ], @@ -1201,7 +1201,7 @@ def test_versions_required(self): CinderPolicy.objects.create( uuid='1', name='policy 1', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[ DECISION_ACTIONS.AMO_REJECT_VERSION_ADDON.api_value ], @@ -1297,7 +1297,7 @@ def test_delayed_rejection_days_value_not_in_the_future(self): CinderPolicy.objects.create( uuid='1', name='policy 1', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[ DECISION_ACTIONS.AMO_REJECT_VERSION_ADDON.api_value ], @@ -1324,7 +1324,7 @@ def test_delayable_action_missing_fields(self): CinderPolicy.objects.create( uuid='1', name='policy 1', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[ DECISION_ACTIONS.AMO_REJECT_VERSION_ADDON.api_value ], @@ -1594,19 +1594,39 @@ def test_cinder_jobs_to_resolve_choices(self): assert label_two_reports.attr['data-value'] == 'appeal_deny appeal_override' def test_cinder_policies_choices(self): - policy_exposed = CinderPolicy.objects.create( - uuid='1', name='foo', expose_in_reviewer_tools=True + both_policy_exposed = CinderPolicy.objects.create( + uuid='1', name='foo', expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH + ) + ext_policy_exposed = CinderPolicy.objects.create( + uuid='2', name='foo', expose_in_reviewer_tools=POLICY_EXPOSURE.EXTENSION ) CinderPolicy.objects.create( - uuid='2', name='baa', expose_in_reviewer_tools=False + uuid='3', name='baa', expose_in_reviewer_tools=POLICY_EXPOSURE.NONE + ) + thm_policy_exposed = CinderPolicy.objects.create( + uuid='4', name='baa', expose_in_reviewer_tools=POLICY_EXPOSURE.THEME ) form = self.get_form() choices = form.fields['cinder_policies'].choices qs_list = list(choices.queryset) assert qs_list == [ - # only policies that are expose_in_reviewer_tools=True should be included - policy_exposed + # only policies that are expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH + # or POLICY_EXPOSURE.EXTENSION should be included + both_policy_exposed, + ext_policy_exposed, + ] + + # if it's a theme though, it's POLICY_EXPOSURE.THEME instead + self.addon.update(type=amo.ADDON_STATICTHEME) + form = self.get_form() + choices = form.fields['cinder_policies'].choices + qs_list = list(choices.queryset) + assert qs_list == [ + # only policies that are expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH + # or POLICY_EXPOSURE.THEME should be included + both_policy_exposed, + thm_policy_exposed, ] def test_upload_attachment(self): @@ -1637,12 +1657,14 @@ def test_upload_attachment(self): def test_cinder_policy_choices(self): CinderPolicy.objects.create(uuid='not-exposed', name='not exposed') CinderPolicy.objects.create( - uuid='no-enforcement', name='no enforcement', expose_in_reviewer_tools=True + uuid='no-enforcement', + name='no enforcement', + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, ) CinderPolicy.objects.create( uuid='4-rejections', name='for rejections', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[ DECISION_ACTIONS.AMO_DISABLE_ADDON.api_value, 'some-invalid-action', @@ -1653,7 +1675,7 @@ def test_cinder_policy_choices(self): CinderPolicy.objects.create( uuid='4-approve', name='for approving', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_APPROVE.api_value], ) self.file.update(status=amo.STATUS_AWAITING_REVIEW) @@ -1697,7 +1719,7 @@ def test_policy_values_fields(self): policy_0 = CinderPolicy.objects.create( uuid='4-rejections', name='for rejections', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[ DECISION_ACTIONS.AMO_DISABLE_ADDON.api_value, 'some-other-action', @@ -1707,7 +1729,7 @@ def test_policy_values_fields(self): policy_1 = CinderPolicy.objects.create( uuid='4-approve', name='for approving', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_APPROVE.api_value], text='No placeholders here', ) diff --git a/src/olympia/reviewers/tests/test_views.py b/src/olympia/reviewers/tests/test_views.py index 2e8f8879002a..0602154ebbdd 100644 --- a/src/olympia/reviewers/tests/test_views.py +++ b/src/olympia/reviewers/tests/test_views.py @@ -58,7 +58,7 @@ ) from olympia.blocklist.models import Block, BlocklistSubmission, BlockType, BlockVersion from olympia.blocklist.utils import block_activity_log_save -from olympia.constants.abuse import DECISION_ACTIONS +from olympia.constants.abuse import DECISION_ACTIONS, POLICY_EXPOSURE from olympia.constants.promoted import PROMOTED_GROUP_CHOICES from olympia.constants.reviewers import REVIEWER_DELAYED_REJECTION_PERIOD_DAYS_DEFAULT from olympia.constants.scanners import WEBHOOK, YARA @@ -2701,7 +2701,7 @@ def test_resolve_reports_job(self, resolve_mock): ) policy = CinderPolicy.objects.create( uuid='x', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_IGNORE.api_value], ) AbuseReport.objects.create( @@ -4131,7 +4131,7 @@ def review_version(self, version, url, mock_sign): policy = CinderPolicy.objects.create( uuid=uuid.uuid4(), name='policy 1', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_APPROVE.api_value], ) if version.channel == amo.CHANNEL_LISTED: @@ -4415,7 +4415,7 @@ def test_approve_recommended_addon(self, mock_sign_file): policy = CinderPolicy.objects.create( uuid='1', name='policy 1', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_APPROVE.api_value], ) self.version.file.update(status=amo.STATUS_AWAITING_REVIEW) @@ -4448,7 +4448,7 @@ def test_approve_addon_for_unlisted_pre_review_promoted_groups( policy = CinderPolicy.objects.create( uuid='1', name='policy 1', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_APPROVE.api_value], ) self.version.file.update(status=amo.STATUS_AWAITING_REVIEW) @@ -4494,7 +4494,7 @@ def test_policy_required_for_approve(self, mock_sign_file): CinderPolicy.objects.create( uuid='1', name='policy 1', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_APPROVE.api_value], ).id ], @@ -4518,7 +4518,7 @@ def test_approve_listing_content_review(self): CinderPolicy.objects.create( uuid='1', name='policy 1', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_APPROVE.api_value], ).id ], @@ -4575,7 +4575,7 @@ def test_approve_rejected_listing_content_review(self): CinderPolicy.objects.create( uuid='1', name='policy 1', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_APPROVE.api_value], ).id ], @@ -4651,7 +4651,7 @@ def _do_reject_listing_content_review(self, extra_data): def test_reject_listing_content_review_with_policies(self): policy = CinderPolicy.objects.create( uuid='x', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_REJECT_LISTING_CONTENT.api_value], ) extra_data = { @@ -4763,7 +4763,7 @@ def test_approve_multiple_versions(self, sign_file_mock): policy = CinderPolicy.objects.create( uuid='1', name='policy 1', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_APPROVE.api_value], ) old_version = self.version @@ -4836,7 +4836,7 @@ def test_policies_required_for_multiple_approve(self, sign_file_mock): CinderPolicy.objects.create( uuid='1', name='policy 1', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_APPROVE.api_value], ).id ], @@ -4865,7 +4865,7 @@ def test_reject_multiple_versions(self): policy = CinderPolicy.objects.create( uuid='1', name='policy 1', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_REJECT_VERSION_ADDON.api_value], ) old_version = self.version @@ -4906,7 +4906,7 @@ def test_reject_multiple_versions_with_no_delay(self): policy = CinderPolicy.objects.create( uuid='1', name='policy 1', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_REJECT_VERSION_ADDON.api_value], ) old_version = self.version @@ -4950,7 +4950,7 @@ def test_reject_multiple_versions_with_delay(self): policy = CinderPolicy.objects.create( uuid='1', name='policy 1', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[ DECISION_ACTIONS.AMO_REJECT_VERSION_WARNING_ADDON.api_value ], @@ -5002,7 +5002,7 @@ def test_reject(self): policy = CinderPolicy.objects.create( uuid='123-reject', name='Bad thing', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[ DECISION_ACTIONS.AMO_DISABLE_ADDON.api_value, 'some-other-action', @@ -5055,7 +5055,7 @@ def test_form_error_persists_placeholder_values(self): policy = CinderPolicy.objects.create( uuid='123-reject', name='Bad thing', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[ DECISION_ACTIONS.AMO_DISABLE_ADDON.api_value, 'some-other-action', @@ -6598,7 +6598,7 @@ def test_abuse_reports_resolved_as_disable_addon_with_disable_action( policy = CinderPolicy.objects.create( uuid='1', name='policy 1', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_DISABLE_ADDON.api_value], ) self.addon.update(status=amo.STATUS_APPROVED) @@ -6670,7 +6670,7 @@ def test_abuse_reports_resolved_as_approve_with_approve_latest_version_action( CinderPolicy.objects.create( uuid='1', name='policy 1', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_APPROVE.api_value], ).id ], @@ -6783,13 +6783,13 @@ def test_policy_text_rendered(self): policy_fixed = CinderPolicy.objects.create( uuid='no-enforcement', name='no enforcement', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, text='Something something', ) policy_dynamic = CinderPolicy.objects.create( uuid='4-rejections', name='for rejections', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[ DECISION_ACTIONS.AMO_DISABLE_ADDON.api_value, 'some-other-action', @@ -6830,7 +6830,7 @@ def test_review_with_review_with_policy_action_disable(self): policy = CinderPolicy.objects.create( uuid='1', name='policy 1', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_DISABLE_ADDON.api_value], ) response = self.client.post( @@ -6860,7 +6860,7 @@ def test_review_with_review_with_policy_action_reject(self): policy = CinderPolicy.objects.create( uuid='1', name='policy 1', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_REJECT_VERSION_ADDON.api_value], ) old_version = self.version @@ -6902,7 +6902,7 @@ def test_review_with_review_with_policy_action_multiple_reject(self): policy = CinderPolicy.objects.create( uuid='1', name='policy 1', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_REJECT_VERSION_ADDON.api_value], ) old_version = self.version @@ -6942,7 +6942,7 @@ def test_review_with_review_with_policy_action_approve(self): policy = CinderPolicy.objects.create( uuid='1', name='policy 1', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_APPROVE.api_value], ) self.addon.update(status=amo.STATUS_REJECTED) @@ -6977,7 +6977,7 @@ def test_review_with_review_with_policy_action_approve_versions(self, sign_mock) policy = CinderPolicy.objects.create( uuid='1', name='policy 1', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_APPROVE_VERSION.api_value], ) old_version = self.version @@ -7137,7 +7137,7 @@ def test_pending_to_public(self, mock_sign): policy = CinderPolicy.objects.create( uuid='1', name='policy 1', - expose_in_reviewer_tools=True, + expose_in_reviewer_tools=POLICY_EXPOSURE.BOTH, enforcement_actions=[DECISION_ACTIONS.AMO_APPROVE.api_value], ) assert self.version.file.status == amo.STATUS_AWAITING_REVIEW diff --git a/src/olympia/scanners/models.py b/src/olympia/scanners/models.py index a842bed2c032..ddeeb715a3db 100644 --- a/src/olympia/scanners/models.py +++ b/src/olympia/scanners/models.py @@ -22,6 +22,7 @@ ) from olympia.access.models import Group, GroupUser from olympia.amo.models import ModelBase +from olympia.constants.abuse import POLICY_EXPOSURE from olympia.constants.base import ADDON_EXTENSION from olympia.constants.scanners import ( ABORTED, @@ -326,7 +327,9 @@ class ScannerRule(AbstractScannerRule): help_text=( 'Policy used to automatically derive an action from when the rule hit.' ), - limit_choices_to={'expose_in_reviewer_tools': True}, + limit_choices_to={ + 'expose_in_reviewer_tools__in': POLICY_EXPOSURE.FOR_EXTENSIONS + }, ) is_active = models.BooleanField( default=True, diff --git a/src/olympia/scanners/tests/test_actions.py b/src/olympia/scanners/tests/test_actions.py index 2ea082e197e5..b823a19c9dc4 100644 --- a/src/olympia/scanners/tests/test_actions.py +++ b/src/olympia/scanners/tests/test_actions.py @@ -20,7 +20,7 @@ version_factory, ) from olympia.blocklist.models import Block, BlocklistSubmission, BlockType, BlockVersion -from olympia.constants.abuse import DECISION_ACTIONS +from olympia.constants.abuse import DECISION_ACTIONS, POLICY_EXPOSURE from olympia.constants.promoted import PROMOTED_GROUP_CHOICES from olympia.constants.scanners import ( DELAY_AUTO_APPROVAL, @@ -1392,7 +1392,7 @@ def test_execute_policy_enforcement_action(self): text='Just saying.', # expose_in_reviewer_tools shouldn't matter if the link already # exists - it's only for availability in the admin/reviewer tools. - expose_in_reviewer_tools=False, + expose_in_reviewer_tools=POLICY_EXPOSURE.NONE, enforcement_actions=[DECISION_ACTIONS.AMO_DISABLE_ADDON.api_value], ) # Extra useless policy shouldn't get picked up.