in src/olympia/reviewers/utils.py [0:0]
def get_actions(self):
actions = OrderedDict()
# 2 kind of checks are made for the review page.
# - Base permission checks to access the review page itself, done in
# the review() view
# - A more specific check for each action, done below, restricting
# their availability while not affecting whether the user can see
# the review page or not.
version_is_unlisted = (
self.version and self.version.channel == amo.CHANNEL_UNLISTED
)
version_is_listed = self.version and self.version.channel == amo.CHANNEL_LISTED
promoted_group = self.addon.promoted_groups(currently_approved=False)
is_static_theme = self.addon.type == amo.ADDON_STATICTHEME
# Default permissions / admin needed values if it's just a regular
# code review, nothing fancy.
permission = amo.permissions.ADDONS_REVIEW
permission_post_review = amo.permissions.ADDONS_REVIEW
is_admin_needed = is_admin_needed_post_review = False
# More complex/specific cases.
if PROMOTED_GROUP_CHOICES.RECOMMENDED in promoted_group.group_id:
permission = amo.permissions.ADDONS_RECOMMENDED_REVIEW
permission_post_review = permission
elif version_is_unlisted:
permission = amo.permissions.ADDONS_REVIEW_UNLISTED
permission_post_review = permission
elif any(promoted_group.admin_review):
is_admin_needed = is_admin_needed_post_review = True
elif self.content_review:
permission = amo.permissions.ADDONS_CONTENT_REVIEW
elif is_static_theme:
is_admin_needed = self.addon.needs_admin_theme_review
permission = amo.permissions.STATIC_THEMES_REVIEW
permission_post_review = permission
# In addition, if the latest (or current for post-review) version is
# pending rejection, an admin is needed.
if self.version and self.version.pending_rejection:
is_admin_needed = True
if self.addon.current_version and self.addon.current_version.pending_rejection:
is_admin_needed_post_review = True
# Whatever permission values we set, we override if an admin is needed.
if is_admin_needed:
permission = amo.permissions.REVIEWS_ADMIN
if is_admin_needed_post_review:
permission_post_review = amo.permissions.REVIEWS_ADMIN
# Is the current user a reviewer for this kind of add-on ?
is_reviewer = acl.is_reviewer(self.user, self.addon)
# Is the current user an appropriate reviewer, not only for this kind
# of add-on, but also for the state the add-on is in ? (Allows more
# impactful actions).
is_appropriate_reviewer = acl.action_allowed_for(self.user, permission)
is_appropriate_reviewer_post_review = acl.action_allowed_for(
self.user, permission_post_review
)
is_appropriate_admin_reviewer = is_appropriate_reviewer and is_admin_reviewer(
self.user
)
addon_is_not_deleted = self.addon.status != amo.STATUS_DELETED
addon_is_not_disabled = self.addon.status != amo.STATUS_DISABLED
addon_is_not_disabled_or_deleted = self.addon.status not in (
amo.STATUS_DELETED,
amo.STATUS_DISABLED,
)
addon_is_incomplete_and_version_is_unlisted = (
self.addon.status == amo.STATUS_NULL and version_is_unlisted
)
addon_is_reviewable = (
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
version_was_rejected = bool(
self.version
and self.version.file.status == amo.STATUS_DISABLED
and self.version.human_review_date
)
addon_is_valid = self.addon.is_public() or self.addon.is_unreviewed()
addon_is_valid_and_version_is_listed = addon_is_valid and version_is_listed
current_or_latest_listed_version_was_auto_approved = version_is_listed and (
(
self.addon.current_version
and self.addon.current_version.was_auto_approved
)
or (not self.addon.current_version and self.version.was_auto_approved)
)
version_is_blocked = self.version and self.version.is_blocked
self.unresolved_cinderjob_qs = (
CinderJob.objects.for_addon(self.addon)
.unresolved()
.resolvable_in_reviewer_tools()
.prefetch_related(
'abusereport_set',
'appealed_decisions__cinder_job',
'appealed_decisions__override_of__cinder_job',
'appealed_decisions__appeals',
)
)
unresolved_cinder_jobs = list(self.unresolved_cinderjob_qs)
has_unresolved_abuse_report_jobs = any(
job for job in unresolved_cinder_jobs if not job.is_appeal
)
has_unresolved_appeal_jobs = any(
job for job in unresolved_cinder_jobs if job.is_appeal
)
# Special logic for availability of reject/approve multiple action:
if version_is_unlisted:
can_reject_multiple = is_appropriate_reviewer
can_approve_multiple = is_appropriate_reviewer
elif (
self.content_review
or any(promoted_group.listed_pre_review)
or is_static_theme
):
can_reject_multiple = (
addon_is_valid_and_version_is_listed and is_appropriate_reviewer
)
can_approve_multiple = False
else:
# When doing a code review, this action is also available to
# users with Addons:PostReview even if the current version hasn't
# been auto-approved, provided that the add-on isn't marked as
# needing admin review.
can_reject_multiple = addon_is_valid_and_version_is_listed and (
is_appropriate_reviewer
or is_appropriate_reviewer_post_review
or not self.human_review
)
can_approve_multiple = False
# Definitions for all actions.
actions['public'] = {
'method': self.handler.approve_latest_version,
'minimal': False,
'details': (
'This will approve, sign, and publish this '
'version. The comments will be sent to the '
'developer.'
),
'label': 'Approve',
'available': (
not self.content_review
and addon_is_reviewable
and version_is_unreviewed
and (is_appropriate_reviewer or not self.human_review)
and not version_is_blocked
),
'allows_reasons': not is_static_theme,
'resolves_cinder_jobs': True,
'requires_reasons': False,
'requires_reasons_for_cinder_jobs': False,
'boilerplate_text': 'Thank you for your contribution.',
'can_attach': True,
}
actions['reject'] = {
'method': self.handler.reject_latest_version,
'label': 'Reject',
'details': (
'This will reject this version and remove it '
'from the queue. The comments will be sent '
'to the developer.'
),
'minimal': False,
'available': (
not self.content_review
# We specifically don't let the individual reject action be
# available for unlisted review. `reject_latest_version` isn't
# currently implemented for unlisted.
and addon_is_valid_and_version_is_listed
and version_is_unreviewed
and is_appropriate_reviewer
),
'allows_reasons': True,
'resolves_cinder_jobs': True,
'requires_reasons': not is_static_theme,
'requires_reasons_for_cinder_jobs': True,
}
actions['approve_content'] = {
'method': self.handler.approve_content,
'label': 'Approve Content',
'details': (
'This records your approbation of the '
'content of the latest public version, '
'without notifying the developer.'
),
'minimal': False,
'comments': False,
'available': (
self.content_review
and addon_is_valid_and_version_is_listed
and is_appropriate_reviewer
),
}
actions['confirm_auto_approved'] = {
'method': self.handler.confirm_auto_approved,
'label': 'Confirm Approval',
'details': (
'The latest public version of this add-on was '
'automatically approved. This records your '
'confirmation of the approval of that version, '
'without notifying the developer.'
),
'minimal': True,
'comments': False,
'available': (
not self.content_review
and current_or_latest_listed_version_was_auto_approved
and is_appropriate_reviewer_post_review
),
'resolves_cinder_jobs': True,
}
actions['approve_multiple_versions'] = {
'method': self.handler.approve_multiple_versions,
'label': 'Approve Multiple Versions',
'minimal': True,
'multiple_versions': True,
'details': (
'This will approve the selected versions. '
'The comments will be sent to the developer.'
),
'available': (can_approve_multiple),
'allows_reasons': not is_static_theme,
'resolves_cinder_jobs': True,
'requires_reasons': False,
'requires_reasons_for_cinder_jobs': False,
}
actions['reject_multiple_versions'] = {
'method': self.handler.reject_multiple_versions,
'label': 'Reject Multiple Versions',
'minimal': True,
'delayable': True,
'multiple_versions': True,
'details': (
'This will reject the selected versions. '
'The comments will be sent to the developer.'
),
'available': can_reject_multiple,
'allows_reasons': True,
'resolves_cinder_jobs': True,
'requires_reasons': not is_static_theme,
'requires_reasons_for_cinder_jobs': True,
}
actions['unreject_latest_version'] = {
'method': self.handler.unreject_latest_version,
'label': 'Un-reject',
'minimal': True,
'details': (
'This will un-reject the latest version without notifying the '
'developer.'
),
'comments': False,
'available': (
not version_is_unlisted
and addon_is_not_disabled_or_deleted
and version_was_rejected
and is_appropriate_admin_reviewer
),
}
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': (
version_is_unlisted
and addon_is_not_disabled_or_deleted
and is_appropriate_admin_reviewer
),
}
actions['block_multiple_versions'] = {
'method': self.handler.block_multiple_versions,
'label': 'Block Multiple Versions',
'minimal': True,
'multiple_versions': True,
'comments': False,
'details': (
'This will disable the selected approved '
'versions silently, and open up the block creation '
'admin page.'
),
'available': (
not is_static_theme and version_is_unlisted and is_appropriate_reviewer
),
}
actions['confirm_multiple_versions'] = {
'method': self.handler.confirm_multiple_versions,
'label': 'Confirm Multiple Versions',
'minimal': True,
'multiple_versions': True,
'details': (
'This will confirm approval of the selected '
'versions without notifying the developer.'
),
'comments': False,
'available': (
not is_static_theme and version_is_unlisted and is_appropriate_reviewer
),
'resolves_cinder_jobs': True,
}
actions['change_or_clear_pending_rejection_multiple_versions'] = {
'method': self.handler.change_or_clear_pending_rejection_multiple_versions,
'label': 'Change pending rejection',
'details': (
'Change or clear pending rejection from selected versions, '
"but otherwise don't change the version(s) or add-on "
'statuses. Developer will be notified of the new pending '
'rejection date unless the action clears it.'
),
'delayable': True,
'multiple_versions': True,
'minimal': True,
'comments': False,
'available': is_appropriate_admin_reviewer,
}
actions['clear_needs_human_review_multiple_versions'] = {
'method': self.handler.clear_needs_human_review_multiple_versions,
'label': 'Clear Needs Human Review',
'details': (
'Clear needs human review flag from selected versions, but '
"otherwise don't change the version(s) or add-on statuses."
),
'multiple_versions': True,
'minimal': True,
'comments': False,
'available': is_appropriate_admin_reviewer,
}
actions['set_needs_human_review_multiple_versions'] = {
'method': self.handler.set_needs_human_review_multiple_versions,
'label': 'Set Needs Human Review',
'details': (
'Set needs human review flag from selected versions, but '
"otherwise don't change the version(s) or add-on statuses."
),
'multiple_versions': True,
'minimal': True,
'available': addon_is_not_disabled and is_appropriate_reviewer,
}
actions['reply'] = {
'method': self.handler.reviewer_reply,
'label': 'Reviewer reply',
'details': (
'This will send a message to the developer, attached to the '
'selected version(s). You will be notified when they reply.'
),
'multiple_versions': True,
'minimal': True,
'available': (
self.version is not None
and is_reviewer
and (not any(promoted_group.admin_review) or is_appropriate_reviewer)
),
'allows_reasons': not is_static_theme,
'requires_reasons': False,
}
actions['request_admin_review'] = {
'method': self.handler.request_admin_review,
'label': 'Request review from admin',
'details': (
'If you have concerns about this add-on that '
'an admin reviewer should look into, enter '
'your comments in the area below. They will '
'not be sent to the developer.'
),
'minimal': True,
'available': (self.version is not None and is_reviewer and is_static_theme),
}
actions['clear_admin_review'] = {
'method': self.handler.clear_admin_review,
'label': 'Clear admin review',
'details': ('Clear needs admin review flag on the add-on.'),
'minimal': True,
'comments': False,
'available': is_appropriate_admin_reviewer and is_static_theme,
}
actions['enable_addon'] = {
'method': self.handler.enable_addon,
'label': 'Force enable',
'details': (
'This will force enable this add-on, and any versions previously '
'disabled with Force Disable. '
'The comments will be sent to the developer.'
),
'minimal': True,
'available': (
addon_is_not_deleted
and not addon_is_not_disabled
and is_appropriate_admin_reviewer
),
'resolves_cinder_jobs': True,
'can_attach': False,
}
actions['disable_addon'] = {
'method': self.handler.disable_addon,
'label': 'Force disable',
'details': (
'This will force disable this add-on, and all its versions. '
'The comments will be sent to the developer.'
),
'minimal': False,
'available': (
addon_is_not_disabled_or_deleted and is_appropriate_admin_reviewer
),
'allows_reasons': True,
'resolves_cinder_jobs': True,
'requires_reasons': not is_static_theme,
'requires_reasons_for_cinder_jobs': True,
'can_attach': False,
}
actions['resolve_reports_job'] = {
'method': self.handler.resolve_reports_job,
'label': 'Resolve Reports',
'details': (
'Allows abuse report jobs to be resolved without an action on the '
'add-on or versions.'
),
'minimal': True,
'available': is_reviewer and has_unresolved_abuse_report_jobs,
'comments': False,
'resolves_cinder_jobs': True,
'requires_policies': True,
}
actions['resolve_appeal_job'] = {
'method': self.handler.resolve_appeal_job,
'label': 'Resolve Appeals',
'details': (
'Allows abuse report jobs to be resolved without an action on the '
'add-on or versions.'
),
'minimal': True,
'available': is_reviewer and has_unresolved_appeal_jobs,
'resolves_cinder_jobs': True,
}
actions['request_legal_review'] = {
'method': self.handler.request_legal_review,
'label': 'Request review from Mozilla Legal',
'details': (
'If you have concerns about the legality of this add-on that requires '
"Mozilla's legal to investigate, enter your comments in the area "
'below. They will not be sent to the developer.'
'If it relates to an open abuse report job or appeal resolve then job.'
),
'minimal': True,
'available': is_appropriate_reviewer,
'resolves_cinder_jobs': True,
}
actions['comment'] = {
'method': self.handler.process_comment,
'label': 'Comment',
'details': (
"Make a comment on this version. The developer won't be able to see "
'this.'
),
'minimal': True,
'available': is_reviewer,
}
return OrderedDict(
((key, action) for key, action in actions.items() if action['available'])
)