in src/olympia/abuse/views.py [0:0]
def appeal(request, *, abuse_report_id, decision_cinder_id, **kwargs):
appealable_decisions = tuple(DECISION_ACTIONS.APPEALABLE_BY_AUTHOR.values) + tuple(
DECISION_ACTIONS.APPEALABLE_BY_REPORTER.values
)
cinder_decision = get_object_or_404(
ContentDecision.objects.filter(action__in=appealable_decisions),
cinder_id=decision_cinder_id,
)
if abuse_report_id:
abuse_report = get_object_or_404(
AbuseReport.objects.filter(cinder_job__isnull=False),
id=abuse_report_id,
cinder_job=cinder_decision.cinder_job,
)
else:
abuse_report = None
# Reporter appeal: we need an abuse report.
if (
abuse_report is None
and cinder_decision.action in DECISION_ACTIONS.APPEALABLE_BY_REPORTER
):
raise Http404
target = cinder_decision.target
context_data = {
'decision_cinder_id': decision_cinder_id,
}
post_data = request.POST if request.method == 'POST' else None
valid_user_or_email_provided = False
appeal_email_form = None
if cinder_decision.action in DECISION_ACTIONS.APPEALABLE_BY_REPORTER or (
cinder_decision.action == DECISION_ACTIONS.AMO_BAN_USER
):
# Only person would should be appealing an approval is the reporter.
if (
cinder_decision.action in DECISION_ACTIONS.APPEALABLE_BY_REPORTER
and abuse_report
and abuse_report.reporter
):
# Authenticated reporter is the easy case, they should just be
# authenticated with the right account.
if not request.user.is_authenticated:
return redirect_for_login(request)
valid_user_or_email_provided = request.user == abuse_report.reporter
elif cinder_decision.action == DECISION_ACTIONS.AMO_BAN_USER or (
abuse_report and abuse_report.reporter_email
):
# Anonymous reporter appealing or banned user appealing is tricky,
# we need the email to be submitted via POST to match. If there was
# no POST, then we show a form for it instead of showing the appeal
# form. We do the same for ban appeals, since the user would no
# longer be able to log in.
expected_email = (
target.email
if cinder_decision.action == DECISION_ACTIONS.AMO_BAN_USER
else abuse_report.reporter_email
)
appeal_email_form = AbuseAppealEmailForm(
post_data, expected_email=expected_email, request=request
)
if appeal_email_form.is_bound and appeal_email_form.is_valid():
valid_user_or_email_provided = True
# We'll be re-using the form, but the user shouldn't change
# the email (that would prevent submission, it would no
# longer be valid), so make the input hidden.
appeal_email_form.fields['email'].widget = forms.HiddenInput()
context_data['appeal_email_form'] = appeal_email_form
else:
# Only person would should be appealing anything else than an approval
# is the author of the content.
if not request.user.is_authenticated:
return redirect_for_login(request)
allowed_users = []
if hasattr(target, 'authors'):
allowed_users = target.authors.all()
elif hasattr(target, 'author'):
allowed_users = [target.author]
elif hasattr(target, 'user'):
allowed_users = [target.user]
valid_user_or_email_provided = request.user in allowed_users
if not valid_user_or_email_provided and not appeal_email_form:
# At this point we should either have a valid user/email provided, or
# we are just showing the email form. Anything else should result in a
# 403.
raise PermissionDenied
if valid_user_or_email_provided:
# After this point, the user is either authenticated or has entered the
# right email address, we can start testing whether or not they can
# actually appeal, and show the form if they indeed can.
is_reporter = cinder_decision.action in DECISION_ACTIONS.APPEALABLE_BY_REPORTER
if cinder_decision.can_be_appealed(
is_reporter=is_reporter, abuse_report=abuse_report
):
appeal_form = AbuseAppealForm(post_data, request=request)
if appeal_form.is_bound and appeal_form.is_valid():
appeal_to_cinder.delay(
decision_cinder_id=cinder_decision.cinder_id,
abuse_report_id=abuse_report.id if abuse_report else None,
appeal_text=appeal_form.cleaned_data['reason'],
user_id=request.user.pk,
is_reporter=is_reporter,
)
context_data['appeal_processed'] = True
context_data['appeal_form'] = appeal_form
else:
# We can't appeal this, remove email form if it was there (which at
# this point should only contain the hidden email input) if the
# report can't be appealed. No form should be left on the page.
context_data.pop('appeal_email_form', None)
if hasattr(cinder_decision, 'overridden_by'):
# The reason we can't appeal this is that the decision has already been
# overriden by a new decision. We want a specific error message in this
# case.
context_data['appealed_decision_overridden'] = True
elif (
is_reporter
and not hasattr(abuse_report, 'cinderappeal')
and cinder_decision.appealed_decision_already_made()
):
# The reason we can't appeal this is that there was already an
# appeal made for which we have a decision. We want a specific
# error message in this case.
context_data['appealed_decision_already_made'] = True
context_data['appealed_decision_affirmed'] = (
cinder_decision.appeal_job.final_decision.action
== cinder_decision.action
)
return TemplateResponse(request, 'abuse/appeal.html', context=context_data)