addons-server/apps/reviews/views.py

214 строки
7.8 KiB
Python

from django import http
from django.shortcuts import get_object_or_404, redirect
import commonware.log
import jingo
from tower import ugettext as _
from amo import messages
import amo.utils
from amo.decorators import post_required, json_view, login_required
from access import acl
from addons.models import Addon
from .models import Review, ReviewFlag, GroupedRating, Spam
from . import forms
log = commonware.log.getLogger('z.reviews')
def flag_context():
return dict(ReviewFlag=ReviewFlag,
flag_form=forms.ReviewFlagForm())
def review_list(request, addon_id, review_id=None, user_id=None):
addon = get_object_or_404(Addon.objects.valid(), id=addon_id)
q = (Review.objects.valid().filter(addon=addon)
.order_by('-created'))
ctx = {'addon': addon,
'grouped_ratings': GroupedRating.get(addon_id)}
ctx.update(flag_context())
ctx['form'] = forms.ReviewForm(None)
if review_id is not None:
ctx['page'] = 'detail'
# If this is a dev reply, find the first msg for context.
review = get_object_or_404(Review.objects.all(), pk=review_id)
if review.reply_to_id:
review_id = review.reply_to_id
ctx['reply'] = review
q = q.filter(pk=review_id)
elif user_id is not None:
ctx['page'] = 'user'
q = q.filter(user=user_id)
if not q:
raise http.Http404()
else:
ctx['page'] = 'list'
q = q.filter(is_latest=True)
ctx['reviews'] = reviews = amo.utils.paginate(request, q)
ctx['replies'] = Review.get_replies(reviews.object_list)
if request.user.is_authenticated():
ctx['review_perms'] = {
'is_admin': acl.action_allowed(request, 'Admin', 'EditAnyAddon'),
'is_editor': acl.action_allowed(request, 'Editor', '%'),
'is_author': acl.check_ownership(request, addon,
require_owner=True),
'can_delete': acl.action_allowed(request, 'Editors',
'DeleteReview'),
}
ctx['flags'] = get_flags(request, reviews.object_list)
else:
ctx['review_perms'] = {}
return jingo.render(request, 'reviews/review_list.html', ctx)
def get_flags(request, reviews):
reviews = [r.id for r in reviews]
qs = ReviewFlag.objects.filter(review__in=reviews, user=request.user.id)
return dict((r.review_id, r) for r in qs)
@post_required
@login_required(redirect=False)
@json_view
def flag(request, addon_id, review_id):
d = dict(review=review_id, user=request.user.id)
try:
instance = ReviewFlag.objects.get(**d)
except ReviewFlag.DoesNotExist:
instance = None
data = dict(request.POST.items(), **d)
form = forms.ReviewFlagForm(data, instance=instance)
if form.is_valid():
form.save()
Review.objects.filter(id=review_id).update(editorreview=True)
return {'msg': _('Thanks; this review has been flagged '
'for editor approval.')}
else:
return json_view.error(unicode(form.errors))
@post_required
@login_required(redirect=False)
def delete(request, addon_id, review_id):
if not acl.action_allowed(request, 'Editors', 'DeleteReview'):
return http.HttpResponseForbidden()
review = get_object_or_404(Review.objects, pk=review_id, addon=addon_id)
review.delete()
log.info('DELETE: %s deleted %s by %s ("%s": "%s")' %
(request.amo_user.name, review_id,
review.user.name, review.title, review.body))
return http.HttpResponse()
def _review_details(request, addon, form):
version = addon.current_version and addon.current_version.id
d = dict(addon_id=addon.id, user_id=request.user.id,
version_id=version,
ip_address=request.META.get('REMOTE_ADDR', ''))
d.update(**form.cleaned_data)
return d
@login_required
def reply(request, addon_id, review_id):
addon = get_object_or_404(Addon.objects.valid(), id=addon_id)
is_admin = acl.action_allowed(request, 'Admin', 'EditAnyAddon')
is_author = acl.check_ownership(request, addon, require_owner=True)
if not (is_admin or is_author):
return http.HttpResponseForbidden()
review = get_object_or_404(Review.objects, pk=review_id, addon=addon_id)
form = forms.ReviewReplyForm(request.POST or None)
if request.method == 'POST':
if form.is_valid():
d = dict(reply_to=review, addon=addon,
defaults=dict(user=request.amo_user))
reply, new = Review.objects.get_or_create(**d)
for key, val in _review_details(request, addon, form).items():
setattr(reply, key, val)
reply.save()
action = 'New' if new else 'Edited'
log.debug('%s reply to %s: %s' % (action, review_id, reply.id))
return redirect('reviews.detail', addon_id, review_id)
ctx = dict(review=review, form=form, addon=addon)
ctx.update(flag_context())
return jingo.render(request, 'reviews/reply.html', ctx)
@login_required
def add(request, addon_id):
addon = get_object_or_404(Addon.objects.valid(), id=addon_id)
form = forms.ReviewForm(request.POST or None)
if request.method == 'POST':
if form.is_valid():
details = _review_details(request, addon, form)
review = Review.objects.create(**details)
log.debug('New review: %s' % review.id)
return redirect('reviews.list', addon_id)
return jingo.render(request, 'reviews/add.html',
dict(addon=addon, form=form))
@login_required(redirect=False)
@post_required
def edit(request, addon_id, review_id):
review = get_object_or_404(Review.objects, pk=review_id, addon=addon_id)
is_admin = acl.action_allowed(request, 'Admin', 'EditAnyAddon')
if not (request.user.id == review.user.id or is_admin):
return http.HttpResponseForbidden()
cls = forms.ReviewReplyForm if review.reply_to else forms.ReviewForm
form = cls(request.POST)
if form.is_valid():
for field in form.fields:
if field in form.cleaned_data:
setattr(review, field, form.cleaned_data[field])
review.save()
return http.HttpResponse()
else:
return json_view.error(form.errors)
@login_required
def spam(request):
if not acl.action_allowed(request, 'Admin', 'BattleSpam'):
return http.HttpResponseForbidden()
spam = Spam()
if request.method == 'POST':
review = Review.objects.get(pk=request.POST['review'])
if 'del_review' in request.POST:
log.info('SPAM: %s' % review.id)
delete(request, request.POST['addon'], review.id)
messages.success(request, 'Deleted that review.')
elif 'del_user' in request.POST:
user = review.user
log.info('SPAMMER: %s deleted %s' %
(request.amo_user.username, user.username))
if not user.is_developer:
Review.objects.filter(user=user).delete()
user.anonymize()
messages.success(request, 'Deleted that dirty spammer.')
for reason in spam.reasons():
spam.redis.srem(reason, review.id)
return redirect('reviews.spam')
buckets = {}
for reason in spam.reasons():
ids = spam.redis.smembers(reason)
key = reason.split(':')[-1]
buckets[key] = Review.objects.no_cache().filter(id__in=ids)
reviews = dict((review.addon_id, review) for bucket in buckets.values()
for review in bucket)
for addon in Addon.objects.no_cache().filter(id__in=reviews):
reviews[addon.id].addon = addon
return jingo.render(request, 'reviews/spam.html',
dict(buckets=buckets,
review_perms=dict(is_admin=True)))