add abuse report (bug 546830)
This commit is contained in:
Родитель
7906ad514f
Коммит
edb1ff2297
|
@ -1,6 +1,7 @@
|
|||
import re
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
|
||||
import happyforms
|
||||
|
||||
|
@ -91,3 +92,19 @@ class AddonForm(happyforms.ModelForm):
|
|||
'get_satisfaction_product',)
|
||||
|
||||
exclude = ('status', )
|
||||
|
||||
import captcha.fields
|
||||
|
||||
class AbuseForm(happyforms.Form):
|
||||
recaptcha = captcha.fields.ReCaptchaField(label='')
|
||||
text = forms.CharField(required=True,
|
||||
label=_('Please report abuse in the form below.'),
|
||||
widget=forms.Textarea())
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.request = kwargs.pop('request')
|
||||
super(AbuseForm, self).__init__(*args, **kwargs)
|
||||
|
||||
if (not self.request.user.is_anonymous() or
|
||||
not settings.RECAPTCHA_PRIVATE_KEY):
|
||||
del self.fields['recaptcha']
|
||||
|
|
|
@ -158,3 +158,9 @@ def persona_preview(context, persona, size='large', linked=True, extra=None,
|
|||
@jinja2.contextfunction
|
||||
def persona_grid(context, addons):
|
||||
return new_context(**locals())
|
||||
|
||||
|
||||
@register.inclusion_tag('addons/report_abuse.html')
|
||||
@jinja2.contextfunction
|
||||
def report_abuse(context, hide, addon):
|
||||
return new_context(**locals())
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
{# TODO(fwenzel): "add-on has been added to collection" notification #}
|
||||
|
||||
<div id="addon" class="primary" role="main" data-id="{{ addon.id }}">
|
||||
{% include "messages.html" %}
|
||||
<div class="featured">
|
||||
<div class="featured-inner object-lead inverse">
|
||||
|
||||
|
@ -197,6 +198,10 @@
|
|||
{{ version_detail(addon, version, src="addon-detail-version") }}
|
||||
{% endif %}
|
||||
|
||||
{% if abuse_form %}
|
||||
{{ report_abuse(hide=True, addon=addon) }}
|
||||
{% endif %}
|
||||
|
||||
</div>{# /primary #}
|
||||
|
||||
<div class="secondary" role="navigation">
|
||||
|
@ -325,4 +330,5 @@
|
|||
{# /collections #}
|
||||
|
||||
</div>{# /secondary #}
|
||||
|
||||
{% endblock content %}
|
||||
|
|
|
@ -116,6 +116,10 @@
|
|||
{{ review_add_box(addon=addon) }}
|
||||
{% endif %}
|
||||
|
||||
{% if abuse_form %}
|
||||
{{ report_abuse(hide=True, addon=addon) }}
|
||||
{% endif %}
|
||||
|
||||
</div>{# /primary #}
|
||||
|
||||
<div id="persona-side" class="secondary" role="navigation">
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<div id="addon" class="primary">
|
||||
<form method="post" action="{{ url('addons.abuse', addon.pk) }}">
|
||||
<fieldset class="abuse">
|
||||
{% if hide %}<legend><a href="#">{{ _('Report Abuse') }}</a></legend>{% endif %}
|
||||
<ol>
|
||||
<li>
|
||||
{{ csrf() }}
|
||||
{{ abuse_form.as_p()|safe }}
|
||||
</li>
|
||||
<li>
|
||||
<button type="submit">{{ _('Send Report') }}</button>
|
||||
{% if hide %}
|
||||
or <button type="reset" class="link">{{ _('Cancel') }}</button>
|
||||
{% endif %}
|
||||
</li>
|
||||
</ol>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
|
@ -0,0 +1,18 @@
|
|||
{% extends "base_side_categories.html" %}
|
||||
|
||||
{% set title = _('Report abuse for {0}')|f(addon.name) %}
|
||||
|
||||
{% block title %}{{ page_title(title) }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<header>
|
||||
{{ breadcrumbs([(addon.type_url(), amo.ADDON_TYPES[addon.type]),
|
||||
(addon.get_url_path(), addon.name),
|
||||
(None, _('Add Abuse'))]) }}
|
||||
<h2>{{ title }}</h2>
|
||||
</header>
|
||||
|
||||
{{ report_abuse(hide=False, addon=addon) }}
|
||||
|
||||
{% endblock %}
|
|
@ -7,10 +7,12 @@ from django.conf import settings
|
|||
from django.core.cache import cache
|
||||
from django.utils import translation
|
||||
from django.utils.encoding import iri_to_uri
|
||||
from django.core import mail
|
||||
|
||||
from nose.tools import eq_, set_trace
|
||||
from nose.tools import eq_
|
||||
import test_utils
|
||||
from pyquery import PyQuery as pq
|
||||
from mock import patch
|
||||
|
||||
import amo
|
||||
from amo.helpers import absolutify
|
||||
|
@ -28,6 +30,7 @@ def norm(s):
|
|||
"""Normalize a string so that whitespace is uniform."""
|
||||
return re.sub(r'[\s]+', ' ', str(s)).strip()
|
||||
|
||||
|
||||
class TestHomepage(test_utils.TestCase):
|
||||
fixtures = ['base/apps',
|
||||
'base/users',
|
||||
|
@ -801,3 +804,79 @@ class TestAddonSharing(test_utils.TestCase):
|
|||
assert iri_to_uri(addon.name) in r['Location']
|
||||
assert iri_to_uri(url) in r['Location']
|
||||
assert iri_to_uri(summary) in r['Location']
|
||||
|
||||
|
||||
class TestReportAbuse(test_utils.TestCase):
|
||||
fixtures = ['addons/persona',
|
||||
'base/apps',
|
||||
'base/addon_3615',
|
||||
'base/users']
|
||||
|
||||
@patch('captcha.fields.ReCaptchaField.clean')
|
||||
def test_abuse_anonymous(self, clean):
|
||||
clean.return_value = ""
|
||||
self.client.post(reverse('addons.abuse', args=[3615]),
|
||||
{'text': 'spammy'})
|
||||
eq_(len(mail.outbox), 1)
|
||||
assert 'spammy' in mail.outbox[0].body
|
||||
|
||||
def test_abuse_anonymous_fails(self):
|
||||
r = self.client.post(reverse('addons.abuse', args=[3615]),
|
||||
{'text': 'spammy'})
|
||||
assert 'recaptcha' in r.context['abuse_form'].errors
|
||||
|
||||
def test_abuse_logged_in(self):
|
||||
self.client.login(username='regular@mozilla.com', password='password')
|
||||
self.client.post(reverse('addons.abuse', args=[3615]),
|
||||
{'text': 'spammy'})
|
||||
eq_(len(mail.outbox), 1)
|
||||
assert 'spammy' in mail.outbox[0].body
|
||||
|
||||
def test_abuse_persona(self):
|
||||
r = self.client.get(reverse('addons.detail', args=[15663]))
|
||||
doc = pq(r.content)
|
||||
assert doc("fieldset.abuse")
|
||||
|
||||
# and now just test it works
|
||||
self.client.login(username='regular@mozilla.com', password='password')
|
||||
self.client.post(reverse('addons.abuse', args=[15663]),
|
||||
{'text': 'spammy'})
|
||||
eq_(len(mail.outbox), 1)
|
||||
assert 'spammy' in mail.outbox[0].body
|
||||
|
||||
|
||||
class TestReportAbuseDisabled(test_utils.TestCase):
|
||||
fixtures = ['addons/persona',
|
||||
'base/apps',
|
||||
'base/addon_3615',
|
||||
'base/users']
|
||||
|
||||
def setUp(self):
|
||||
settings.REPORT_ABUSE = False
|
||||
|
||||
def tearDown(self):
|
||||
settings.REPORT_ABUSE = True
|
||||
|
||||
def test_abuse_persona(self):
|
||||
r = self.client.get(reverse('addons.detail', args=[15663]))
|
||||
doc = pq(r.content)
|
||||
assert not doc("fieldset.abuse")
|
||||
|
||||
def test_abuse_fails_anonymous(self):
|
||||
r = self.client.get(reverse('addons.detail', args=[3615]))
|
||||
doc = pq(r.content)
|
||||
assert not doc("fieldset.abuse")
|
||||
|
||||
res = self.client.post(reverse('addons.abuse', args=[3615]),
|
||||
{'text': 'spammy'})
|
||||
eq_(res.status_code, 404)
|
||||
|
||||
def test_abuse_fails_logged_in(self):
|
||||
self.client.login(username='regular@mozilla.com', password='password')
|
||||
r = self.client.get(reverse('addons.detail', args=[3615]))
|
||||
doc = pq(r.content)
|
||||
assert not doc("fieldset.abuse")
|
||||
|
||||
res = self.client.post(reverse('addons.abuse', args=[3615]),
|
||||
{'text': 'spammy'})
|
||||
eq_(res.status_code, 404)
|
||||
|
|
|
@ -11,6 +11,7 @@ detail_patterns = patterns('',
|
|||
url('^eula/(?P<file_id>\d+)?$', views.eula, name='addons.eula'),
|
||||
url('^license/(?P<version>[^/]+)?', views.license, name='addons.license'),
|
||||
url('^privacy/', views.privacy, name='addons.privacy'),
|
||||
url('^abuse/', views.report_abuse, name='addons.abuse'),
|
||||
url('^share$', views.share, name='addons.share'),
|
||||
url('^developers$', views.developers,
|
||||
{'page': 'developers'}, name='addons.meet'),
|
||||
|
|
|
@ -10,11 +10,15 @@ from django.utils import http as urllib
|
|||
|
||||
import caching.base as caching
|
||||
import jingo
|
||||
import commonware.log
|
||||
|
||||
from tower import ugettext_lazy as _lazy
|
||||
from tower import ugettext as _
|
||||
|
||||
import amo
|
||||
from amo import messages
|
||||
from amo.utils import sorted_groupby, randslice
|
||||
from amo.utils import send_mail
|
||||
from amo.helpers import absolutify
|
||||
from amo import urlresolvers
|
||||
from amo.urlresolvers import reverse
|
||||
|
@ -28,6 +32,9 @@ from translations.query import order_by_translation
|
|||
from translations.helpers import truncate
|
||||
from versions.models import Version
|
||||
from .models import Addon
|
||||
from .forms import AbuseForm
|
||||
|
||||
log = commonware.log.getLogger('z.addons')
|
||||
|
||||
|
||||
def author_addon_clicked(f):
|
||||
|
@ -132,6 +139,9 @@ def extension_detail(request, addon):
|
|||
|
||||
'collections': collections.order_by('-subscribers')[:3],
|
||||
}
|
||||
if settings.REPORT_ABUSE:
|
||||
data['abuse_form'] = AbuseForm(request=request)
|
||||
|
||||
return jingo.render(request, 'addons/details.html', data)
|
||||
|
||||
|
||||
|
@ -177,6 +187,8 @@ def persona_detail(request, addon):
|
|||
'author_gallery': settings.PERSONAS_USER_ROOT % persona.author,
|
||||
'search_cat': 'personas',
|
||||
}
|
||||
if settings.REPORT_ABUSE:
|
||||
data['abuse_form'] = AbuseForm(request=request)
|
||||
|
||||
return jingo.render(request, 'addons/personas_detail.html', data)
|
||||
|
||||
|
@ -478,3 +490,32 @@ def license(request, addon_id, version=None):
|
|||
def license_redirect(request, version):
|
||||
version = get_object_or_404(Version, pk=version)
|
||||
return redirect(version.license_url(), permanent=True)
|
||||
|
||||
|
||||
def report_abuse(request, addon_id):
|
||||
if not settings.REPORT_ABUSE:
|
||||
raise http.Http404()
|
||||
|
||||
addon = get_object_or_404(Addon, pk=addon_id)
|
||||
form = AbuseForm(request.POST or None, request=request)
|
||||
if request.method == "POST" and form.is_valid():
|
||||
if request.user.is_anonymous():
|
||||
user_name = 'An anonymous user'
|
||||
else:
|
||||
user_name = '%s (%s)' % (request.amo_user.name,
|
||||
request.amo_user.email)
|
||||
|
||||
subject = 'Abuse Report for %s' % addon.name
|
||||
msg = u'%s reported abuse for %s (%s%s).\n\n%s'
|
||||
msg = msg % (user_name, addon.name, settings.SITE_URL,
|
||||
reverse('addons.detail', args=[addon.pk]),
|
||||
form.cleaned_data['text'])
|
||||
|
||||
messages.success(request, _('Abuse reported.'))
|
||||
log.debug('Abuse reported by %s for %s.' % (user_name, addon_id))
|
||||
send_mail(subject, msg, recipient_list=(settings.FLIGTAR,))
|
||||
|
||||
else:
|
||||
return jingo.render(request, 'addons/report_abuse_full.html',
|
||||
{'addon': addon, 'abuse_form': form, })
|
||||
return redirect(reverse('addons.detail', args=[addon.pk]))
|
||||
|
|
|
@ -1962,10 +1962,10 @@ form .error .note.error {
|
|||
font-weight: bold;
|
||||
}
|
||||
|
||||
.abuse legend span {
|
||||
.abuse legend a {
|
||||
padding-left: 25px;
|
||||
color: #05e;
|
||||
background: transparent url("../../img/amo2009/icons/icons.png") 0 -1700px no-repeat;
|
||||
background: transparent url("../../img/zamboni/notifications.png") 0 -305px no-repeat;
|
||||
}
|
||||
|
||||
.html-rtl .abuse legend span {
|
||||
|
|
|
@ -83,6 +83,18 @@ $(document).ready(function() {
|
|||
|
||||
var etiquette_box = $("#addons-display-review-etiquette").hide();
|
||||
$("#short-review").focus(function() { etiquette_box.show("fast"); } );
|
||||
|
||||
var abuse = $("fieldset.abuse");
|
||||
if (abuse.find("legend a").length) {
|
||||
abuse.find("ol").hide();
|
||||
abuse.find("legend a").click(function() {
|
||||
abuse.find("ol").slideToggle("fast");
|
||||
return false;
|
||||
});
|
||||
abuse.find("button[type=reset]").click(function() {
|
||||
abuse.find("ol").slideToggle("fast");
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/* get satisfaction initialization */
|
||||
|
|
|
@ -653,3 +653,6 @@ ASYNC_SIGNALS = True
|
|||
|
||||
# Performance notes on add-ons
|
||||
PERFORMANCE_NOTES = False
|
||||
|
||||
# flag to turn on or off Abuse reports
|
||||
REPORT_ABUSE = True
|
||||
|
|
Загрузка…
Ссылка в новой задаче