implement admin reviewer unreject versions action (#19728)
* implement admin reviewer unreject versions action * don't subscribe the reviewer to the review * move status setting code to Addon model
This commit is contained in:
Родитель
48667c56f2
Коммит
3fcfd57396
|
@ -1235,6 +1235,22 @@ class Addon(OnChangeMixin, ModelBase):
|
|||
|
||||
self.update_version(ignore=ignore_version)
|
||||
|
||||
def update_nominated_status(self, user):
|
||||
# Update the addon status to nominated if there are versions awaiting review
|
||||
if (
|
||||
self.status == amo.STATUS_NULL
|
||||
and self.versions.filter(
|
||||
file__status=amo.STATUS_AWAITING_REVIEW, channel=amo.CHANNEL_LISTED
|
||||
).exists()
|
||||
):
|
||||
log.info(
|
||||
'Changing add-on status [%s]: %s => %s (%s).'
|
||||
% (self.id, self.status, amo.STATUS_NOMINATED, 'unrejecting versions')
|
||||
)
|
||||
self.update(status=amo.STATUS_NOMINATED)
|
||||
activity.log_create(amo.LOG.CHANGE_STATUS, self, self.status, user=user)
|
||||
self.update_version()
|
||||
|
||||
@staticmethod
|
||||
def attach_related_versions(addons, addon_dict=None):
|
||||
if addon_dict is None:
|
||||
|
|
|
@ -2104,6 +2104,29 @@ class TestUpdateStatus(TestCase):
|
|||
amo.STATUS_NULL
|
||||
) # No listed versions so now NULL
|
||||
|
||||
def test_update_nominated_status(self):
|
||||
addon = addon_factory(
|
||||
status=amo.STATUS_NULL, file_kw={'status': amo.STATUS_DISABLED}
|
||||
)
|
||||
first_version = addon.versions.last()
|
||||
version_factory(addon=addon, file_kw={'status': amo.STATUS_APPROVED})
|
||||
user = user_factory()
|
||||
# if add-on has no files that are AWAITING_REVIEW, the status shouldn't change
|
||||
addon.update_nominated_status(user)
|
||||
assert addon.reload().status == amo.STATUS_NULL
|
||||
|
||||
addon.update(status=amo.STATUS_DISABLED)
|
||||
first_version.file.update(status=amo.STATUS_AWAITING_REVIEW)
|
||||
# and neither should the status change if the addon status isn't NULL
|
||||
addon.update_nominated_status(user)
|
||||
addon.refresh_from_db() # this clears the fk relations too
|
||||
assert addon.status == amo.STATUS_DISABLED
|
||||
|
||||
addon.update(status=amo.STATUS_NULL)
|
||||
# success case - has version that is awaiting review and incomplete addon status
|
||||
addon.update_nominated_status(user)
|
||||
assert addon.reload().status == amo.STATUS_NOMINATED
|
||||
|
||||
|
||||
class TestGetVersion(TestCase):
|
||||
fixtures = [
|
||||
|
|
|
@ -844,6 +844,17 @@ class RESTRICTED(_LOG):
|
|||
format = _('{user} restricted.')
|
||||
|
||||
|
||||
class UNREJECT_VERSION(_LOG):
|
||||
# takes add-on, version
|
||||
id = 171
|
||||
action_class = 'reject'
|
||||
format = _('{addon} {version} unrejected.')
|
||||
short = _('Unrejected')
|
||||
keep = True
|
||||
review_queue = True
|
||||
reviewer_review_action = True
|
||||
|
||||
|
||||
LOGS = [x for x in vars().values() if isclass(x) and issubclass(x, _LOG) and x != _LOG]
|
||||
# Make sure there's no duplicate IDs.
|
||||
assert len(LOGS) == len({log.id for log in LOGS})
|
||||
|
|
|
@ -112,11 +112,28 @@ class VersionsChoiceWidget(forms.SelectMultiple):
|
|||
"""
|
||||
|
||||
actions_filters = {
|
||||
amo.STATUS_APPROVED: ('confirm_multiple_versions', 'block_multiple_versions'),
|
||||
amo.STATUS_AWAITING_REVIEW: (
|
||||
'reject_multiple_versions',
|
||||
'approve_multiple_versions',
|
||||
amo.CHANNEL_UNLISTED: {
|
||||
amo.STATUS_APPROVED: (
|
||||
'block_multiple_versions',
|
||||
'confirm_multiple_versions',
|
||||
),
|
||||
amo.STATUS_AWAITING_REVIEW: (
|
||||
'approve_multiple_versions',
|
||||
'reject_multiple_versions',
|
||||
),
|
||||
amo.STATUS_DISABLED: ('unreject_multiple_versions',),
|
||||
},
|
||||
amo.CHANNEL_LISTED: {
|
||||
amo.STATUS_APPROVED: (
|
||||
'block_multiple_versions',
|
||||
'reject_multiple_versions',
|
||||
),
|
||||
amo.STATUS_AWAITING_REVIEW: (
|
||||
'approve_multiple_versions',
|
||||
'reject_multiple_versions',
|
||||
),
|
||||
amo.STATUS_DISABLED: ('unreject_multiple_versions',),
|
||||
},
|
||||
}
|
||||
|
||||
def create_option(self, *args, **kwargs):
|
||||
|
@ -126,13 +143,12 @@ class VersionsChoiceWidget(forms.SelectMultiple):
|
|||
obj = option['label']
|
||||
status = obj.file.status if obj.file else None
|
||||
versions_actions = getattr(self, 'versions_actions', None)
|
||||
if versions_actions and obj.channel == amo.CHANNEL_UNLISTED:
|
||||
# For unlisted, some actions should only apply to approved/pending
|
||||
# versions, so we add our special `data-toggle` class and the
|
||||
# right `data-value` depending on status.
|
||||
if versions_actions:
|
||||
# Add our special `data-toggle` class and the right `data-value` depending
|
||||
# on status.
|
||||
option['attrs']['class'] = 'data-toggle'
|
||||
option['attrs']['data-value'] = '|'.join(
|
||||
self.actions_filters.get(status, ()) + ('',)
|
||||
self.actions_filters[obj.channel].get(status, ()) + ('',)
|
||||
)
|
||||
# Just in case, let's now force the label to be a string (it would be
|
||||
# converted anyway, but it's probably safer that way).
|
||||
|
@ -218,7 +234,7 @@ class ReviewForm(forms.Form):
|
|||
if action:
|
||||
if not action.get('comments', True):
|
||||
self.fields['comments'].required = False
|
||||
if action.get('versions', False):
|
||||
if action.get('multiple_versions', False):
|
||||
self.fields['versions'].required = True
|
||||
if not action.get('requires_reasons', False):
|
||||
self.fields['reasons'].required = False
|
||||
|
@ -255,18 +271,19 @@ class ReviewForm(forms.Form):
|
|||
# if the relevant actions are available, otherwise we don't really care
|
||||
# about this field.
|
||||
versions_actions = [
|
||||
k for k in self.helper.actions if self.helper.actions[k].get('versions')
|
||||
k
|
||||
for k in self.helper.actions
|
||||
if self.helper.actions[k].get('multiple_versions')
|
||||
]
|
||||
if versions_actions:
|
||||
if self.helper.version:
|
||||
channel = self.helper.version.channel
|
||||
else:
|
||||
channel = amo.CHANNEL_LISTED
|
||||
statuses = (amo.STATUS_APPROVED, amo.STATUS_AWAITING_REVIEW)
|
||||
self.fields['versions'].widget.versions_actions = versions_actions
|
||||
self.fields['versions'].queryset = (
|
||||
self.helper.addon.versions(manager='unfiltered_for_relations')
|
||||
.filter(channel=channel, file__status__in=statuses)
|
||||
.filter(channel=channel)
|
||||
.no_transforms()
|
||||
.select_related('file')
|
||||
.select_related('autoapprovalsummary')
|
||||
|
|
|
@ -61,6 +61,16 @@ class TestReviewForm(TestCase):
|
|||
)
|
||||
assert list(actions.keys()) == ['reply', 'super', 'comment']
|
||||
|
||||
# If an admin reviewer we also show unreject_multiple_versions
|
||||
self.grant_permission(self.request.user, 'Reviews:Admin')
|
||||
actions = self.get_form().helper.get_actions()
|
||||
assert list(actions.keys()) == [
|
||||
'unreject_multiple_versions',
|
||||
'reply',
|
||||
'super',
|
||||
'comment',
|
||||
]
|
||||
|
||||
def test_actions_addon_status_deleted(self):
|
||||
# If the add-on is deleted we only show reply, comment and
|
||||
# super review.
|
||||
|
@ -84,7 +94,18 @@ class TestReviewForm(TestCase):
|
|||
'comment',
|
||||
]
|
||||
|
||||
# The add-on is already disabled so we don't show
|
||||
# If an admin reviewer we also show unreject_multiple_versions
|
||||
self.grant_permission(self.request.user, 'Reviews:Admin')
|
||||
actions = self.get_form().helper.get_actions()
|
||||
assert list(actions.keys()) == [
|
||||
'reject_multiple_versions',
|
||||
'unreject_multiple_versions',
|
||||
'reply',
|
||||
'super',
|
||||
'comment',
|
||||
]
|
||||
|
||||
# The add-on is already disabled so we don't show unreject_multiple_versions or
|
||||
# reject_multiple_versions, but reply/super/comment are still present.
|
||||
actions = self.set_statuses_and_get_actions(
|
||||
addon_status=amo.STATUS_DISABLED, file_status=amo.STATUS_DISABLED
|
||||
|
@ -266,14 +287,24 @@ class TestReviewForm(TestCase):
|
|||
assert form.fields['versions'].required is False
|
||||
assert list(form.fields['versions'].queryset) == [self.addon.current_version]
|
||||
|
||||
def test_versions_queryset_contains_pending_files_for_listed(self):
|
||||
def test_versions_queryset_contains_pending_files_for_listed(
|
||||
self, select_data_value='reject_multiple_versions|'
|
||||
):
|
||||
# We hide some of the versions using JavaScript + some data attributes on each
|
||||
# <option>.
|
||||
# The queryset should contain both pending, rejected, and approved versions.
|
||||
self.grant_permission(self.request.user, 'Addons:Review')
|
||||
addon_factory() # Extra add-on, shouldn't be included.
|
||||
version_factory(
|
||||
pending_version = version_factory(
|
||||
addon=self.addon,
|
||||
channel=amo.CHANNEL_LISTED,
|
||||
file_kw={'status': amo.STATUS_AWAITING_REVIEW},
|
||||
)
|
||||
rejected_version = version_factory(
|
||||
addon=self.addon,
|
||||
channel=amo.CHANNEL_LISTED,
|
||||
file_kw={'status': amo.STATUS_DISABLED},
|
||||
)
|
||||
# auto-approve everything (including self.addon.current_version)
|
||||
for version in Version.unfiltered.all():
|
||||
AutoApprovalSummary.objects.create(
|
||||
|
@ -285,35 +316,71 @@ class TestReviewForm(TestCase):
|
|||
assert list(form.fields['versions'].queryset) == list(
|
||||
self.addon.versions.all().order_by('pk')
|
||||
)
|
||||
assert form.fields['versions'].queryset.count() == 2
|
||||
assert form.fields['versions'].queryset.count() == 3
|
||||
|
||||
content = str(form['versions'])
|
||||
doc = pq(content)
|
||||
|
||||
# <select> should have 'data-toggle' class and data-value attribute to
|
||||
# show/hide it depending on action in JavaScript.
|
||||
select = doc('select')[0]
|
||||
select.attrib.get('class') == 'data-toggle'
|
||||
assert select.attrib.get('data-value') == 'reject_multiple_versions|'
|
||||
assert select.attrib.get('data-value') == select_data_value
|
||||
|
||||
# <option>s shouldn't, because for listed review they will all be
|
||||
# shown. They should still have a value attribute however.
|
||||
options = doc('option')
|
||||
assert len(options) == 2
|
||||
for option in options:
|
||||
assert option.attrib.get('class') is None
|
||||
assert option.attrib.get('data-value') is None
|
||||
assert option.attrib.get('value')
|
||||
# <option>s should as well, and the value depends on which version:
|
||||
# the approved one and the pending one should have different values.
|
||||
assert len(doc('option')) == 3
|
||||
option1 = doc('option[value="%s"]' % self.version.pk)[0]
|
||||
assert option1.attrib.get('class') == 'data-toggle'
|
||||
assert option1.attrib.get('data-value') == (
|
||||
# That version is approved.
|
||||
'block_multiple_versions|reject_multiple_versions|'
|
||||
)
|
||||
assert option1.attrib.get('value') == str(self.version.pk)
|
||||
|
||||
def test_versions_queryset_contains_pending_files_for_unlisted(self):
|
||||
# We also return pending versions for unlisted, but hide some of the
|
||||
# versions using JavaScript + some data attributes on each <option>.
|
||||
# The queryset should contain both pending and approved versions.
|
||||
option2 = doc('option[value="%s"]' % pending_version.pk)[0]
|
||||
assert option2.attrib.get('class') == 'data-toggle'
|
||||
assert option2.attrib.get('data-value') == (
|
||||
# That version is pending.
|
||||
'approve_multiple_versions|reject_multiple_versions|'
|
||||
)
|
||||
assert option2.attrib.get('value') == str(pending_version.pk)
|
||||
|
||||
option3 = doc('option[value="%s"]' % rejected_version.pk)[0]
|
||||
assert option3.attrib.get('class') == 'data-toggle'
|
||||
assert option3.attrib.get('data-value') == (
|
||||
# That version is rejected.
|
||||
'unreject_multiple_versions|'
|
||||
)
|
||||
assert option3.attrib.get('value') == str(rejected_version.pk)
|
||||
|
||||
def test_versions_queryset_contains_pending_files_for_listed_admin_reviewer(self):
|
||||
self.grant_permission(self.request.user, 'Reviews:Admin')
|
||||
self.test_versions_queryset_contains_pending_files_for_listed(
|
||||
select_data_value='reject_multiple_versions|unreject_multiple_versions|'
|
||||
)
|
||||
|
||||
def test_versions_queryset_contains_pending_files_for_unlisted(
|
||||
self,
|
||||
select_data_value=(
|
||||
'approve_multiple_versions|reject_multiple_versions|'
|
||||
'block_multiple_versions|confirm_multiple_versions|'
|
||||
),
|
||||
):
|
||||
# We hide some of the versions using JavaScript + some data attributes on each
|
||||
# <option>.
|
||||
# The queryset should contain both pending, rejected, and approved versions.
|
||||
addon_factory() # Extra add-on, shouldn't be included.
|
||||
pending_version = version_factory(
|
||||
addon=self.addon,
|
||||
channel=amo.CHANNEL_UNLISTED,
|
||||
file_kw={'status': amo.STATUS_AWAITING_REVIEW},
|
||||
)
|
||||
rejected_version = version_factory(
|
||||
addon=self.addon,
|
||||
channel=amo.CHANNEL_UNLISTED,
|
||||
file_kw={'status': amo.STATUS_DISABLED},
|
||||
)
|
||||
self.version.update(channel=amo.CHANNEL_UNLISTED)
|
||||
# auto-approve everything
|
||||
for version in Version.unfiltered.all():
|
||||
|
@ -334,27 +401,25 @@ class TestReviewForm(TestCase):
|
|||
assert list(form.fields['versions'].queryset) == list(
|
||||
self.addon.versions.all().order_by('pk')
|
||||
)
|
||||
assert form.fields['versions'].queryset.count() == 2
|
||||
assert form.fields['versions'].queryset.count() == 3
|
||||
|
||||
content = str(form['versions'])
|
||||
doc = pq(content)
|
||||
|
||||
# <select> should have 'data-toggle' class and data-value attribute to
|
||||
# show/hide it depending on action in JavaScript.
|
||||
select = doc('select')[0]
|
||||
select.attrib.get('class') == 'data-toggle'
|
||||
assert select.attrib.get('data-value') == (
|
||||
'approve_multiple_versions|reject_multiple_versions|'
|
||||
'block_multiple_versions|confirm_multiple_versions|'
|
||||
)
|
||||
assert select.attrib.get('data-value') == select_data_value
|
||||
|
||||
# <option>s should as well, and the value depends on which version:
|
||||
# the approved one and the pending one should have different values.
|
||||
assert len(doc('option')) == 2
|
||||
assert len(doc('option')) == 3
|
||||
option1 = doc('option[value="%s"]' % self.version.pk)[0]
|
||||
assert option1.attrib.get('class') == 'data-toggle'
|
||||
assert option1.attrib.get('data-value') == (
|
||||
# That version is approved.
|
||||
'confirm_multiple_versions|block_multiple_versions|'
|
||||
'block_multiple_versions|confirm_multiple_versions|'
|
||||
)
|
||||
assert option1.attrib.get('value') == str(self.version.pk)
|
||||
|
||||
|
@ -362,10 +427,28 @@ class TestReviewForm(TestCase):
|
|||
assert option2.attrib.get('class') == 'data-toggle'
|
||||
assert option2.attrib.get('data-value') == (
|
||||
# That version is pending.
|
||||
'reject_multiple_versions|approve_multiple_versions|'
|
||||
'approve_multiple_versions|reject_multiple_versions|'
|
||||
)
|
||||
assert option2.attrib.get('value') == str(pending_version.pk)
|
||||
|
||||
option3 = doc('option[value="%s"]' % rejected_version.pk)[0]
|
||||
assert option3.attrib.get('class') == 'data-toggle'
|
||||
assert option3.attrib.get('data-value') == (
|
||||
# That version is rejected.
|
||||
'unreject_multiple_versions|'
|
||||
)
|
||||
assert option3.attrib.get('value') == str(rejected_version.pk)
|
||||
|
||||
def test_versions_queryset_contains_pending_files_for_unlisted_admin_reviewer(self):
|
||||
self.grant_permission(self.request.user, 'Reviews:Admin')
|
||||
self.test_versions_queryset_contains_pending_files_for_unlisted(
|
||||
select_data_value=(
|
||||
'approve_multiple_versions|reject_multiple_versions|'
|
||||
'unreject_multiple_versions|block_multiple_versions|'
|
||||
'confirm_multiple_versions|'
|
||||
)
|
||||
)
|
||||
|
||||
def test_versions_required(self):
|
||||
# auto-approve everything (including self.addon.current_version)
|
||||
for version in Version.unfiltered.all():
|
||||
|
|
|
@ -73,9 +73,9 @@ class TestReviewHelperBase(TestCase):
|
|||
|
||||
self.user = UserProfile.objects.get(pk=10482)
|
||||
self.addon = Addon.objects.get(pk=3615)
|
||||
self.version = self.addon.versions.all()[0]
|
||||
self.review_version = self.addon.versions.all()[0]
|
||||
self.helper = self.get_helper()
|
||||
self.file = self.version.file
|
||||
self.file = self.review_version.file
|
||||
|
||||
self.create_paths()
|
||||
|
||||
|
@ -110,7 +110,8 @@ class TestReviewHelperBase(TestCase):
|
|||
self.file.update(status=file_status)
|
||||
if channel == amo.CHANNEL_UNLISTED:
|
||||
self.make_addon_unlisted(self.addon)
|
||||
self.version.reload()
|
||||
if self.review_version:
|
||||
self.review_version.reload()
|
||||
self.file.reload()
|
||||
self.helper = self.get_helper(
|
||||
content_review=content_review, human_review=human_review
|
||||
|
@ -129,7 +130,7 @@ class TestReviewHelperBase(TestCase):
|
|||
def get_helper(self, content_review=False, human_review=True):
|
||||
return ReviewHelper(
|
||||
addon=self.addon,
|
||||
version=self.version,
|
||||
version=self.review_version,
|
||||
user=self.user,
|
||||
human_review=human_review,
|
||||
content_review=content_review,
|
||||
|
@ -173,7 +174,7 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
def test_review_files(self):
|
||||
version_factory(
|
||||
addon=self.addon,
|
||||
created=self.version.created - timedelta(days=1),
|
||||
created=self.review_version.created - timedelta(days=1),
|
||||
file_kw={'status': amo.STATUS_APPROVED},
|
||||
)
|
||||
for status in REVIEW_FILES_STATUSES:
|
||||
|
@ -396,7 +397,7 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
"""Deleted addons and addons with no versions in that channel have no
|
||||
version set."""
|
||||
expected = []
|
||||
self.version = None
|
||||
self.review_version = None
|
||||
assert (
|
||||
list(
|
||||
self.get_review_actions(
|
||||
|
@ -556,6 +557,7 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
'public',
|
||||
'reject',
|
||||
'reject_multiple_versions',
|
||||
'unreject_multiple_versions',
|
||||
'reply',
|
||||
'super',
|
||||
'comment',
|
||||
|
@ -573,7 +575,7 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
def test_actions_unlisted(self):
|
||||
# Just regular review permissions don't let you do much on an unlisted
|
||||
# review page.
|
||||
self.version.update(channel=amo.CHANNEL_UNLISTED)
|
||||
self.review_version.update(channel=amo.CHANNEL_UNLISTED)
|
||||
self.grant_permission(self.user, 'Addons:Review')
|
||||
expected = ['reply', 'super', 'comment']
|
||||
assert (
|
||||
|
@ -653,7 +655,7 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
)
|
||||
|
||||
# it's okay if the version is outside the blocked range though
|
||||
block.update(min_version=self.version.version + '.1')
|
||||
block.update(min_version=self.review_version.version + '.1')
|
||||
expected = [
|
||||
'public',
|
||||
'reject',
|
||||
|
@ -672,7 +674,7 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
version=self.addon.current_version, verdict=amo.AUTO_APPROVED
|
||||
)
|
||||
version_review_flags_factory(
|
||||
version=self.version, pending_rejection=datetime.now()
|
||||
version=self.review_version, pending_rejection=datetime.now()
|
||||
)
|
||||
expected = ['reply', 'super', 'comment']
|
||||
assert (
|
||||
|
@ -693,8 +695,8 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
'super',
|
||||
'comment',
|
||||
]
|
||||
self.version = version_factory(addon=self.addon)
|
||||
self.file = self.version.file
|
||||
self.review_version = version_factory(addon=self.addon)
|
||||
self.file = self.review_version.file
|
||||
|
||||
assert (
|
||||
list(
|
||||
|
@ -715,11 +717,12 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
version=self.addon.current_version, verdict=amo.AUTO_APPROVED
|
||||
)
|
||||
version_review_flags_factory(
|
||||
version=self.version, pending_rejection=datetime.now()
|
||||
version=self.review_version, pending_rejection=datetime.now()
|
||||
)
|
||||
expected = [
|
||||
'confirm_auto_approved',
|
||||
'reject_multiple_versions',
|
||||
'unreject_multiple_versions',
|
||||
'reply',
|
||||
'super',
|
||||
'comment',
|
||||
|
@ -743,12 +746,13 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
'reject',
|
||||
'confirm_auto_approved',
|
||||
'reject_multiple_versions',
|
||||
'unreject_multiple_versions',
|
||||
'reply',
|
||||
'super',
|
||||
'comment',
|
||||
]
|
||||
self.version = version_factory(addon=self.addon)
|
||||
self.file = self.version.file
|
||||
self.review_version = version_factory(addon=self.addon)
|
||||
self.file = self.review_version.file
|
||||
assert (
|
||||
list(
|
||||
self.get_review_actions(
|
||||
|
@ -789,9 +793,9 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
|
||||
def test_set_file(self):
|
||||
self.file.update(datestatuschanged=yesterday)
|
||||
self.helper.handler.set_file(amo.STATUS_APPROVED, self.version.file)
|
||||
self.helper.handler.set_file(amo.STATUS_APPROVED, self.review_version.file)
|
||||
|
||||
self.file = self.version.file
|
||||
self.file = self.review_version.file
|
||||
assert self.file.status == amo.STATUS_APPROVED
|
||||
assert self.file.datestatuschanged.date() > yesterday.date()
|
||||
|
||||
|
@ -835,8 +839,8 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
self.helper.set_data(self.get_data())
|
||||
base_fragment = 'To respond, please reply to this email or visit'
|
||||
user = self.addon.listed_authors[0]
|
||||
ActivityLogToken.objects.create(version=self.version, user=user)
|
||||
uuid = self.version.token.get(user=user).uuid.hex
|
||||
ActivityLogToken.objects.create(version=self.review_version, user=user)
|
||||
uuid = self.review_version.token.get(user=user).uuid.hex
|
||||
reply_email = f'reviewreply+{uuid}@{settings.INBOUND_EMAIL_DOMAIN}'
|
||||
|
||||
templates = (
|
||||
|
@ -951,7 +955,7 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
status = amo.STATUS_NOMINATED
|
||||
self.setup_data(status)
|
||||
AutoApprovalSummary.objects.create(
|
||||
version=self.version, verdict=amo.AUTO_APPROVED, weight=101
|
||||
version=self.review_version, verdict=amo.AUTO_APPROVED, weight=101
|
||||
)
|
||||
|
||||
# Make sure we have no public files
|
||||
|
@ -985,31 +989,31 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
|
||||
def test_nomination_to_public_need_human_review(self):
|
||||
self.setup_data(amo.STATUS_NOMINATED)
|
||||
self.version.update(needs_human_review=True)
|
||||
self.review_version.update(needs_human_review=True)
|
||||
self.helper.handler.approve_latest_version()
|
||||
self.addon.reload()
|
||||
self.version.reload()
|
||||
self.review_version.reload()
|
||||
self.file.reload()
|
||||
assert self.addon.status == amo.STATUS_APPROVED
|
||||
assert self.file.status == amo.STATUS_APPROVED
|
||||
assert not self.version.needs_human_review
|
||||
assert not self.review_version.needs_human_review
|
||||
|
||||
def test_nomination_to_public_need_human_review_not_human(self):
|
||||
self.setup_data(amo.STATUS_NOMINATED, human_review=False)
|
||||
self.version.update(needs_human_review=True)
|
||||
self.review_version.update(needs_human_review=True)
|
||||
self.helper.handler.approve_latest_version()
|
||||
self.addon.reload()
|
||||
self.version.reload()
|
||||
self.review_version.reload()
|
||||
self.file.reload()
|
||||
assert self.addon.status == amo.STATUS_APPROVED
|
||||
assert self.file.status == amo.STATUS_APPROVED
|
||||
assert self.version.needs_human_review
|
||||
assert self.review_version.needs_human_review
|
||||
|
||||
def test_unlisted_approve_latest_version_need_human_review(self):
|
||||
self.setup_data(amo.STATUS_NULL, channel=amo.CHANNEL_UNLISTED)
|
||||
self.version.update(needs_human_review=True)
|
||||
self.review_version.update(needs_human_review=True)
|
||||
flags = version_review_flags_factory(
|
||||
version=self.version,
|
||||
version=self.review_version,
|
||||
needs_human_review_by_mad=True,
|
||||
)
|
||||
AddonReviewerFlags.objects.create(
|
||||
|
@ -1017,13 +1021,13 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
)
|
||||
self.helper.handler.approve_latest_version()
|
||||
self.addon.reload()
|
||||
self.version.reload()
|
||||
self.review_version.reload()
|
||||
self.file.reload()
|
||||
flags.reload()
|
||||
addon_flags = self.addon.reviewerflags.reload()
|
||||
assert self.addon.status == amo.STATUS_NULL
|
||||
assert self.file.status == amo.STATUS_APPROVED
|
||||
assert not self.version.needs_human_review
|
||||
assert not self.review_version.needs_human_review
|
||||
assert not flags.needs_human_review_by_mad
|
||||
assert not addon_flags.auto_approval_disabled_until_next_approval_unlisted
|
||||
|
||||
|
@ -1031,22 +1035,22 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
self.setup_data(
|
||||
amo.STATUS_NULL, channel=amo.CHANNEL_UNLISTED, human_review=False
|
||||
)
|
||||
self.version.update(needs_human_review=True)
|
||||
self.review_version.update(needs_human_review=True)
|
||||
flags = version_review_flags_factory(
|
||||
version=self.version, needs_human_review_by_mad=True
|
||||
version=self.review_version, needs_human_review_by_mad=True
|
||||
)
|
||||
AddonReviewerFlags.objects.create(
|
||||
addon=self.addon, auto_approval_disabled_until_next_approval_unlisted=True
|
||||
)
|
||||
self.helper.handler.approve_latest_version()
|
||||
self.addon.reload()
|
||||
self.version.reload()
|
||||
self.review_version.reload()
|
||||
self.file.reload()
|
||||
flags.reload()
|
||||
addon_flags = self.addon.reviewerflags.reload()
|
||||
assert self.addon.status == amo.STATUS_NULL
|
||||
assert self.file.status == amo.STATUS_APPROVED
|
||||
assert self.version.needs_human_review
|
||||
assert self.review_version.needs_human_review
|
||||
assert flags.needs_human_review_by_mad
|
||||
|
||||
# Not changed this this is not a human approval.
|
||||
|
@ -1075,7 +1079,8 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
self.sign_file_mock.reset()
|
||||
self.setup_data(amo.STATUS_NOMINATED)
|
||||
AutoApprovalSummary.objects.update_or_create(
|
||||
version=self.version, defaults={'verdict': amo.AUTO_APPROVED, 'weight': 101}
|
||||
version=self.review_version,
|
||||
defaults={'verdict': amo.AUTO_APPROVED, 'weight': 101},
|
||||
)
|
||||
|
||||
self.helper.handler.approve_latest_version()
|
||||
|
@ -1102,7 +1107,7 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
def test_old_nomination_to_public_bonus_score(self):
|
||||
self.sign_file_mock.reset()
|
||||
self.setup_data(amo.STATUS_NOMINATED, type=amo.ADDON_STATICTHEME)
|
||||
self.version.update(nomination=self.days_ago(9))
|
||||
self.review_version.update(nomination=self.days_ago(9))
|
||||
|
||||
self.helper.handler.approve_latest_version()
|
||||
|
||||
|
@ -1160,7 +1165,7 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
def test_public_addon_with_version_awaiting_review_to_public(self):
|
||||
self.sign_file_mock.reset()
|
||||
self.addon.current_version.update(created=self.days_ago(1))
|
||||
self.version = version_factory(
|
||||
self.review_version = version_factory(
|
||||
addon=self.addon,
|
||||
channel=amo.CHANNEL_LISTED,
|
||||
version='3.0.42',
|
||||
|
@ -1170,10 +1175,10 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
},
|
||||
)
|
||||
self.preamble = 'Mozilla Add-ons: Delicious Bookmarks 3.0.42'
|
||||
self.file = self.version.file
|
||||
self.file = self.review_version.file
|
||||
self.setup_data(amo.STATUS_APPROVED)
|
||||
AutoApprovalSummary.objects.create(
|
||||
version=self.version, verdict=amo.AUTO_APPROVED, weight=101
|
||||
version=self.review_version, verdict=amo.AUTO_APPROVED, weight=101
|
||||
)
|
||||
self.create_paths()
|
||||
AddonApprovalsCounter.objects.create(
|
||||
|
@ -1217,13 +1222,13 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
def test_public_addon_with_version_need_human_review_to_public(self):
|
||||
self.old_version = self.addon.current_version
|
||||
self.old_version.update(created=self.days_ago(1), needs_human_review=True)
|
||||
self.version = version_factory(
|
||||
self.review_version = version_factory(
|
||||
addon=self.addon,
|
||||
channel=amo.CHANNEL_LISTED,
|
||||
version='3.0.42',
|
||||
file_kw={'status': amo.STATUS_AWAITING_REVIEW},
|
||||
)
|
||||
self.file = self.version.file
|
||||
self.file = self.review_version.file
|
||||
self.setup_data(amo.STATUS_APPROVED)
|
||||
|
||||
self.helper.handler.approve_latest_version()
|
||||
|
@ -1239,13 +1244,13 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
AddonReviewerFlags.objects.create(
|
||||
addon=self.addon, auto_approval_disabled_until_next_approval=True
|
||||
)
|
||||
self.version = version_factory(
|
||||
self.review_version = version_factory(
|
||||
addon=self.addon,
|
||||
channel=amo.CHANNEL_LISTED,
|
||||
version='3.0.42',
|
||||
file_kw={'status': amo.STATUS_AWAITING_REVIEW},
|
||||
)
|
||||
self.file = self.version.file
|
||||
self.file = self.review_version.file
|
||||
self.setup_data(amo.STATUS_APPROVED)
|
||||
|
||||
self.helper.handler.approve_latest_version()
|
||||
|
@ -1260,7 +1265,7 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
def test_public_addon_with_version_awaiting_review_to_sandbox(self):
|
||||
self.sign_file_mock.reset()
|
||||
self.addon.current_version.update(created=self.days_ago(1))
|
||||
self.version = version_factory(
|
||||
self.review_version = version_factory(
|
||||
addon=self.addon,
|
||||
channel=amo.CHANNEL_LISTED,
|
||||
version='3.0.42',
|
||||
|
@ -1270,10 +1275,10 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
},
|
||||
)
|
||||
self.preamble = 'Mozilla Add-ons: Delicious Bookmarks 3.0.42'
|
||||
self.file = self.version.file
|
||||
self.file = self.review_version.file
|
||||
self.setup_data(amo.STATUS_APPROVED)
|
||||
AutoApprovalSummary.objects.create(
|
||||
version=self.version, verdict=amo.AUTO_APPROVED, weight=101
|
||||
version=self.review_version, verdict=amo.AUTO_APPROVED, weight=101
|
||||
)
|
||||
AddonApprovalsCounter.objects.create(addon=self.addon, counter=1)
|
||||
|
||||
|
@ -1308,14 +1313,14 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
def test_public_addon_with_version_need_human_review_to_sandbox(self):
|
||||
self.old_version = self.addon.current_version
|
||||
self.old_version.update(created=self.days_ago(1), needs_human_review=True)
|
||||
self.version = version_factory(
|
||||
self.review_version = version_factory(
|
||||
addon=self.addon,
|
||||
channel=amo.CHANNEL_LISTED,
|
||||
version='3.0.42',
|
||||
needs_human_review=True,
|
||||
file_kw={'status': amo.STATUS_AWAITING_REVIEW},
|
||||
)
|
||||
self.file = self.version.file
|
||||
self.file = self.review_version.file
|
||||
self.setup_data(amo.STATUS_APPROVED)
|
||||
|
||||
self.helper.handler.reject_latest_version()
|
||||
|
@ -1332,14 +1337,14 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
self.addon.current_version.reload()
|
||||
assert self.addon.current_version.needs_human_review
|
||||
|
||||
self.version.reload()
|
||||
assert not self.version.needs_human_review
|
||||
self.review_version.reload()
|
||||
assert not self.review_version.needs_human_review
|
||||
|
||||
def test_public_addon_confirm_auto_approval(self):
|
||||
self.grant_permission(self.user, 'Addons:Review')
|
||||
self.setup_data(amo.STATUS_APPROVED, file_status=amo.STATUS_APPROVED)
|
||||
summary = AutoApprovalSummary.objects.create(
|
||||
version=self.version, verdict=amo.AUTO_APPROVED, weight=151
|
||||
version=self.review_version, verdict=amo.AUTO_APPROVED, weight=151
|
||||
)
|
||||
assert summary.confirmed is None
|
||||
self.create_paths()
|
||||
|
@ -1362,7 +1367,7 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
.filter(action=amo.LOG.CONFIRM_AUTO_APPROVED.id)
|
||||
.get()
|
||||
)
|
||||
assert activity.arguments == [self.addon, self.version]
|
||||
assert activity.arguments == [self.addon, self.review_version]
|
||||
assert activity.details['comments'] == ''
|
||||
|
||||
# Check points awarded.
|
||||
|
@ -1371,16 +1376,16 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
def test_public_with_unreviewed_version_addon_confirm_auto_approval(self):
|
||||
self.grant_permission(self.user, 'Addons:Review')
|
||||
self.setup_data(amo.STATUS_APPROVED, file_status=amo.STATUS_APPROVED)
|
||||
self.current_version = self.version
|
||||
self.current_version = self.review_version
|
||||
summary = AutoApprovalSummary.objects.create(
|
||||
version=self.version, verdict=amo.AUTO_APPROVED, weight=152
|
||||
version=self.review_version, verdict=amo.AUTO_APPROVED, weight=152
|
||||
)
|
||||
self.version = version_factory(
|
||||
self.review_version = version_factory(
|
||||
addon=self.addon,
|
||||
version='3.0',
|
||||
file_kw={'status': amo.STATUS_AWAITING_REVIEW},
|
||||
)
|
||||
self.file = self.version.file
|
||||
self.file = self.review_version.file
|
||||
self.helper = self.get_helper() # To make it pick up the new version.
|
||||
self.helper.set_data(self.get_data())
|
||||
|
||||
|
@ -1410,14 +1415,14 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
def test_public_with_disabled_version_addon_confirm_auto_approval(self):
|
||||
self.grant_permission(self.user, 'Addons:Review')
|
||||
self.setup_data(amo.STATUS_APPROVED, file_status=amo.STATUS_APPROVED)
|
||||
self.current_version = self.version
|
||||
self.current_version = self.review_version
|
||||
summary = AutoApprovalSummary.objects.create(
|
||||
version=self.version, verdict=amo.AUTO_APPROVED, weight=153
|
||||
version=self.review_version, verdict=amo.AUTO_APPROVED, weight=153
|
||||
)
|
||||
self.version = version_factory(
|
||||
self.review_version = version_factory(
|
||||
addon=self.addon, version='3.0', file_kw={'status': amo.STATUS_DISABLED}
|
||||
)
|
||||
self.file = self.version.file
|
||||
self.file = self.review_version.file
|
||||
self.helper = self.get_helper() # To make it pick up the new version.
|
||||
self.helper.set_data(self.get_data())
|
||||
|
||||
|
@ -1448,12 +1453,12 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
self.grant_permission(self.user, 'Addons:Review')
|
||||
self.grant_permission(self.user, 'Reviews:Admin')
|
||||
self.setup_data(amo.STATUS_APPROVED, file_status=amo.STATUS_APPROVED)
|
||||
self.version = version_factory(
|
||||
self.review_version = version_factory(
|
||||
addon=self.addon, version='3.0', file_kw={'status': amo.STATUS_APPROVED}
|
||||
)
|
||||
self.file = self.version.file
|
||||
self.file = self.review_version.file
|
||||
summary = AutoApprovalSummary.objects.create(
|
||||
version=self.version, verdict=amo.AUTO_APPROVED, weight=153
|
||||
version=self.review_version, verdict=amo.AUTO_APPROVED, weight=153
|
||||
)
|
||||
|
||||
for version in self.addon.versions.all():
|
||||
|
@ -1483,7 +1488,7 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
.filter(action=amo.LOG.CONFIRM_AUTO_APPROVED.id)
|
||||
.get()
|
||||
)
|
||||
assert activity.arguments == [self.addon, self.version]
|
||||
assert activity.arguments == [self.addon, self.review_version]
|
||||
assert activity.details['comments'] == ''
|
||||
|
||||
# None of the versions should be pending rejection anymore.
|
||||
|
@ -1523,9 +1528,9 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
def test_confirm_multiple_versions_with_version_scanner_flags(self):
|
||||
self.grant_permission(self.user, 'Addons:ReviewUnlisted')
|
||||
self.setup_data(amo.STATUS_APPROVED, file_status=amo.STATUS_APPROVED)
|
||||
self.version.update(channel=amo.CHANNEL_UNLISTED)
|
||||
self.review_version.update(channel=amo.CHANNEL_UNLISTED)
|
||||
flags = version_review_flags_factory(
|
||||
version=self.version,
|
||||
version=self.review_version,
|
||||
needs_human_review_by_mad=True,
|
||||
)
|
||||
assert flags.needs_human_review_by_mad
|
||||
|
@ -1565,14 +1570,14 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
needs_human_review=True,
|
||||
created=self.days_ago(6),
|
||||
)
|
||||
self.version = version_factory(
|
||||
self.review_version = version_factory(
|
||||
addon=self.addon,
|
||||
version='5.0',
|
||||
channel=amo.CHANNEL_UNLISTED,
|
||||
needs_human_review=True,
|
||||
created=self.days_ago(5),
|
||||
)
|
||||
self.file = self.version.file
|
||||
self.file = self.review_version.file
|
||||
self.helper = self.get_helper() # To make it pick up the new version.
|
||||
data = self.get_data().copy()
|
||||
data['versions'] = self.addon.versions.filter(
|
||||
|
@ -1589,8 +1594,8 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
summary.reload()
|
||||
assert summary.confirmed is True
|
||||
|
||||
self.version.reload()
|
||||
assert self.version.needs_human_review # Untouched.
|
||||
self.review_version.reload()
|
||||
assert self.review_version.needs_human_review # Untouched.
|
||||
|
||||
second_unlisted.reload()
|
||||
assert not second_unlisted.needs_human_review # Cleared.
|
||||
|
@ -1627,7 +1632,8 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
message = mail.outbox[0]
|
||||
assert message.subject == ('%s signed and ready to download' % self.preamble)
|
||||
assert (
|
||||
'%s is now signed and ready for you to download' % self.version.version
|
||||
'%s is now signed and ready for you to download'
|
||||
% self.review_version.version
|
||||
in message.body
|
||||
)
|
||||
assert 'You received this email because' not in message.body
|
||||
|
@ -1781,16 +1787,16 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
assert self.addon.needs_admin_code_review
|
||||
|
||||
def test_nominated_review_time_set_version_approve_latest_version(self):
|
||||
self.version.update(reviewed=None)
|
||||
self.review_version.update(reviewed=None)
|
||||
self.setup_data(amo.STATUS_NOMINATED)
|
||||
self.helper.handler.approve_latest_version()
|
||||
assert self.version.reload().reviewed
|
||||
assert self.review_version.reload().reviewed
|
||||
|
||||
def test_nominated_review_time_set_version_reject_latest_version(self):
|
||||
self.version.update(reviewed=None)
|
||||
self.review_version.update(reviewed=None)
|
||||
self.setup_data(amo.STATUS_NOMINATED)
|
||||
self.helper.handler.reject_latest_version()
|
||||
assert self.version.reload().reviewed
|
||||
assert self.review_version.reload().reviewed
|
||||
|
||||
def test_nominated_review_time_set_file_approve_latest_version(self):
|
||||
self.file.update(reviewed=None)
|
||||
|
@ -1806,7 +1812,7 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
|
||||
def test_review_unlisted_while_a_listed_version_is_awaiting_review(self):
|
||||
self.make_addon_unlisted(self.addon)
|
||||
self.version.reload()
|
||||
self.review_version.reload()
|
||||
version_factory(
|
||||
addon=self.addon,
|
||||
channel=amo.CHANNEL_LISTED,
|
||||
|
@ -1816,10 +1822,10 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
assert self.get_helper()
|
||||
|
||||
def test_reject_multiple_versions(self):
|
||||
old_version = self.version
|
||||
self.version = version_factory(addon=self.addon, version='3.0')
|
||||
old_version = self.review_version
|
||||
self.review_version = version_factory(addon=self.addon, version='3.0')
|
||||
AutoApprovalSummary.objects.create(
|
||||
version=self.version, verdict=amo.AUTO_APPROVED, weight=101
|
||||
version=self.review_version, verdict=amo.AUTO_APPROVED, weight=101
|
||||
)
|
||||
self.setup_data(amo.STATUS_APPROVED, file_status=amo.STATUS_APPROVED)
|
||||
|
||||
|
@ -1838,7 +1844,7 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
self.file.reload()
|
||||
assert self.addon.status == amo.STATUS_NULL
|
||||
assert self.addon.current_version is None
|
||||
assert list(self.addon.versions.all()) == [self.version, old_version]
|
||||
assert list(self.addon.versions.all()) == [self.review_version, old_version]
|
||||
assert self.file.status == amo.STATUS_DISABLED
|
||||
|
||||
# The versions are not pending rejection.
|
||||
|
@ -1878,14 +1884,14 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
# The reviewer should have been automatically subscribed to new listed
|
||||
# versions.
|
||||
assert ReviewerSubscription.objects.filter(
|
||||
addon=self.addon, user=self.user, channel=self.version.channel
|
||||
addon=self.addon, user=self.user, channel=self.review_version.channel
|
||||
).exists()
|
||||
|
||||
def test_reject_multiple_versions_with_delay(self):
|
||||
old_version = self.version
|
||||
self.version = version_factory(addon=self.addon, version='3.0')
|
||||
old_version = self.review_version
|
||||
self.review_version = version_factory(addon=self.addon, version='3.0')
|
||||
AutoApprovalSummary.objects.create(
|
||||
version=self.version, verdict=amo.AUTO_APPROVED, weight=101
|
||||
version=self.review_version, verdict=amo.AUTO_APPROVED, weight=101
|
||||
)
|
||||
self.setup_data(amo.STATUS_APPROVED, file_status=amo.STATUS_APPROVED)
|
||||
|
||||
|
@ -1912,8 +1918,8 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
self.addon.reload()
|
||||
self.file.reload()
|
||||
assert self.addon.status == amo.STATUS_APPROVED
|
||||
assert self.addon.current_version == self.version
|
||||
assert list(self.addon.versions.all()) == [self.version, old_version]
|
||||
assert self.addon.current_version == self.review_version
|
||||
assert list(self.addon.versions.all()) == [self.review_version, old_version]
|
||||
assert self.file.status == amo.STATUS_APPROVED
|
||||
|
||||
# The versions are now pending rejection.
|
||||
|
@ -1958,16 +1964,16 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
# The reviewer should have been automatically subscribed to new listed
|
||||
# versions.
|
||||
assert ReviewerSubscription.objects.filter(
|
||||
addon=self.addon, user=self.user, channel=self.version.channel
|
||||
addon=self.addon, user=self.user, channel=self.review_version.channel
|
||||
).exists()
|
||||
|
||||
def test_reject_multiple_versions_except_latest(self):
|
||||
old_version = self.version
|
||||
old_version = self.review_version
|
||||
extra_version = version_factory(addon=self.addon, version='3.1')
|
||||
# Add yet another version we don't want to reject.
|
||||
self.version = version_factory(addon=self.addon, version='42.0')
|
||||
self.review_version = version_factory(addon=self.addon, version='42.0')
|
||||
AutoApprovalSummary.objects.create(
|
||||
version=self.version, verdict=amo.AUTO_APPROVED, weight=91
|
||||
version=self.review_version, verdict=amo.AUTO_APPROVED, weight=91
|
||||
)
|
||||
self.setup_data(amo.STATUS_APPROVED, file_status=amo.STATUS_APPROVED)
|
||||
|
||||
|
@ -1978,7 +1984,7 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
assert self.addon.current_version.is_public()
|
||||
|
||||
data = self.get_data().copy()
|
||||
data['versions'] = self.addon.versions.all().exclude(pk=self.version.pk)
|
||||
data['versions'] = self.addon.versions.all().exclude(pk=self.review_version.pk)
|
||||
self.helper.set_data(data)
|
||||
self.helper.handler.reject_multiple_versions()
|
||||
|
||||
|
@ -1986,9 +1992,9 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
self.file.reload()
|
||||
# latest_version is still public so the add-on is still public.
|
||||
assert self.addon.status == amo.STATUS_APPROVED
|
||||
assert self.addon.current_version == self.version
|
||||
assert self.addon.current_version == self.review_version
|
||||
assert list(self.addon.versions.all().order_by('-pk')) == [
|
||||
self.version,
|
||||
self.review_version,
|
||||
extra_version,
|
||||
old_version,
|
||||
]
|
||||
|
@ -2001,7 +2007,7 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
'Mozilla Add-ons: Versions disabled for Delicious Bookmarks'
|
||||
)
|
||||
assert 'Version(s) affected and disabled:\n3.1, 2.1.072' in message.body
|
||||
log_token = ActivityLogToken.objects.filter(version=self.version).get()
|
||||
log_token = ActivityLogToken.objects.filter(version=self.review_version).get()
|
||||
assert log_token.uuid.hex in message.reply_to[0]
|
||||
|
||||
assert self.check_log_count(amo.LOG.REJECT_VERSION.id) == 2
|
||||
|
@ -2011,9 +2017,9 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
self._check_score(amo.REVIEWED_EXTENSION_MEDIUM_RISK)
|
||||
|
||||
def test_reject_multiple_versions_need_human_review(self):
|
||||
old_version = self.version
|
||||
old_version = self.review_version
|
||||
old_version.update(needs_human_review=True)
|
||||
self.version = version_factory(
|
||||
self.review_version = version_factory(
|
||||
addon=self.addon, version='3.0', needs_human_review=True
|
||||
)
|
||||
|
||||
|
@ -2026,7 +2032,7 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
self.file.reload()
|
||||
assert self.addon.status == amo.STATUS_NULL
|
||||
assert self.addon.current_version is None
|
||||
assert list(self.addon.versions.all()) == [self.version, old_version]
|
||||
assert list(self.addon.versions.all()) == [self.review_version, old_version]
|
||||
# We rejected all versions so there aren't any left that need human
|
||||
# review.
|
||||
assert not self.addon.versions.filter(needs_human_review=True).exists()
|
||||
|
@ -2034,8 +2040,8 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
|
||||
def test_reject_multiple_versions_content_review(self):
|
||||
self.grant_permission(self.user, 'Addons:ContentReview')
|
||||
old_version = self.version
|
||||
self.version = version_factory(addon=self.addon, version='3.0')
|
||||
old_version = self.review_version
|
||||
self.review_version = version_factory(addon=self.addon, version='3.0')
|
||||
self.setup_data(
|
||||
amo.STATUS_APPROVED, file_status=amo.STATUS_APPROVED, content_review=True
|
||||
)
|
||||
|
@ -2055,7 +2061,7 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
self.file.reload()
|
||||
assert self.addon.status == amo.STATUS_NULL
|
||||
assert self.addon.current_version is None
|
||||
assert list(self.addon.versions.all()) == [self.version, old_version]
|
||||
assert list(self.addon.versions.all()) == [self.review_version, old_version]
|
||||
assert self.file.status == amo.STATUS_DISABLED
|
||||
|
||||
assert len(mail.outbox) == 1
|
||||
|
@ -2077,8 +2083,8 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
|
||||
def test_reject_multiple_versions_content_review_with_delay(self):
|
||||
self.grant_permission(self.user, 'Addons:ContentReview')
|
||||
old_version = self.version
|
||||
self.version = version_factory(addon=self.addon, version='3.0')
|
||||
old_version = self.review_version
|
||||
self.review_version = version_factory(addon=self.addon, version='3.0')
|
||||
self.setup_data(
|
||||
amo.STATUS_APPROVED, file_status=amo.STATUS_APPROVED, content_review=True
|
||||
)
|
||||
|
@ -2086,7 +2092,7 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
# Pre-subscribe the user to new listed versions of this add-on, it
|
||||
# shouldn't matter.
|
||||
ReviewerSubscription.objects.create(
|
||||
addon=self.addon, user=self.user, channel=self.version.channel
|
||||
addon=self.addon, user=self.user, channel=self.review_version.channel
|
||||
)
|
||||
|
||||
in_the_future = datetime.now() + timedelta(days=14)
|
||||
|
@ -2112,8 +2118,8 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
self.addon.reload()
|
||||
self.file.reload()
|
||||
assert self.addon.status == amo.STATUS_APPROVED
|
||||
assert self.addon.current_version == self.version
|
||||
assert list(self.addon.versions.all()) == [self.version, old_version]
|
||||
assert self.addon.current_version == self.review_version
|
||||
assert list(self.addon.versions.all()) == [self.review_version, old_version]
|
||||
assert self.file.status == amo.STATUS_APPROVED
|
||||
|
||||
# The versions are now pending rejection.
|
||||
|
@ -2148,13 +2154,109 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
# The reviewer was already subscribed to new listed versions for this
|
||||
# addon, nothing has changed.
|
||||
assert ReviewerSubscription.objects.filter(
|
||||
addon=self.addon, user=self.user, channel=self.version.channel
|
||||
addon=self.addon, user=self.user, channel=self.review_version.channel
|
||||
).exists()
|
||||
|
||||
def test_unreject_multiple_versions_approved_addon(self):
|
||||
first_version = self.review_version
|
||||
self.review_version = version_factory(
|
||||
addon=self.addon, version='3.0', file_kw={'status': amo.STATUS_DISABLED}
|
||||
)
|
||||
self.file = self.review_version.file
|
||||
|
||||
# Safeguards.
|
||||
assert isinstance(self.helper.handler, ReviewFiles)
|
||||
assert self.addon.status == amo.STATUS_APPROVED
|
||||
assert first_version.file.status == amo.STATUS_APPROVED
|
||||
assert self.file.status == amo.STATUS_DISABLED
|
||||
assert self.addon.current_version.is_public()
|
||||
assert self.addon.current_version == first_version
|
||||
|
||||
data = self.get_data().copy()
|
||||
data['versions'] = [self.review_version]
|
||||
self.helper.set_data(data)
|
||||
self.helper.handler.unreject_multiple_versions()
|
||||
|
||||
self.addon.reload()
|
||||
self.file.reload()
|
||||
assert self.addon.status == amo.STATUS_APPROVED
|
||||
assert self.addon.current_version == first_version
|
||||
assert list(self.addon.versions.all()) == [self.review_version, first_version]
|
||||
assert self.file.status == amo.STATUS_AWAITING_REVIEW
|
||||
|
||||
assert len(mail.outbox) == 0
|
||||
|
||||
assert self.check_log_count(amo.LOG.UNREJECT_VERSION.id) == 1
|
||||
|
||||
def test_unreject_multiple_versions_with_unlisted(self):
|
||||
old_version = self.review_version
|
||||
self.review_version = version_factory(addon=self.addon, version='3.0')
|
||||
self.file = self.review_version.file
|
||||
self.setup_data(
|
||||
amo.STATUS_NULL,
|
||||
file_status=amo.STATUS_DISABLED,
|
||||
channel=amo.CHANNEL_UNLISTED,
|
||||
)
|
||||
|
||||
# Safeguards.
|
||||
assert isinstance(self.helper.handler, ReviewUnlisted)
|
||||
assert self.addon.status == amo.STATUS_NULL
|
||||
assert old_version.file.status == amo.STATUS_APPROVED
|
||||
assert self.file.status == amo.STATUS_DISABLED
|
||||
assert self.addon.current_version is None
|
||||
|
||||
data = self.get_data().copy()
|
||||
data['versions'] = [self.review_version]
|
||||
self.helper.set_data(data)
|
||||
self.helper.handler.unreject_multiple_versions()
|
||||
|
||||
self.addon.reload()
|
||||
self.file.reload()
|
||||
assert self.addon.status == amo.STATUS_NULL
|
||||
assert self.addon.current_version is None
|
||||
assert list(self.addon.versions.all()) == [self.review_version, old_version]
|
||||
assert self.file.status == amo.STATUS_AWAITING_REVIEW
|
||||
|
||||
assert len(mail.outbox) == 0
|
||||
|
||||
assert self.check_log_count(amo.LOG.UNREJECT_VERSION.id) == 1
|
||||
|
||||
def test_unreject_multiple_versions_incomplete_addon(self):
|
||||
old_version = self.review_version
|
||||
old_version.file.update(status=amo.STATUS_DISABLED)
|
||||
self.review_version = version_factory(
|
||||
addon=self.addon, version='3.0', file_kw={'status': amo.STATUS_DISABLED}
|
||||
)
|
||||
self.file = self.review_version.file
|
||||
self.setup_data(amo.STATUS_NULL, file_status=amo.STATUS_DISABLED)
|
||||
|
||||
# Safeguards.
|
||||
assert isinstance(self.helper.handler, ReviewFiles)
|
||||
assert self.addon.status == amo.STATUS_NULL
|
||||
assert old_version.file.status == amo.STATUS_DISABLED
|
||||
assert self.file.status == amo.STATUS_DISABLED
|
||||
assert self.addon.current_version is None
|
||||
|
||||
data = self.get_data().copy()
|
||||
data['versions'] = [self.review_version]
|
||||
self.helper.set_data(data)
|
||||
self.helper.handler.unreject_multiple_versions()
|
||||
|
||||
self.addon.reload()
|
||||
self.file.reload()
|
||||
assert self.addon.status == amo.STATUS_NOMINATED
|
||||
assert self.addon.current_version == self.review_version
|
||||
assert list(self.addon.versions.all()) == [self.review_version, old_version]
|
||||
assert self.file.status == amo.STATUS_AWAITING_REVIEW
|
||||
|
||||
assert len(mail.outbox) == 0
|
||||
|
||||
assert self.check_log_count(amo.LOG.UNREJECT_VERSION.id) == 1
|
||||
|
||||
def test_approve_multiple_versions_unlisted(self):
|
||||
old_version = self.version
|
||||
old_version = self.review_version
|
||||
self.make_addon_unlisted(self.addon)
|
||||
self.version = version_factory(
|
||||
self.review_version = version_factory(
|
||||
addon=self.addon,
|
||||
version='3.0',
|
||||
channel=amo.CHANNEL_UNLISTED,
|
||||
|
@ -2181,7 +2283,7 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
self.file.reload()
|
||||
assert self.addon.status == amo.STATUS_NULL
|
||||
assert self.addon.current_version is None
|
||||
assert list(self.addon.versions.all()) == [self.version, old_version]
|
||||
assert list(self.addon.versions.all()) == [self.review_version, old_version]
|
||||
assert self.file.status == amo.STATUS_APPROVED
|
||||
|
||||
# unlisted auto approvals should be enabled again
|
||||
|
@ -2212,16 +2314,16 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
assert logs[0].created == logs[1].created
|
||||
|
||||
def test_reject_multiple_versions_unlisted(self):
|
||||
old_version = self.version
|
||||
old_version = self.review_version
|
||||
self.make_addon_unlisted(self.addon)
|
||||
self.version = version_factory(
|
||||
self.review_version = version_factory(
|
||||
addon=self.addon,
|
||||
version='3.0',
|
||||
channel=amo.CHANNEL_UNLISTED,
|
||||
file_kw={'status': amo.STATUS_AWAITING_REVIEW},
|
||||
)
|
||||
AutoApprovalSummary.objects.create(
|
||||
version=self.version, verdict=amo.AUTO_APPROVED, weight=101
|
||||
version=self.review_version, verdict=amo.AUTO_APPROVED, weight=101
|
||||
)
|
||||
self.setup_data(amo.STATUS_NULL, file_status=amo.STATUS_AWAITING_REVIEW)
|
||||
|
||||
|
@ -2239,7 +2341,7 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
self.file.reload()
|
||||
assert self.addon.status == amo.STATUS_NULL
|
||||
assert self.addon.current_version is None
|
||||
assert list(self.addon.versions.all()) == [self.version, old_version]
|
||||
assert list(self.addon.versions.all()) == [self.review_version, old_version]
|
||||
assert self.file.status == amo.STATUS_DISABLED
|
||||
|
||||
# unlisted auto approvals should be disabled until the next manual approval.
|
||||
|
@ -2275,9 +2377,9 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
def _test_reject_multiple_versions_delayed(self, content_review):
|
||||
# Do a rejection with delay.
|
||||
original_user = self.user
|
||||
self.version = version_factory(addon=self.addon, version='3.0')
|
||||
self.review_version = version_factory(addon=self.addon, version='3.0')
|
||||
AutoApprovalSummary.objects.create(
|
||||
version=self.version, verdict=amo.AUTO_APPROVED, weight=101
|
||||
version=self.review_version, verdict=amo.AUTO_APPROVED, weight=101
|
||||
)
|
||||
self.setup_data(
|
||||
amo.STATUS_APPROVED,
|
||||
|
@ -2356,7 +2458,7 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
amo.STATUS_APPROVED, file_status=amo.STATUS_APPROVED, content_review=True
|
||||
)
|
||||
summary = AutoApprovalSummary.objects.create(
|
||||
version=self.version, verdict=amo.AUTO_APPROVED
|
||||
version=self.review_version, verdict=amo.AUTO_APPROVED
|
||||
)
|
||||
self.create_paths()
|
||||
|
||||
|
@ -2380,7 +2482,7 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
.filter(action=amo.LOG.APPROVE_CONTENT.id)
|
||||
.get()
|
||||
)
|
||||
assert activity.arguments == [self.addon, self.version]
|
||||
assert activity.arguments == [self.addon, self.review_version]
|
||||
assert activity.details['comments'] == ''
|
||||
|
||||
# Check points awarded.
|
||||
|
@ -2393,7 +2495,7 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
self.addon.get_dev_url('versions')
|
||||
)
|
||||
|
||||
self.version.update(channel=amo.CHANNEL_UNLISTED)
|
||||
self.review_version.update(channel=amo.CHANNEL_UNLISTED)
|
||||
context_data = self.helper.handler.get_context_data()
|
||||
assert context_data['dev_versions_url'] == absolutify(
|
||||
reverse('devhub.addons.versions', args=[self.addon.id])
|
||||
|
@ -2467,8 +2569,8 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
assert self.addon.promoted_group() == STRATEGIC
|
||||
|
||||
def _test_block_multiple_unlisted_versions(self, redirect_url):
|
||||
old_version = self.version
|
||||
self.version = version_factory(
|
||||
old_version = self.review_version
|
||||
self.review_version = version_factory(
|
||||
addon=self.addon, version='3.0', needs_human_review=True
|
||||
)
|
||||
self.setup_data(
|
||||
|
@ -2478,7 +2580,7 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
)
|
||||
# Add a needs_human_review_by_mad flag that should be cleared later.
|
||||
version_review_flags_factory(
|
||||
version=self.version, needs_human_review_by_mad=True
|
||||
version=self.review_version, needs_human_review_by_mad=True
|
||||
)
|
||||
# Safeguards.
|
||||
assert isinstance(self.helper.handler, ReviewUnlisted)
|
||||
|
@ -2506,7 +2608,7 @@ class TestReviewHelper(TestReviewHelperBase):
|
|||
|
||||
# We should have set redirect_url to point to the Block admin page
|
||||
if '%s' in redirect_url:
|
||||
redirect_url = redirect_url % (old_version.pk, self.version.pk)
|
||||
redirect_url = redirect_url % (old_version.pk, self.review_version.pk)
|
||||
assert self.helper.redirect_url == redirect_url
|
||||
|
||||
def test_pending_blocklistsubmission_multiple_unlisted_versions(self):
|
||||
|
@ -2564,9 +2666,9 @@ class TestReviewHelperSigning(TestReviewHelperBase):
|
|||
file_kw={'filename': 'webextension.xpi'},
|
||||
users=[self.user],
|
||||
)
|
||||
self.version = self.addon.versions.all()[0]
|
||||
self.review_version = self.addon.versions.all()[0]
|
||||
self.helper = self.get_helper()
|
||||
self.file = self.version.file
|
||||
self.file = self.review_version.file
|
||||
|
||||
def test_nomination_to_public(self):
|
||||
self.setup_data(amo.STATUS_NOMINATED)
|
||||
|
|
|
@ -2864,6 +2864,7 @@ class TestReview(ReviewBase):
|
|||
'public',
|
||||
'reject',
|
||||
'reject_multiple_versions',
|
||||
'unreject_multiple_versions',
|
||||
'reply',
|
||||
'super',
|
||||
'comment',
|
||||
|
@ -5008,6 +5009,85 @@ class TestReview(ReviewBase):
|
|||
assert version.pending_rejection
|
||||
self.assertCloseToNow(version.pending_rejection, now=in_the_future)
|
||||
|
||||
def test_unreject_multiple_versions(self):
|
||||
old_version = self.version
|
||||
version_factory(addon=self.addon, version='2.99')
|
||||
old_version.file.update(status=amo.STATUS_DISABLED)
|
||||
self.version = version_factory(
|
||||
addon=self.addon, version='3.0', file_kw={'status': amo.STATUS_DISABLED}
|
||||
)
|
||||
GroupUser.objects.filter(user=self.reviewer).all().delete()
|
||||
self.grant_permission(self.reviewer, 'Addons:Review')
|
||||
self.grant_permission(self.reviewer, 'Reviews:Admin')
|
||||
assert self.addon.status == amo.STATUS_APPROVED
|
||||
|
||||
response = self.client.post(
|
||||
self.url,
|
||||
{
|
||||
'action': 'unreject_multiple_versions',
|
||||
'versions': [old_version.pk, self.version.pk],
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == 302
|
||||
for version in [old_version, self.version]:
|
||||
file_ = version.file.reload()
|
||||
assert file_.status == amo.STATUS_AWAITING_REVIEW
|
||||
assert self.addon.reload().status == amo.STATUS_APPROVED
|
||||
|
||||
def test_unreject_multiple_versions_to_nominated(self):
|
||||
old_version = self.version
|
||||
old_version.file.update(status=amo.STATUS_DISABLED)
|
||||
self.version = version_factory(
|
||||
addon=self.addon, version='3.0', file_kw={'status': amo.STATUS_DISABLED}
|
||||
)
|
||||
GroupUser.objects.filter(user=self.reviewer).all().delete()
|
||||
self.grant_permission(self.reviewer, 'Addons:Review')
|
||||
self.grant_permission(self.reviewer, 'Reviews:Admin')
|
||||
assert self.addon.status == amo.STATUS_NULL
|
||||
|
||||
response = self.client.post(
|
||||
self.url,
|
||||
{
|
||||
'action': 'unreject_multiple_versions',
|
||||
'versions': [old_version.pk, self.version.pk],
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == 302
|
||||
for version in [old_version, self.version]:
|
||||
file_ = version.file.reload()
|
||||
assert file_.status == amo.STATUS_AWAITING_REVIEW
|
||||
assert self.addon.reload().status == amo.STATUS_NOMINATED
|
||||
|
||||
def test_unreject_multiple_versions_with_unlisted(self):
|
||||
old_version = self.version
|
||||
old_version.file.update(status=amo.STATUS_DISABLED)
|
||||
self.version = version_factory(
|
||||
addon=self.addon, version='3.0', file_kw={'status': amo.STATUS_DISABLED}
|
||||
)
|
||||
self.make_addon_unlisted(self.addon)
|
||||
GroupUser.objects.filter(user=self.reviewer).all().delete()
|
||||
self.grant_permission(self.reviewer, 'Addons:Review')
|
||||
self.grant_permission(self.reviewer, 'Reviews:Admin')
|
||||
self.grant_permission(self.reviewer, 'Addons:ReviewUnlisted')
|
||||
assert self.addon.status == amo.STATUS_NULL
|
||||
|
||||
unlisted_url = reverse('reviewers.review', args=['unlisted', self.addon.pk])
|
||||
response = self.client.post(
|
||||
unlisted_url,
|
||||
{
|
||||
'action': 'unreject_multiple_versions',
|
||||
'versions': [old_version.pk, self.version.pk],
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == 302
|
||||
for version in [old_version, self.version]:
|
||||
file_ = version.file.reload()
|
||||
assert file_.status == amo.STATUS_AWAITING_REVIEW
|
||||
assert self.addon.reload().status == amo.STATUS_NULL
|
||||
|
||||
def test_block_multiple_versions(self):
|
||||
self.url = reverse('reviewers.review', args=('unlisted', self.addon.pk))
|
||||
old_version = self.version
|
||||
|
|
|
@ -561,9 +561,11 @@ class ReviewHelper:
|
|||
is_appropriate_reviewer_post_review = acl.action_allowed_for(
|
||||
self.user, permission_post_review
|
||||
)
|
||||
is_admin_reviewer = is_appropriate_reviewer and acl.action_allowed_for(
|
||||
self.user, amo.permissions.REVIEWS_ADMIN
|
||||
)
|
||||
|
||||
addon_is_complete_and_not_disabled = self.addon.status not in (
|
||||
amo.STATUS_NULL,
|
||||
addon_is_not_disabled_or_deleted = self.addon.status not in (
|
||||
amo.STATUS_DELETED,
|
||||
amo.STATUS_DISABLED,
|
||||
)
|
||||
|
@ -571,9 +573,8 @@ class ReviewHelper:
|
|||
self.addon.status == amo.STATUS_NULL and version_is_unlisted
|
||||
)
|
||||
addon_is_reviewable = (
|
||||
addon_is_complete_and_not_disabled
|
||||
or addon_is_incomplete_and_version_is_unlisted
|
||||
)
|
||||
addon_is_not_disabled_or_deleted and self.addon.status != amo.STATUS_NULL
|
||||
) or addon_is_incomplete_and_version_is_unlisted
|
||||
version_is_unreviewed = self.version and self.version.is_unreviewed
|
||||
addon_is_valid = self.addon.is_public() or self.addon.is_unreviewed()
|
||||
addon_is_valid_and_version_is_listed = (
|
||||
|
@ -689,7 +690,7 @@ class ReviewHelper:
|
|||
'method': self.handler.approve_multiple_versions,
|
||||
'label': _('Approve Multiple Versions'),
|
||||
'minimal': True,
|
||||
'versions': True,
|
||||
'multiple_versions': True,
|
||||
'details': _(
|
||||
'This will approve the selected versions. '
|
||||
'The comments will be sent to the developer.'
|
||||
|
@ -708,7 +709,7 @@ class ReviewHelper:
|
|||
# or (unlisted and) awaiting review
|
||||
or self.version.file.status == amo.STATUS_AWAITING_REVIEW
|
||||
),
|
||||
'versions': True,
|
||||
'multiple_versions': True,
|
||||
'details': _(
|
||||
'This will reject the selected versions. '
|
||||
'The comments will be sent to the developer.'
|
||||
|
@ -717,11 +718,23 @@ class ReviewHelper:
|
|||
'allows_reasons': not is_static_theme,
|
||||
'requires_reasons': not is_static_theme,
|
||||
}
|
||||
actions['unreject_multiple_versions'] = {
|
||||
'method': self.handler.unreject_multiple_versions,
|
||||
'label': _('Un-Reject Versions'),
|
||||
'minimal': True,
|
||||
'multiple_versions': True,
|
||||
'details': _(
|
||||
'This will un-reject the selected versions without notifying the '
|
||||
'developer.'
|
||||
),
|
||||
'comments': False,
|
||||
'available': (addon_is_not_disabled_or_deleted and is_admin_reviewer),
|
||||
}
|
||||
actions['block_multiple_versions'] = {
|
||||
'method': self.handler.block_multiple_versions,
|
||||
'label': _('Block Multiple Versions'),
|
||||
'minimal': True,
|
||||
'versions': True,
|
||||
'multiple_versions': True,
|
||||
'comments': False,
|
||||
'details': _(
|
||||
'This will disable the selected approved '
|
||||
|
@ -736,7 +749,7 @@ class ReviewHelper:
|
|||
'method': self.handler.confirm_multiple_versions,
|
||||
'label': _('Confirm Multiple Versions'),
|
||||
'minimal': True,
|
||||
'versions': True,
|
||||
'multiple_versions': True,
|
||||
'details': _(
|
||||
'This will confirm approval of the selected '
|
||||
'versions without notifying the developer.'
|
||||
|
@ -1360,6 +1373,37 @@ class ReviewBase:
|
|||
content_review=self.content_review,
|
||||
)
|
||||
|
||||
def unreject_multiple_versions(self):
|
||||
"""Un-reject a list of versions."""
|
||||
# self.version and self.file won't point to the versions we want to
|
||||
# modify in this action, so set them to None before finding the right
|
||||
# versions.
|
||||
self.version = None
|
||||
self.file = None
|
||||
now = datetime.now()
|
||||
# we're only supporting non-automated reviews right now:
|
||||
assert self.human_review
|
||||
|
||||
log.info(
|
||||
'Making %s versions %s awaiting review (not disabled)'
|
||||
% (self.addon, ', '.join(str(v.pk) for v in self.data['versions']))
|
||||
)
|
||||
|
||||
for version in self.data['versions']:
|
||||
self.set_file(amo.STATUS_AWAITING_REVIEW, version.file)
|
||||
|
||||
self.log_action(
|
||||
action=amo.LOG.UNREJECT_VERSION,
|
||||
version=version,
|
||||
file=version.file,
|
||||
timestamp=now,
|
||||
user=self.user,
|
||||
)
|
||||
|
||||
if self.data['versions']:
|
||||
# if these are listed versions then the addon status may need updating
|
||||
self.addon.update_nominated_status(self.user)
|
||||
|
||||
def notify_about_auto_approval_delay(self, version):
|
||||
"""Notify developers of the add-on when their version has not been
|
||||
auto-approved for a while."""
|
||||
|
|
Загрузка…
Ссылка в новой задаче