def test_get_performance_since(self): self._give_points() ReviewerScore.award_moderation_points(self.user, self.app, 1) rs = list(ReviewerScore.objects.all()) rs[0].update(created=self.days_ago(50)) performance = ReviewerScore.get_performance_since(self.user, self.days_ago(30)) eq_(len(performance), 1)
def test_get_breakdown(self): self._give_points() ReviewerScore.award_moderation_points(self.user, self.app, 1) breakdown = ReviewerScore.get_breakdown(self.user) eq_(len(breakdown), 1) eq_(set([b.atype for b in breakdown]), set([amo.ADDON_WEBAPP]))
def moderatelog_detail(request, eventlog_id): log = get_object_or_404(ActivityLog.objects.editor_events(), pk=eventlog_id) review = None if len(log.arguments) > 1 and isinstance(log.arguments[1], Review): review = log.arguments[1] form = ModerateLogDetailForm(request.POST or None) is_admin = acl.action_allowed(request, 'ReviewerAdminTools', 'View') can_undelete = review and review.deleted and (is_admin or request.user.pk == log.user.pk) if (request.method == 'POST' and form.is_valid() and form.cleaned_data['action'] == 'undelete'): if not can_undelete: if not review: raise RuntimeError('Review doesn`t exist.') elif not review.deleted: raise RuntimeError('Review isn`t deleted.') else: raise PermissionDenied ReviewerScore.award_moderation_points(log.user, review.addon, review.id, undo=True) review.undelete() return redirect('reviewers.apps.moderatelog.detail', eventlog_id) data = context(request, log=log, form=form, review=review, can_undelete=can_undelete) return render(request, 'reviewers/moderatelog_detail.html', data)
def test_get_total(self): user2 = UserProfile.objects.get(email="*****@*****.**") self._give_points() self._give_points() self._give_points(user=user2) eq_(ReviewerScore.get_total(self.user), mkt.REVIEWED_SCORES[mkt.REVIEWED_WEBAPP_HOSTED] * 2) eq_(ReviewerScore.get_total(user2), mkt.REVIEWED_SCORES[mkt.REVIEWED_WEBAPP_HOSTED])
def moderatelog_detail(request, eventlog_id): log = get_object_or_404( ActivityLog.objects.editor_events(), pk=eventlog_id) review = None if len(log.arguments) > 1 and isinstance(log.arguments[1], Review): review = log.arguments[1] form = ModerateLogDetailForm(request.POST or None) is_admin = acl.action_allowed(request, 'ReviewerAdminTools', 'View') can_undelete = review and review.deleted and ( is_admin or request.user.pk == log.user.pk) if (request.method == 'POST' and form.is_valid() and form.cleaned_data['action'] == 'undelete'): if not can_undelete: if not review: raise RuntimeError('Review doesn`t exist.') elif not review.deleted: raise RuntimeError('Review isn`t deleted.') else: raise PermissionDenied ReviewerScore.award_moderation_points( log.user, review.addon, review.id, undo=True) review.undelete() return redirect('reviewers.apps.moderatelog.detail', eventlog_id) data = context(request, log=log, form=form, review=review, can_undelete=can_undelete) return render(request, 'reviewers/moderatelog_detail.html', data)
def test_get_performance_since(self): self._give_points() ReviewerScore.award_moderation_points(self.user, self.app, 1) rs = list(ReviewerScore.objects.all()) rs[0].update(created=self.days_ago(50)) performance = ReviewerScore.get_performance_since( self.user, self.days_ago(30)) eq_(len(performance), 1)
def test_get_total(self): user2 = UserProfile.objects.get(email='*****@*****.**') self._give_points() self._give_points() self._give_points(user=user2) eq_(ReviewerScore.get_total(self.user), mkt.REVIEWED_SCORES[mkt.REVIEWED_WEBAPP_HOSTED] * 2) eq_(ReviewerScore.get_total(user2), mkt.REVIEWED_SCORES[mkt.REVIEWED_WEBAPP_HOSTED])
def test_get_breakdown_since(self): self._give_points() ReviewerScore.award_moderation_points(self.user, self.app, 1) rs = list(ReviewerScore.objects.all()) rs[0].update(created=self.days_ago(50)) breakdown = ReviewerScore.get_breakdown_since(self.user, self.days_ago(30)) eq_(len(breakdown), 1) eq_([b.atype for b in breakdown], [rs[1].addon.type])
def reviewers_score_bar(context, types=None): user = context.get('user') return new_context(dict( request=context.get('request'), mkt=mkt, settings=settings, points=ReviewerScore.get_recent(user), total=ReviewerScore.get_total(user), **ReviewerScore.get_leaderboards(user, types=types)))
def reviewers_score_bar(context, types=None): user = context.get('user') return new_context( dict(request=context.get('request'), amo=amo, settings=settings, points=ReviewerScore.get_recent(user), total=ReviewerScore.get_total(user), **ReviewerScore.get_leaderboards(user, types=types)))
def reviewers_score_bar(context, types=None, addon_type=None): user = context.get("amo_user") return new_context( dict( request=context.get("request"), amo=amo, settings=settings, points=ReviewerScore.get_recent(user, addon_type=addon_type), total=ReviewerScore.get_total(user), **ReviewerScore.get_leaderboards(user, types=types, addon_type=addon_type) ) )
def test_get_leaderboards_last(self): users = [] for i in range(6): users.append(user_factory()) last_user = users.pop(len(users) - 1) for u in users: self._give_points(user=u) # Last user gets lower points by a moderation review. ReviewerScore.award_moderation_points(last_user, self.app, 1) leaders = ReviewerScore.get_leaderboards(last_user) eq_(leaders['user_rank'], 6) eq_(len(leaders['leader_top']), 3) eq_(len(leaders['leader_near']), 2)
def test_award_moderation_points(self): ReviewerScore.award_moderation_points(self.user, self.app, 1) score = ReviewerScore.objects.all()[0] eq_(score.score, mkt.REVIEWED_SCORES.get(mkt.REVIEWED_APP_REVIEW)) eq_(score.note_key, mkt.REVIEWED_APP_REVIEW) ReviewerScore.award_moderation_points(self.user, self.app, 1, undo=True) score = ReviewerScore.objects.all()[1] eq_(score.score, mkt.REVIEWED_SCORES.get(mkt.REVIEWED_APP_REVIEW_UNDO)) eq_(score.note_key, mkt.REVIEWED_APP_REVIEW_UNDO) # If we change the _UNDO score to be different this test will fail. eq_(ReviewerScore.get_total(self.user), 0)
def test_get_leaderboards_last(self): users = [] for i in range(6): users.append(UserProfile.objects.create(username='******' % i)) last_user = users.pop(len(users) - 1) for u in users: self._give_points(user=u) # Last user gets lower points by a moderation review. ReviewerScore.award_moderation_points(last_user, self.app, 1) leaders = ReviewerScore.get_leaderboards(last_user) eq_(leaders['user_rank'], 6) eq_(len(leaders['leader_top']), 3) eq_(len(leaders['leader_near']), 2)
def test_get_leaderboards_last(self): users = [] for i in range(6): users.append(user_factory()) last_user = users.pop(len(users) - 1) for u in users: self._give_points(user=u) # Last user gets lower points by a moderation review. ReviewerScore.award_moderation_points(last_user, self.app, 1) leaders = ReviewerScore.get_leaderboards(last_user) eq_(leaders["user_rank"], 6) eq_(len(leaders["leader_top"]), 3) eq_(len(leaders["leader_near"]), 2)
def test_award_moderation_points(self): ReviewerScore.award_moderation_points(self.user, self.app, 1) score = ReviewerScore.objects.all()[0] eq_(score.score, mkt.REVIEWED_SCORES.get(mkt.REVIEWED_APP_REVIEW)) eq_(score.note_key, mkt.REVIEWED_APP_REVIEW) ReviewerScore.award_moderation_points(self.user, self.app, 1, undo=True) score = ReviewerScore.objects.all()[1] eq_(score.score, mkt.REVIEWED_SCORES.get(mkt.REVIEWED_APP_REVIEW_UNDO)) eq_(score.note_key, mkt.REVIEWED_APP_REVIEW_UNDO) # If we change the _UNDO score to be different this test will fail. eq_(ReviewerScore.get_total(self.user), 0)
def save(self): for form in self.forms: if form.cleaned_data: action = int(form.cleaned_data['action']) if action == ABUSE_REPORT_SKIP: continue inst = form.instance app = None site = None user = None texts = [] for report in inst.abuse_reports.all().filter(read=False): report.read = True report.save() app = report.addon site = report.website user = report.user if report.message: texts.append(report.message) if app: mkt.log(mkt.LOG.APP_ABUSE_MARKREAD, app, report, details=dict(body=unicode(report.message), addon_id=app.id, addon_title=unicode(app.name))) elif user: # Not possible on Marketplace currently. pass elif site: mkt.log(mkt.LOG.WEBSITE_ABUSE_MARKREAD, site, report, details=dict(body=unicode(report.message), website_id=site.id, website_title=unicode(site.name))) if app or site: ReviewerScore.award_mark_abuse_points(self.request.user, addon=app, website=site) if app and action == ABUSE_REPORT_FLAG: message = _('Abuse reports needing investigation: %s' % (', '.join(texts))) RereviewQueue.flag(app, mkt.LOG.REREVIEW_ABUSE_APP, message=message)
def process_reject(self): """ Reject an app. Changes status to Rejected. Creates Rejection note. """ # Hold onto the status before we change it. status = self.addon.status self.set_files(mkt.STATUS_DISABLED, self.version.files.all(), hide_disabled_file=True) # If this app is not packaged (packaged apps can have multiple # versions) or if there aren't other versions with already reviewed # files, reject the app also. if (not self.addon.is_packaged or not self.addon.versions.exclude(id=self.version.id) .filter(files__status__in=mkt.REVIEWED_STATUSES).exists()): self.set_addon(status=mkt.STATUS_REJECTED) if self.in_escalate: EscalationQueue.objects.filter(addon=self.addon).delete() if self.in_rereview: RereviewQueue.objects.filter(addon=self.addon).delete() self.create_note(mkt.LOG.REJECT_VERSION) log.info(u'Making %s disabled' % self.addon) # Assign reviewer incentive scores. return ReviewerScore.award_points(self.request.user, self.addon, status, in_rereview=self.in_rereview)
def process_public(self): """ Makes an app public or approved. Changes status to Public/Public Waiting. Creates Approval note/email. """ if self.addon.has_incomplete_status(): # Failsafe. return # Hold onto the status before we change it. status = self.addon.status if self.addon.make_public == amo.PUBLIC_IMMEDIATELY: self._process_public_immediately() else: self._process_approved() if self.in_escalate: EscalationQueue.objects.filter(addon=self.addon).delete() # Clear priority_review flag on approval - its not persistant. if self.addon.priority_review: self.addon.update(priority_review=False) # Assign reviewer incentive scores. return ReviewerScore.award_points(self.request.amo_user, self.addon, status)
def process_reject(self): """ Reject an app. Changes status to Rejected. Creates Rejection note. """ # Hold onto the status before we change it. status = self.addon.status self.set_files(mkt.STATUS_DISABLED, self.version.files.all(), hide_disabled_file=True) # If this app is not packaged (packaged apps can have multiple # versions) or if there aren't other versions with already reviewed # files, reject the app also. if (not self.addon.is_packaged or not self.addon.versions.exclude(id=self.version.id).filter( files__status__in=mkt.REVIEWED_STATUSES).exists()): self.set_addon(status=mkt.STATUS_REJECTED) if self.in_escalate: EscalationQueue.objects.filter(addon=self.addon).delete() if self.in_rereview: RereviewQueue.objects.filter(addon=self.addon).delete() self.create_note(mkt.LOG.REJECT_VERSION) log.info(u'Making %s disabled' % self.addon) # Assign reviewer incentive scores. return ReviewerScore.award_points(self.request.user, self.addon, status, in_rereview=self.in_rereview)
def save(self): for form in self.forms: if form.cleaned_data and user_can_delete_review(self.request, form.instance): action = int(form.cleaned_data["action"]) is_flagged = form.instance.reviewflag_set.count() > 0 if action != REVIEW_MODERATE_SKIP: # Delete flags. for flag in form.instance.reviewflag_set.all(): flag.delete() review = form.instance webapp = review.webapp if action == REVIEW_MODERATE_DELETE: review.delete() mkt.log( mkt.LOG.DELETE_REVIEW, webapp, review, details=dict( title=unicode(review.title), body=unicode(review.body), webapp_id=webapp.id, webapp_title=unicode(webapp.name), is_flagged=is_flagged, ), ) if self.request: ReviewerScore.award_moderation_points(self.request.user, webapp, review.id) elif action == REVIEW_MODERATE_KEEP: review.editorreview = False review.save() mkt.log( mkt.LOG.APPROVE_REVIEW, webapp, review, details=dict( title=unicode(review.title), body=unicode(review.body), webapp_id=webapp.id, webapp_title=unicode(webapp.name), is_flagged=is_flagged, ), ) if self.request: ReviewerScore.award_moderation_points(self.request.user, webapp, review.id)
def save(self): for form in self.forms: if form.cleaned_data: action = int(form.cleaned_data['action']) if action == ABUSE_REPORT_SKIP: continue inst = form.instance app = None site = None user = None texts = [] for report in inst.abuse_reports.all().filter(read=False): report.read = True report.save() app = report.addon site = report.website user = report.user if report.message: texts.append(report.message) if app: mkt.log(mkt.LOG.APP_ABUSE_MARKREAD, app, report, details=dict( body=unicode(report.message), addon_id=app.id, addon_title=unicode(app.name) )) elif user: # Not possible on Marketplace currently. pass elif site: mkt.log(mkt.LOG.WEBSITE_ABUSE_MARKREAD, site, report, details=dict( body=unicode(report.message), website_id=site.id, website_title=unicode(site.name) )) if app or site: ReviewerScore.award_mark_abuse_points( self.request.user, addon=app, website=site) if app and action == ABUSE_REPORT_FLAG: message = _('Abuse reports needing investigation: %s' % (', '.join(texts))) RereviewQueue.flag( app, mkt.LOG.REREVIEW_ABUSE_APP, message=message)
def performance(request, username=None): is_admin = acl.action_allowed(request, 'Admin', '%') if username: if username == request.amo_user.username: user = request.amo_user elif is_admin: user = get_object_or_404(UserProfile, username=username) else: raise http.Http404 else: user = request.amo_user today = datetime.date.today() month_ago = today - datetime.timedelta(days=30) year_ago = today - datetime.timedelta(days=365) total = ReviewerScore.get_total(user) totals = ReviewerScore.get_breakdown(user) months = ReviewerScore.get_breakdown_since(user, month_ago) years = ReviewerScore.get_breakdown_since(user, year_ago) def _sum(iter, types): return sum(s.total for s in iter if s.atype in types) breakdown = { 'month': { 'addons': _sum(months, amo.GROUP_TYPE_ADDON), 'apps': _sum(months, amo.GROUP_TYPE_WEBAPP), }, 'year': { 'addons': _sum(years, amo.GROUP_TYPE_ADDON), 'apps': _sum(years, amo.GROUP_TYPE_WEBAPP), }, 'total': { 'addons': _sum(totals, amo.GROUP_TYPE_ADDON), 'apps': _sum(totals, amo.GROUP_TYPE_WEBAPP), } } ctx = context(request, **{ 'profile': user, 'total': total, 'breakdown': breakdown, }) return render(request, 'reviewers/performance.html', ctx)
def save(self): for form in self.forms: if form.cleaned_data and user_can_delete_review( self.request, form.instance): action = int(form.cleaned_data['action']) is_flagged = (form.instance.reviewflag_set.count() > 0) if action != REVIEW_MODERATE_SKIP: # Delete flags. for flag in form.instance.reviewflag_set.all(): flag.delete() review = form.instance addon = review.addon if action == REVIEW_MODERATE_DELETE: review_addon = review.addon review_id = review.id review.delete() amo.log(amo.LOG.DELETE_REVIEW, review_addon, review_id, details=dict(title=unicode(review.title), body=unicode(review.body), addon_id=addon.id, addon_title=unicode(addon.name), is_flagged=is_flagged)) if self.request: ReviewerScore.award_moderation_points( self.request.user, addon, review_id) elif action == REVIEW_MODERATE_KEEP: review.editorreview = False review.save() amo.log(amo.LOG.APPROVE_REVIEW, review.addon, review, details=dict(title=unicode(review.title), body=unicode(review.body), addon_id=addon.id, addon_title=unicode(addon.name), is_flagged=is_flagged)) if self.request: ReviewerScore.award_moderation_points( self.request.user, addon, review.id)
def test_get_recent(self): user2 = UserProfile.objects.get(email='*****@*****.**') self._give_points() time.sleep(1) # Wait 1 sec so ordering by created is checked. self._give_points() self._give_points(user=user2) scores = ReviewerScore.get_recent(self.user) eq_(len(scores), 2) eq_(scores[0].score, amo.REVIEWED_SCORES[amo.REVIEWED_WEBAPP_HOSTED]) eq_(scores[1].score, amo.REVIEWED_SCORES[amo.REVIEWED_WEBAPP_HOSTED])
def test_get_recent(self): user2 = UserProfile.objects.get(email='*****@*****.**') self._give_points() time.sleep(1) # Wait 1 sec so ordering by created is checked. self._give_points() self._give_points(user=user2) scores = ReviewerScore.get_recent(self.user) eq_(len(scores), 2) eq_(scores[0].score, mkt.REVIEWED_SCORES[mkt.REVIEWED_WEBAPP_HOSTED]) eq_(scores[1].score, mkt.REVIEWED_SCORES[mkt.REVIEWED_WEBAPP_HOSTED])
def test_no_admins_or_staff_in_leaderboards(self): user2 = UserProfile.objects.get(email='*****@*****.**') self._give_points() self._give_points(user=user2) leaders = ReviewerScore.get_leaderboards(self.user) eq_(leaders['user_rank'], 1) eq_(leaders['leader_near'], []) eq_(leaders['leader_top'][0]['user_id'], self.user.id) eq_(len(leaders['leader_top']), 1) # Only the editor is here. assert user2.id not in [l['user_id'] for l in leaders['leader_top']], ( 'Unexpected admin user found in leaderboards.')
def process_clear_rereview(self): """ Clear app from re-review queue. Doesn't change status. Creates Reviewer-only note. """ RereviewQueue.objects.filter(addon=self.addon).delete() self.create_note(mkt.LOG.REREVIEW_CLEARED) log.info(u"Re-review cleared for app: %s" % self.addon) # Assign reviewer incentive scores. return ReviewerScore.award_points(self.request.user, self.addon, self.addon.status, in_rereview=True)
def test_no_admins_or_staff_in_leaderboards(self): user2 = UserProfile.objects.get(email='*****@*****.**') self._give_points() self._give_points(user=user2) leaders = ReviewerScore.get_leaderboards(self.user) eq_(leaders['user_rank'], 1) eq_(leaders['leader_near'], []) eq_(leaders['leader_top'][0]['user_id'], self.user.id) eq_(len(leaders['leader_top']), 1) # Only the editor is here. assert user2.id not in [l['user_id'] for l in leaders['leader_top']], ( 'Unexpected admin user found in leaderboards.')
def process_clear_rereview(self): """ Clear app from re-review queue. Doesn't change status. Doesn't create note/email. """ RereviewQueue.objects.filter(addon=self.addon).delete() self.create_note(amo.LOG.REREVIEW_CLEARED) log.info(u'Re-review cleared for app: %s' % self.addon) # Assign reviewer incentive scores. return ReviewerScore.award_points(self.request.user, self.addon, self.addon.status, in_rereview=True)
def save(self): for form in self.forms: if form.cleaned_data and user_can_delete_review(self.request, form.instance): action = int(form.cleaned_data['action']) is_flagged = (form.instance.reviewflag_set.count() > 0) if action != REVIEW_MODERATE_SKIP: # Delete flags. for flag in form.instance.reviewflag_set.all(): flag.delete() review = form.instance addon = review.addon if action == REVIEW_MODERATE_DELETE: review_addon = review.addon review_id = review.id review.delete() amo.log(amo.LOG.DELETE_REVIEW, review_addon, review_id, details=dict(title=unicode(review.title), body=unicode(review.body), addon_id=addon.id, addon_title=unicode(addon.name), is_flagged=is_flagged)) if self.request: ReviewerScore.award_moderation_points( self.request.user, addon, review_id) elif action == REVIEW_MODERATE_KEEP: review.editorreview = False review.save() amo.log(amo.LOG.APPROVE_REVIEW, review.addon, review, details=dict(title=unicode(review.title), body=unicode(review.body), addon_id=addon.id, addon_title=unicode(addon.name), is_flagged=is_flagged)) if self.request: ReviewerScore.award_moderation_points( self.request.user, addon, review.id)
def performance(request, username=None): is_admin = acl.action_allowed(request, 'Admin', '%') if username: if username == request.user.username: user = request.user elif is_admin: user = get_object_or_404(UserProfile, username=username) else: raise http.Http404 else: user = request.user today = datetime.date.today() month_ago = today - datetime.timedelta(days=30) year_ago = today - datetime.timedelta(days=365) total = ReviewerScore.get_total(user) totals = ReviewerScore.get_performance(user) months = ReviewerScore.get_performance_since(user, month_ago) years = ReviewerScore.get_performance_since(user, year_ago) def _sum(iter): return sum(s.total or 0 for s in iter) performance = { 'month': _sum(months), 'year': _sum(years), 'total': _sum(totals), } ctx = context( request, **{ 'profile': user, 'total': total, 'performance': performance, }) return render(request, 'reviewers/performance.html', ctx)
def performance(request, email=None): is_admin = acl.action_allowed(request, 'Admin', '%') if email: if email == request.user.email: user = request.user elif is_admin: user = get_object_or_404(UserProfile, email=email) else: raise http.Http404 else: user = request.user today = datetime.date.today() month_ago = today - datetime.timedelta(days=30) year_ago = today - datetime.timedelta(days=365) total = ReviewerScore.get_total(user) totals = ReviewerScore.get_performance(user) months = ReviewerScore.get_performance_since(user, month_ago) years = ReviewerScore.get_performance_since(user, year_ago) def _sum(iter): return sum(s.total or 0 for s in iter) performance = { 'month': _sum(months), 'year': _sum(years), 'total': _sum(totals), } ctx = context(request, **{ 'profile': user, 'total': total, 'performance': performance, }) return render(request, 'reviewers/performance.html', ctx)
def test_all_users_by_score(self): user2 = UserProfile.objects.get(email='*****@*****.**') mkt.REVIEWED_LEVELS[0]['points'] = 120 self._give_points() self._give_points() self._give_points(user=user2) users = ReviewerScore.all_users_by_score() eq_(len(users), 2) # First user. eq_(users[0]['total'], 120) eq_(users[0]['user_id'], self.user.id) eq_(users[0]['level'], mkt.REVIEWED_LEVELS[0]['name']) # Second user. eq_(users[1]['total'], 60) eq_(users[1]['user_id'], user2.id) eq_(users[1]['level'], '')
def test_all_users_by_score(self): user2 = UserProfile.objects.get(email="*****@*****.**") mkt.REVIEWED_LEVELS[0]["points"] = 120 self._give_points() self._give_points() self._give_points(user=user2) users = ReviewerScore.all_users_by_score() eq_(len(users), 2) # First user. eq_(users[0]["total"], 120) eq_(users[0]["user_id"], self.user.id) eq_(users[0]["level"], mkt.REVIEWED_LEVELS[0]["name"]) # Second user. eq_(users[1]["total"], 60) eq_(users[1]["user_id"], user2.id) eq_(users[1]["level"], "")
def test_all_users_by_score(self): user2 = UserProfile.objects.get(email='*****@*****.**') amo.REVIEWED_LEVELS[0]['points'] = 120 self._give_points() self._give_points() self._give_points(user=user2) users = ReviewerScore.all_users_by_score() eq_(len(users), 2) # First user. eq_(users[0]['total'], 120) eq_(users[0]['user_id'], self.user.id) eq_(users[0]['level'], amo.REVIEWED_LEVELS[0]['name']) # Second user. eq_(users[1]['total'], 60) eq_(users[1]['user_id'], user2.id) eq_(users[1]['level'], '')
def test_get_leaderboards(self): user2 = UserProfile.objects.get(email='*****@*****.**') self._give_points() self._give_points() self._give_points(user=user2) leaders = ReviewerScore.get_leaderboards(self.user) eq_(leaders['user_rank'], 1) eq_(leaders['leader_near'], []) eq_(leaders['leader_top'][0]['rank'], 1) eq_(leaders['leader_top'][0]['user_id'], self.user.id) eq_(leaders['leader_top'][0]['total'], amo.REVIEWED_SCORES[amo.REVIEWED_WEBAPP_HOSTED] + amo.REVIEWED_SCORES[amo.REVIEWED_WEBAPP_HOSTED]) eq_(leaders['leader_top'][1]['rank'], 2) eq_(leaders['leader_top'][1]['user_id'], user2.id) eq_(leaders['leader_top'][1]['total'], amo.REVIEWED_SCORES[amo.REVIEWED_WEBAPP_HOSTED])
def test_get_leaderboards(self): user2 = UserProfile.objects.get(email="*****@*****.**") self._give_points() self._give_points() self._give_points(user=user2) leaders = ReviewerScore.get_leaderboards(self.user) eq_(leaders["user_rank"], 1) eq_(leaders["leader_near"], []) eq_(leaders["leader_top"][0]["rank"], 1) eq_(leaders["leader_top"][0]["user_id"], self.user.id) eq_( leaders["leader_top"][0]["total"], mkt.REVIEWED_SCORES[mkt.REVIEWED_WEBAPP_HOSTED] + mkt.REVIEWED_SCORES[mkt.REVIEWED_WEBAPP_HOSTED], ) eq_(leaders["leader_top"][1]["rank"], 2) eq_(leaders["leader_top"][1]["user_id"], user2.id) eq_(leaders["leader_top"][1]["total"], mkt.REVIEWED_SCORES[mkt.REVIEWED_WEBAPP_HOSTED])
def test_get_leaderboards(self): user2 = UserProfile.objects.get(email='*****@*****.**') self._give_points() self._give_points() self._give_points(user=user2) leaders = ReviewerScore.get_leaderboards(self.user) eq_(leaders['user_rank'], 1) eq_(leaders['leader_near'], []) eq_(leaders['leader_top'][0]['rank'], 1) eq_(leaders['leader_top'][0]['user_id'], self.user.id) eq_(leaders['leader_top'][0]['total'], amo.REVIEWED_SCORES[amo.REVIEWED_WEBAPP_HOSTED] + amo.REVIEWED_SCORES[amo.REVIEWED_WEBAPP_HOSTED]) eq_(leaders['leader_top'][1]['rank'], 2) eq_(leaders['leader_top'][1]['user_id'], user2.id) eq_(leaders['leader_top'][1]['total'], amo.REVIEWED_SCORES[amo.REVIEWED_WEBAPP_HOSTED])
def process_approve(self): """ Handle the approval of apps and/or files. """ if self.addon.has_incomplete_status(): # Failsafe. return # Hold onto the status before we change it. status = self.addon.status if self.addon.publish_type == mkt.PUBLISH_IMMEDIATE: self._process_public(mkt.STATUS_PUBLIC) elif self.addon.publish_type == mkt.PUBLISH_HIDDEN: self._process_public(mkt.STATUS_UNLISTED) else: self._process_private() # Note: Post save signals shouldn't happen here. All the set_*() # methods pass _signal=False to prevent them from being sent. They are # manually triggered in the view after the transaction is committed to # avoid multiple indexing tasks getting fired with stale data. # # This does mean that we need to call update_version() manually to get # the addon in the correct state before updating names. We do that, # passing _signal=False again to prevent it from sending # 'version_changed'. The post_save() that happen in the view will # call it without that parameter, sending 'version_changed' normally. self.addon.update_version(_signal=False) if self.addon.is_packaged: self.addon.update_name_from_package_manifest() self.addon.update_supported_locales() self.addon.resend_version_changed_signal = True if self.in_escalate: EscalationQueue.objects.filter(addon=self.addon).delete() # Clear priority_review flag on approval - its not persistant. if self.addon.priority_review: self.addon.update(priority_review=False) # Assign reviewer incentive scores. return ReviewerScore.award_points(self.request.user, self.addon, status)
def process_approve(self): """ Handle the approval of apps and/or files. """ if self.addon.has_incomplete_status(): # Failsafe. return # Hold onto the status before we change it. status = self.addon.status if self.addon.publish_type == mkt.PUBLISH_IMMEDIATE: self._process_public(mkt.STATUS_PUBLIC) elif self.addon.publish_type == mkt.PUBLISH_HIDDEN: self._process_public(mkt.STATUS_UNLISTED) else: self._process_private() # Note: Post save signals shouldn't happen here. All the set_*() # methods pass _signal=False to prevent them from being sent. They are # manually triggered in the view after the transaction is committed to # avoid multiple indexing tasks getting fired with stale data. # # This does mean that we need to call update_version() manually to get # the addon in the correct state before updating names. We do that, # passing _signal=False again to prevent it from sending # 'version_changed'. The post_save() that happen in the view will # call it without that parameter, sending 'version_changed' normally. self.addon.update_version(_signal=False) if self.addon.is_packaged: self.addon.update_name_from_package_manifest() self.addon.update_supported_locales() self.addon.resend_version_changed_signal = True if self.in_escalate: EscalationQueue.objects.filter(addon=self.addon).delete() # Clear priority_review flag on approval - its not persistant. if self.addon.priority_review: self.addon.update(priority_review=False) # Assign reviewer incentive scores. return ReviewerScore.award_points(self.request.user, self.addon, status)
def test_award_mark_abuse_points_website(self): ReviewerScore.award_mark_abuse_points(self.user, website=self.website) score = ReviewerScore.objects.all()[0] eq_(score.score, mkt.REVIEWED_SCORES.get(mkt.REVIEWED_WEBSITE_ABUSE_REPORT)) eq_(score.note_key, mkt.REVIEWED_WEBSITE_ABUSE_REPORT)
def check_event(self, status, event, **kwargs): eq_(ReviewerScore.get_event(self.app, status, **kwargs), event, ('Score event status:%s was not %s' % (status, event)))
def _give_points(self, user=None, app=None, status=None): user = user or self.user app = app or self.app ReviewerScore.award_points(user, app, status or app.status)
def test_award_moderation_points(self): ReviewerScore.award_moderation_points(self.user, self.app, 1) score = ReviewerScore.objects.all()[0] eq_(score.score, amo.REVIEWED_SCORES.get(amo.REVIEWED_APP_REVIEW)) eq_(score.note_key, amo.REVIEWED_APP_REVIEW)
def check_event(self, type, status, event, **kwargs): self.app.type = type eq_(ReviewerScore.get_event(self.app, status, **kwargs), event, ( 'Score event for type:%s and status:%s was not %s' % ( type, status, event)))
def _give_points(self, user=None, app=None, status=None): user = user or self.user app = app or self.app ReviewerScore.award_points(user, app, status or app.status)
def test_caching(self): self._give_points() with self.assertNumQueries(1): ReviewerScore.get_total(self.user) with self.assertNumQueries(0): ReviewerScore.get_total(self.user) with self.assertNumQueries(1): ReviewerScore.get_recent(self.user) with self.assertNumQueries(0): ReviewerScore.get_recent(self.user) with self.assertNumQueries(1): ReviewerScore.get_leaderboards(self.user) with self.assertNumQueries(0): ReviewerScore.get_leaderboards(self.user) with self.assertNumQueries(1): ReviewerScore.get_breakdown(self.user) with self.assertNumQueries(0): ReviewerScore.get_breakdown(self.user) # New points invalidates all caches. self._give_points() with self.assertNumQueries(1): ReviewerScore.get_total(self.user) with self.assertNumQueries(1): ReviewerScore.get_recent(self.user) with self.assertNumQueries(1): ReviewerScore.get_leaderboards(self.user) with self.assertNumQueries(1): ReviewerScore.get_breakdown(self.user)
def test_caching(self): self._give_points() with self.assertNumQueries(1): ReviewerScore.get_total(self.user) with self.assertNumQueries(0): ReviewerScore.get_total(self.user) with self.assertNumQueries(1): ReviewerScore.get_recent(self.user) with self.assertNumQueries(0): ReviewerScore.get_recent(self.user) with self.assertNumQueries(1): ReviewerScore.get_leaderboards(self.user) with self.assertNumQueries(0): ReviewerScore.get_leaderboards(self.user) with self.assertNumQueries(1): ReviewerScore.get_performance(self.user) with self.assertNumQueries(0): ReviewerScore.get_performance(self.user) # New points invalidates all caches. self._give_points() with self.assertNumQueries(1): ReviewerScore.get_total(self.user) with self.assertNumQueries(1): ReviewerScore.get_recent(self.user) with self.assertNumQueries(1): ReviewerScore.get_leaderboards(self.user) with self.assertNumQueries(1): ReviewerScore.get_performance(self.user)
def test_award_moderation_points(self): ReviewerScore.award_moderation_points(self.user, self.app, 1) score = ReviewerScore.objects.all()[0] eq_(score.score, amo.REVIEWED_SCORES.get(amo.REVIEWED_APP_REVIEW)) eq_(score.note_key, amo.REVIEWED_APP_REVIEW)
def test_get_performance(self): self._give_points() ReviewerScore.award_moderation_points(self.user, self.app, 1) performance = ReviewerScore.get_performance(self.user) eq_(len(performance), 1)
def test_award_additional_review_points(self): ReviewerScore.award_additional_review_points(self.user, self.app, QUEUE_TARAKO) score = ReviewerScore.objects.all()[0] eq_(score.score, mkt.REVIEWED_SCORES.get(mkt.REVIEWED_WEBAPP_TARAKO)) eq_(score.note_key, mkt.REVIEWED_WEBAPP_TARAKO)
def test_award_mark_abuse_points_app(self): ReviewerScore.award_mark_abuse_points(self.user, addon=self.app) score = ReviewerScore.objects.all()[0] eq_(score.score, mkt.REVIEWED_SCORES.get(mkt.REVIEWED_APP_ABUSE_REPORT)) eq_(score.note_key, mkt.REVIEWED_APP_ABUSE_REPORT)
def test_award_additional_review_points(self): ReviewerScore.award_additional_review_points(self.user, self.app, QUEUE_TARAKO) score = ReviewerScore.objects.all()[0] eq_(score.score, mkt.REVIEWED_SCORES.get(mkt.REVIEWED_WEBAPP_TARAKO)) eq_(score.note_key, mkt.REVIEWED_WEBAPP_TARAKO)
def leaderboard(request): return render( request, 'reviewers/leaderboard.html', context(request, **{'scores': ReviewerScore.all_users_by_score()}))
def _review(request, addon, version): if (not settings.ALLOW_SELF_REVIEWS and not acl.action_allowed(request, 'Admin', '%') and addon.has_author(request.user)): messages.warning(request, _('Self-reviews are not allowed.')) return redirect(reverse('reviewers.home')) if (addon.status == amo.STATUS_BLOCKED and not acl.action_allowed(request, 'Apps', 'ReviewEscalated')): messages.warning( request, _('Only senior reviewers can review blocklisted apps.')) return redirect(reverse('reviewers.home')) attachment_formset = CommAttachmentFormSet(data=request.POST or None, files=request.FILES or None, prefix='attachment') form = forms.get_review_form(data=request.POST or None, files=request.FILES or None, request=request, addon=addon, version=version, attachment_formset=attachment_formset) postdata = request.POST if request.method == 'POST' else None all_forms = [form, attachment_formset] if version: features_list = [unicode(f) for f in version.features.to_list()] appfeatures_form = AppFeaturesForm(data=postdata, instance=version.features) all_forms.append(appfeatures_form) else: appfeatures_form = None features_list = None queue_type = form.helper.review_type redirect_url = reverse('reviewers.apps.queue_%s' % queue_type) is_admin = acl.action_allowed(request, 'Apps', 'Edit') if request.method == 'POST' and all(f.is_valid() for f in all_forms): old_types = set(o.id for o in addon.device_types) new_types = set(form.cleaned_data.get('device_override')) old_features = set(features_list) new_features = set( unicode(f) for f in appfeatures_form.instance.to_list()) if form.cleaned_data.get('action') == 'public': if old_types != new_types: # The reviewer overrode the device types. We need to not # publish this app immediately. if addon.publish_type == amo.PUBLISH_IMMEDIATE: addon.update(publish_type=amo.PUBLISH_PRIVATE) # And update the device types to what the reviewer set. AddonDeviceType.objects.filter(addon=addon).delete() for device in form.cleaned_data.get('device_override'): addon.addondevicetype_set.create(device_type=device) # Log that the reviewer changed the device types. added_devices = new_types - old_types removed_devices = old_types - new_types msg = _( u'Device(s) changed by ' u'reviewer: {0}' ).format(', '.join([ _(u'Added {0}').format(unicode(amo.DEVICE_TYPES[d].name)) for d in added_devices ] + [ _(u'Removed {0}').format(unicode(amo.DEVICE_TYPES[d].name)) for d in removed_devices ])) log_reviewer_action(addon, request.user, msg, amo.LOG.REVIEW_DEVICE_OVERRIDE) if old_features != new_features: # The reviewer overrode the requirements. We need to not # publish this app immediately. if addon.publish_type == amo.PUBLISH_IMMEDIATE: addon.update(publish_type=amo.PUBLISH_PRIVATE) appfeatures_form.save(mark_for_rereview=False) # Log that the reviewer changed the minimum requirements. added_features = new_features - old_features removed_features = old_features - new_features fmt = ', '.join( [_(u'Added {0}').format(f) for f in added_features] + [_(u'Removed {0}').format(f) for f in removed_features]) # L10n: {0} is the list of requirements changes. msg = _(u'Requirements changed by reviewer: {0}').format(fmt) log_reviewer_action(addon, request.user, msg, amo.LOG.REVIEW_FEATURES_OVERRIDE) score = form.helper.process() if form.cleaned_data.get('notify'): # TODO: bug 741679 for implementing notifications in Marketplace. EditorSubscription.objects.get_or_create(user=request.user, addon=addon) is_tarako = form.cleaned_data.get('is_tarako', False) if is_tarako: Tag(tag_text='tarako').save_tag(addon) else: Tag(tag_text='tarako').remove_tag(addon) # Success message. if score: score = ReviewerScore.objects.filter(user=request.user)[0] # L10N: {0} is the type of review. {1} is the points they earned. # {2} is the points they now have total. success = _( u'"{0}" successfully processed (+{1} points, {2} total).'. format(unicode(amo.REVIEWED_CHOICES[score.note_key]), score.score, ReviewerScore.get_total(request.user))) else: success = _('Review successfully processed.') messages.success(request, success) return redirect(redirect_url) canned = CannedResponse.objects.all() actions = form.helper.actions.items() try: if not version: raise Version.DoesNotExist show_diff = (addon.versions.exclude(id=version.id).filter( files__isnull=False, created__lt=version.created, files__status=amo.STATUS_PUBLIC).latest()) except Version.DoesNotExist: show_diff = None # The actions we should show a minimal form from. actions_minimal = [k for (k, a) in actions if not a.get('minimal')] # We only allow the user to check/uncheck files for "pending" allow_unchecking_files = form.helper.review_type == "pending" versions = (Version.with_deleted.filter( addon=addon).order_by('-created').transform( Version.transformer_activity).transform(Version.transformer)) product_attrs = { 'product': json.dumps(product_as_dict(request, addon, False, 'reviewer'), cls=JSONEncoder), 'manifest_url': addon.manifest_url, } pager = paginate(request, versions, 10) num_pages = pager.paginator.num_pages count = pager.paginator.count ctx = context(request, version=version, product=addon, pager=pager, num_pages=num_pages, count=count, form=form, canned=canned, is_admin=is_admin, status_types=amo.STATUS_CHOICES, show_diff=show_diff, allow_unchecking_files=allow_unchecking_files, actions=actions, actions_minimal=actions_minimal, tab=queue_type, product_attrs=product_attrs, attachment_formset=attachment_formset, appfeatures_form=appfeatures_form) if features_list is not None: ctx['feature_list'] = features_list return render(request, 'reviewers/review.html', ctx)