Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

add 403 and skip_cache to comm thread app view

  • Loading branch information...
commit 0e8c606a8949cba45f6aa931c26f2daeb8dcf0bd 1 parent 315a0f0
@ngokevin ngokevin authored
View
16 mkt/comm/api.py
@@ -1,9 +1,7 @@
import os
from django.conf import settings
-from django.core.servers.basehttp import FileWrapper
from django.db.models import Q
-from django.http import Http404
from django.shortcuts import get_object_or_404
from rest_framework import status
@@ -23,6 +21,7 @@
from rest_framework.viewsets import GenericViewSet
from addons.models import Addon
+from amo.decorators import skip_cache
from amo.helpers import absolutify
from amo.urlresolvers import reverse
from amo.utils import HttpResponseSendFile
@@ -36,7 +35,8 @@
from mkt.api.base import CORSMixin, MarketplaceView, SilentListModelMixin
from mkt.comm.models import (CommAttachment, CommunicationNote,
CommunicationNoteRead, CommunicationThread,
- user_has_perm_note, user_has_perm_thread)
+ user_has_perm_app, user_has_perm_note,
+ user_has_perm_thread)
from mkt.comm.tasks import consume_email, mark_thread_read
from mkt.comm.utils import (create_attachments, create_comm_note,
filter_notes_by_read_status)
@@ -261,6 +261,7 @@ class ThreadViewSet(SilentListModelMixin, RetrieveModelMixin,
filter_backends = (OrderingFilter,)
cors_allowed_methods = ['get', 'post', 'patch']
+ @skip_cache
def list(self, request):
self.serializer_class = ThreadSerializer
profile = request.amo_user
@@ -274,10 +275,13 @@ def list(self, request):
if 'app' in request.GET:
form = forms.AppSlugForm(request.GET)
if not form.is_valid():
- raise Http404()
+ return Response('App does not exist or no app slug given',
+ status=status.HTTP_404_NOT_FOUND)
+ elif not user_has_perm_app(profile, form.cleaned_data['app']):
+ return Response('You do not have permissions for this app',
+ status=status.HTTP_403_FORBIDDEN)
- # TODO: use CommunicationThread.with_perms once other PR merged in.
- queryset = CommunicationThread.objects.filter(pk__in=notes + cc,
+ queryset = CommunicationThread.objects.filter(
addon=form.cleaned_data['app'])
# Thread IDs and version numbers from same app.
View
14 mkt/comm/models.py
@@ -72,6 +72,20 @@ def check_acls_comm_obj(obj, profile):
return False
+def user_has_perm_app(user, app):
+ """
+ Check if user has any app-level ACLs.
+ (Mozilla contact, admin, review, senior reivewer, developer).
+ """
+ return (
+ check_acls(user, None, 'reviewer') or
+ user.addons.filter(pk=app.id).exists() or
+ check_acls(user, None, 'senior_reviewer') or
+ check_acls(user, None, 'admin') or
+ user.email in app.get_mozilla_contacts()
+ )
+
+
def user_has_perm_thread(thread, profile):
"""
Check if the user has read/write permissions on the given thread.
View
8 mkt/comm/tests/test_api.py
@@ -255,6 +255,7 @@ def test_response(self):
def test_addon_filter(self):
self._thread_factory(note=True)
+ self.grant_permission(self.user.get_profile(), 'Apps:Review')
res = self.client.get(self.list_url, {'app': '337141'})
eq_(res.status_code, 200)
eq_(len(res.json['objects']), 1)
@@ -268,6 +269,7 @@ def test_app_slug(self):
CommunicationNote.objects.create(author=self.profile, thread=thread,
note_type=0, body='something')
+ self.grant_permission(self.user.get_profile(), 'Apps:Review')
res = self.client.get(self.list_url, {'app': self.addon.app_slug})
eq_(res.status_code, 200)
eq_(res.json['objects'][0]['addon_meta']['app_slug'],
@@ -284,10 +286,12 @@ def test_app_threads(self):
addon=self.addon, version=version2, read_permission_public=True)
CommunicationThreadCC.objects.create(user=self.profile, thread=thread2)
+ self.grant_permission(self.user.get_profile(), 'Apps:Review')
res = self.client.get(self.list_url, {'app': self.addon.app_slug})
+ eq_(res.status_code, 200)
eq_(res.json['app_threads'],
- [{"id": thread2.id, "version__version": version2.version},
- {"id": thread1.id, "version__version": version1.version}])
+ [{'id': thread2.id, 'version__version': version2.version},
+ {'id': thread1.id, 'version__version': version1.version}])
def test_create(self):
self.create_switch('comm-dashboard')
View
14 mkt/comm/tests/test_models.py
@@ -13,7 +13,8 @@
from mkt.comm.models import (CommAttachment, CommunicationNote,
CommunicationThread, CommunicationThreadCC,
- CommunicationThreadToken, user_has_perm_note,
+ CommunicationThreadToken,
+ user_has_perm_app, user_has_perm_note,
user_has_perm_thread)
from mkt.comm.tests.test_api import CommTestMixin
from mkt.constants import comm as const
@@ -93,7 +94,6 @@ def test_manager(self):
self.thread).count(), 0)
self.note.update(author=self.user)
- eq_(CommunicationNote.objects.count(), 1)
eq_(CommunicationNote.objects.with_perms(self.user,
self.thread).count(), 1)
@@ -113,6 +113,16 @@ def test_has_perm_cc(self):
CommunicationThreadCC.objects.create(user=self.user, thread=self.obj)
self._eq_obj_perm(True)
+ def test_has_perm_app_reviewer(self):
+ ok_(not user_has_perm_app(self.user, self.addon))
+ self.grant_permission(self.user, 'Apps:Review')
+ ok_(user_has_perm_app(self.user, self.addon))
+
+ def test_has_perm_app_developer(self):
+ ok_(not user_has_perm_app(self.user, self.addon))
+ self.addon.addonuser_set.create(user=self.user)
+ ok_(user_has_perm_app(self.user, self.addon))
+
class TestThreadTokenModel(amo.tests.TestCase):
fixtures = ['base/addon_3615', 'base/user_999']
View
1  mkt/comm/tests/test_utils_.py
@@ -135,7 +135,6 @@ def test_create_note_existing_thread(self):
# More checking that joining a thread marks all old notes as read.
eq_(thread.thread_cc.count(), 3)
eq_(note.read_by_users.count(), 3)
- eq_(reply.read_by_users.count(), 2)
eq_(last_word.read_by_users.count(), 1)
@mock.patch('mkt.comm.utils.post_create_comm_note', new=mock.Mock)
View
4 mkt/comm/utils.py
@@ -13,8 +13,8 @@
from access.models import Group
from users.models import UserProfile
-from mkt.comm.models import (CommunicationNote, CommunicationNoteRead,
- CommunicationThreadToken, user_has_perm_thread)
+from mkt.comm.models import (CommunicationNoteRead, CommunicationThreadToken,
+ user_has_perm_thread)
from mkt.constants import comm
Please sign in to comment.
Something went wrong with that request. Please try again.