コード例 #1
0
 def setUp(self):
     self.permission = GroupPermission('Drinkers', 'Beer')
     self.obj = Mock()
     self.profile = UserProfile.objects.get(pk=2519)
     self.anonymous = AnonymousUser()
     self.request = RequestFactory().get('/')
     self.request.user = self.anonymous
コード例 #2
0
ファイル: views.py プロジェクト: ayushagrawal288/zamboni
class VersionViewSet(CORSMixin, mixins.RetrieveModelMixin,
                     mixins.UpdateModelMixin, viewsets.GenericViewSet):
    queryset = Version.objects.exclude(addon__status=mkt.STATUS_DELETED)
    serializer_class = VersionSerializer
    authentication_classes = [
        RestOAuthAuthentication, RestSharedSecretAuthentication,
        RestAnonymousAuthentication
    ]
    permission_classes = [
        AnyOf(AllowReadOnlyIfPublic, AllowRelatedAppOwner,
              GroupPermission('Apps', 'Review'), GroupPermission('Admin', '%'))
    ]
    cors_allowed_methods = ['get', 'patch', 'put']

    def update(self, request, *args, **kwargs):
        """
        Allow a version's features to be updated.
        """
        obj = self.get_object()

        # Update features if they are provided.
        if 'features' in request.DATA:

            # Raise an exception if any invalid features are passed.
            invalid = [
                f for f in request.DATA['features']
                if f.upper() not in APP_FEATURES.keys()
            ]
            if any(invalid):
                raise ParseError('Invalid feature(s): %s' % ', '.join(invalid))

            # Update the value of each feature (note: a feature not present in
            # the form data is assumed to be False)
            data = {}
            for key, name in APP_FEATURES.items():
                field_name = 'has_' + key.lower()
                data[field_name] = key.lower() in request.DATA['features']
            obj.features.update(**data)

            del request.DATA['features']

        return super(VersionViewSet, self).update(request, *args, **kwargs)

    @action(methods=['PATCH'],
            cors_allowed_methods=VersionStatusViewSet.cors_allowed_methods)
    def status(self, request, *args, **kwargs):
        self.queryset = Version.with_deleted.all()
        kwargs['version'] = self.get_object()
        view = VersionStatusViewSet.as_view({'patch': 'update'})
        return view(request, *args, **kwargs)
コード例 #3
0
class AppEscalate(_AppAction, CreateAPIView, DestroyAPIView):
    permission_classes = [ByHttpMethod({
        'options': AllowAny,
        'post': GroupPermission('Apps', 'Review'),
        'delete': GroupPermission('Apps', 'Edit'),
    })]
    verb = "escalate"

    def delete(self, request, pk, *a, **kw):
        app = self.get_object()
        handler = ReviewApp(request, app, app.latest_version, ())
        handler.set_data(request.QUERY_PARAMS)
        handler.process_clear_escalation()
        return Response()
コード例 #4
0
class FeedAppViewSet(CORSMixin, MarketplaceView, SlugOrIdMixin,
                     ImageURLUploadMixin):
    """
    A viewset for the FeedApp class, which highlights a single app and some
    additional metadata (e.g. a review or a screenshot).
    """
    authentication_classes = [
        RestOAuthAuthentication, RestSharedSecretAuthentication,
        RestAnonymousAuthentication
    ]
    permission_classes = [
        AnyOf(AllowReadOnly, GroupPermission('Feed', 'Curate'))
    ]
    filter_backends = (OrderingFilter, )
    queryset = FeedApp.objects.all()
    cors_allowed_methods = ('get', 'delete', 'post', 'put', 'patch')
    serializer_class = FeedAppSerializer

    image_fields = (('background_image_upload_url', 'image_hash', ''), )

    def list(self, request, *args, **kwargs):
        page = self.paginate_queryset(self.filter_queryset(
            self.get_queryset()))
        serializer = self.get_pagination_serializer(page)
        return response.Response(serializer.data)
コード例 #5
0
ファイル: views.py プロジェクト: Dreadchild/zamboni
class GlobalStats(CORSMixin, APIView):
    authentication_classes = (RestOAuthAuthentication,
                              RestSharedSecretAuthentication)
    cors_allowed_methods = ['get']
    permission_classes = [GroupPermission('Stats', 'View')]

    def get(self, request, metric):
        if metric not in STATS:
            raise http.Http404('No metric by that name.')

        stat = STATS[metric]

        # Perform form validation.
        form = StatsForm(request.GET)
        if not form.is_valid():
            raise ParseError(dict(form.errors.items()))

        qs = form.cleaned_data

        dimensions = {}
        if 'dimensions' in stat:
            for key, default in stat['dimensions'].items():
                val = request.GET.get(key, default)
                if val is not None:
                    # Avoid passing kwargs to the monolith client when the
                    # dimension is None to avoid facet filters being applied.
                    dimensions[key] = request.GET.get(key, default)

        return Response(
            _get_monolith_data(stat, qs.get('start'), qs.get('end'),
                               qs.get('interval'), dimensions))
コード例 #6
0
 def setUp(self):
     self.permission = GroupPermission('Drinkers', 'Beer')
     self.obj = Mock()
     self.profile = UserProfile.objects.get(pk=2519)
     self.anonymous = AnonymousUser()
     self.request = RequestFactory().get('/')
     self.request.user = self.anonymous
コード例 #7
0
ファイル: views.py プロジェクト: j-barron/zamboni
class ReviewersSearchView(SearchView):
    cors_allowed_methods = ['get']
    authentication_classes = [
        RestSharedSecretAuthentication, RestOAuthAuthentication
    ]
    permission_classes = [GroupPermission('Apps', 'Review')]
    form_class = ApiReviewersSearchForm
    serializer_class = ReviewersESAppSerializer

    def search(self, request):
        # Parse form.
        form = self.form_class(request.GET if request else None)
        if not form.is_valid():
            raise form_errors(form)
        form_data = form.cleaned_data

        # Status filter.
        data = search_form_to_es_fields(form_data)
        if form_data.get('status') != 'any':
            data.update(status=form_data.get('status'))

        # Do filter.
        sq = apply_reviewer_filters(request,
                                    WebappIndexer.search(),
                                    data=form_data)
        sq = WebappIndexer.get_app_filter(request, data, sq=sq, no_filter=True)

        page = self.paginate_queryset(sq)
        return self.get_pagination_serializer(page), request.GET.get('q', '')
コード例 #8
0
ファイル: views.py プロジェクト: Dreadchild/zamboni
class GlobalStatsTotal(CORSMixin, APIView, StatsTotalBase):
    authentication_classes = (RestOAuthAuthentication,
                              RestSharedSecretAuthentication)
    cors_allowed_methods = ['get']
    permission_classes = [GroupPermission('Stats', 'View')]
    slug_field = 'app_slug'

    def get(self, request):
        client = self.get_client()

        # Note: We have to do this as separate requests so that if one fails
        # the rest can still be returned.
        data = {}
        for metric, stat in STATS_TOTAL.items():
            data[metric] = {}
            query = self.get_query(metric, stat['metric'])

            try:
                resp = client.raw(query)
            except ValueError as e:
                log.info('Received value error from monolith client: %s' % e)
                continue

            self.process_response(resp, data)

        return Response(data)
コード例 #9
0
ファイル: views.py プロジェクト: Dreadchild/zamboni
class AppStatsTotal(CORSMixin, SlugOrIdMixin, ListAPIView, StatsTotalBase):
    authentication_classes = (RestOAuthAuthentication,
                              RestSharedSecretAuthentication)
    cors_allowed_methods = ['get']
    permission_classes = [
        AnyOf(AllowAppOwner, GroupPermission('Stats', 'View'))
    ]
    queryset = Webapp.objects.all()
    slug_field = 'app_slug'

    def get(self, request, pk):
        app = self.get_object()
        client = self.get_client()

        # Note: We have to do this as separate requests so that if one fails
        # the rest can still be returned.
        data = {}
        for metric, stat in APP_STATS_TOTAL.items():
            data[metric] = {}
            query = self.get_query(metric, stat['metric'], app.id)

            try:
                resp = client.raw(query)
            except ValueError as e:
                log.info('Received value error from monolith client: %s' % e)
                continue

            self.process_response(resp, data)

        return Response(data)
コード例 #10
0
class MonolithViewSet(CORSMixin, mixins.DestroyModelMixin,
                      mixins.ListModelMixin, mixins.RetrieveModelMixin,
                      viewsets.GenericViewSet):
    cors_allowed_methods = ('get', 'delete')
    permission_classes = [GroupPermission('Monolith', 'API')]
    authentication_classes = [RestOAuthAuthentication]
    serializer_class = MonolithSerializer

    def get_queryset(self):
        form = MonolithForm(self.request.QUERY_PARAMS)
        if not form.is_valid():
            return Response(form.errors, status=status.HTTP_400_BAD_REQUEST)

        key = form.cleaned_data['key']
        start = form.cleaned_data['start']
        end = form.cleaned_data['end']

        qs = MonolithRecord.objects.all()
        if key:
            qs = qs.filter(key=key)
        if start is not None:
            qs = qs.filter(recorded__gte=start)
        if end is not None:
            qs = qs.filter(recorded__lt=end)
        return qs

    @transaction.commit_on_success
    def delete(self, request, *args, **kwargs):
        qs = self.filter_queryset(self.get_queryset())
        logger.info('Deleting %d monolith resources' % qs.count())
        qs.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)
コード例 #11
0
ファイル: views.py プロジェクト: j-barron/zamboni
class CannedResponseViewSet(CORSMixin, MarketplaceView, viewsets.ModelViewSet):
    authentication_classes = (RestOAuthAuthentication,
                              RestSharedSecretAuthentication)
    permission_classes = [GroupPermission('Admin', 'ReviewerTools')]
    model = CannedResponse
    serializer_class = CannedResponseSerializer
    cors_allowed_methods = ['get', 'post', 'patch', 'put', 'delete']
コード例 #12
0
class FailureNotificationView(MarketplaceView, GenericAPIView):
    authentication_classes = [
        RestOAuthAuthentication, RestSharedSecretAuthentication
    ]
    permission_classes = [GroupPermission('Transaction', 'NotifyFailure')]
    queryset = Contribution.objects.filter(uuid__isnull=False)

    def patch(self, request, *args, **kwargs):
        form = FailureForm(request.DATA)
        if not form.is_valid():
            return Response(form.errors, status=status.HTTP_400_BAD_REQUEST)

        obj = self.get_object()
        data = {
            'transaction_id':
            obj,
            'transaction_url':
            absolutify(
                urlparams(reverse('mkt.developers.transactions'),
                          transaction_id=obj.uuid)),
            'url':
            form.cleaned_data['url'],
            'retries':
            form.cleaned_data['attempts']
        }
        owners = obj.addon.authors.values_list('email', flat=True)
        send_mail_jinja('Payment notification failure.',
                        'webpay/failure.txt',
                        data,
                        recipient_list=owners)
        return Response(status=status.HTTP_202_ACCEPTED)
コード例 #13
0
ファイル: views.py プロジェクト: ayushagrawal288/zamboni
class ReviewersWebsiteSearchView(WebsiteSearchView):
    permission_classes = [GroupPermission('Apps', 'Review')]
    filter_backends = [
        SearchQueryFilter, ReviewerWebsiteSearchFormFilter, SortingFilter
    ]
    serializer_class = ReviewerESWebsiteSerializer
    form_class = ReviewersWebsiteSearchForm
コード例 #14
0
class PriceTierViewSet(generics.CreateAPIView,
                       generics.RetrieveUpdateDestroyAPIView,
                       ModelViewSet):
    permission_classes = [GroupPermission('Prices', 'Edit')]
    authentication_classes = [RestOAuthAuthentication]
    serializer_class = PriceTierSerializer
    model = Price
コード例 #15
0
class ProductIconViewSet(CORSMixin, MarketplaceView, ListModelMixin,
                         RetrieveModelMixin, GenericViewSet):
    authentication_classes = [
        RestOAuthAuthentication, RestSharedSecretAuthentication,
        RestAnonymousAuthentication
    ]
    permission_classes = [
        AnyOf(AllowReadOnly, GroupPermission('ProductIcon', 'Create'))
    ]
    queryset = ProductIcon.objects.all()
    serializer_class = ProductIconSerializer
    cors_allowed_methods = ['get', 'post']
    filter_fields = ('ext_url', 'ext_size', 'size')

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.DATA)
        if serializer.is_valid():
            log.info('Resizing product icon %s @ %s to %s for webpay' %
                     (serializer.data['ext_url'], serializer.data['ext_size'],
                      serializer.data['size']))
            tasks.fetch_product_icon.delay(serializer.data['ext_url'],
                                           serializer.data['ext_size'],
                                           serializer.data['size'])
            return Response(serializer.data, status=status.HTTP_202_ACCEPTED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
コード例 #16
0
ファイル: views.py プロジェクト: ayushagrawal288/zamboni
class VersionStatusViewSet(mixins.UpdateModelMixin, viewsets.GenericViewSet):
    """Special API view used by senior reviewers and admins to modify a version
    (actually the corresponding File) status."""
    authentication_classes = [
        RestOAuthAuthentication, RestSharedSecretAuthentication,
        RestAnonymousAuthentication
    ]
    permission_classes = [GroupPermission('Admin', '%')]
    serializer_class = FileStatusSerializer
    cors_allowed_methods = ['patch']

    def get_object(self):
        # Since we are fetching a totally different object than the pk the
        # client is passing, we need to make sure to override the pk in
        # self.kwargs, DRF uses it as a precautionary measure in in pre_save().
        obj = self.kwargs['version'].all_files[0]
        self.kwargs[self.lookup_field] = obj.pk
        return obj

    def update(self, request, *args, **kwargs):
        # PUT is disallowed, only PATCH is accepted for this endpoint.
        if request.method == 'PUT':
            raise MethodNotAllowed('PUT')
        res = super(VersionStatusViewSet, self).update(request, *args,
                                                       **kwargs)
        app = self.object.version.addon
        res.data['app_status'] = mkt.STATUS_CHOICES_API[app.status]
        return res
コード例 #17
0
ファイル: resources.py プロジェクト: vinu76jsr/zamboni
class MonolithView(CORSMixin, MarketplaceView, ListAPIView):
    cors_allowed_methods = ['get']
    permission_classes = [GroupPermission('Monolith', 'API')]
    authentication_classes = [RestOAuthAuthentication]
    serializer_class = MonolithSerializer

    def get_queryset(self):
        form = MonolithForm(self.request.QUERY_PARAMS)
        if not form.is_valid():
            return Response(form.errors, status=status.HTTP_400_BAD_REQUEST)

        key = form.cleaned_data['key']
        start = form.cleaned_data['start']
        end = form.cleaned_data['end']

        log.info('[Monolith] Querying key:%s [%s:%s]' % (key, start, end))

        if key in STATS:
            return _get_query_result(key, start, end)

        else:
            qs = MonolithRecord.objects.all()
            if key:
                qs = qs.filter(key=key)
            if start is not None:
                qs = qs.filter(recorded__gte=start)
            if end is not None:
                qs = qs.filter(recorded__lt=end)

            return qs
コード例 #18
0
ファイル: views.py プロジェクト: Dreadchild/zamboni
class TransactionAPI(CORSMixin, APIView):
    """
    API to query by transaction ID.

    Note: This is intended for Monolith to be able to associate a Solitude
    transaction with an app and price tier amount in USD.

    """
    authentication_classes = (RestOAuthAuthentication,
                              RestSharedSecretAuthentication)
    cors_allowed_methods = ['get']
    permission_classes = [GroupPermission('RevenueStats', 'View')]

    def get(self, request, transaction_id):
        try:
            contrib = (Contribution.objects.select_related('price_tier').get(
                transaction_id=transaction_id))
        except Contribution.DoesNotExist:
            raise http.Http404('No transaction by that ID.')

        data = {
            'id': transaction_id,
            'app_id': contrib.addon_id,
            'amount_USD': contrib.price_tier.price,
            'type': amo.CONTRIB_TYPES[contrib.type],
        }

        return Response(data)
コード例 #19
0
ファイル: views.py プロジェクト: miltonpereira/zamboni
class ReviewingView(ListAPIView):
    authentication_classes = [RestOAuthAuthentication,
                              RestSharedSecretAuthentication]
    permission_classes = [GroupPermission('Apps', 'Review')]
    serializer_class = ReviewingSerializer

    def get_queryset(self):
        return [row['app'] for row in AppsReviewing(self.request).get_apps()]
コード例 #20
0
ファイル: views.py プロジェクト: chenliu0831/zamboni
class FeedItemViewSet(viewsets.ModelViewSet):
    authentication_classes = [RestOAuthAuthentication,
                              RestSharedSecretAuthentication,
                              RestAnonymousAuthentication]
    permission_classes = [AnyOf(AllowReadOnly,
                                GroupPermission('Feed', 'Curate'))]
    queryset = FeedItem.objects.all()
    serializer_class = FeedItemSerializer
コード例 #21
0
class FeedBuilderView(CORSMixin, APIView):
    authentication_classes = [
        RestOAuthAuthentication, RestSharedSecretAuthentication
    ]
    permission_classes = [GroupPermission('Feed', 'Curate')]
    cors_allowed_methods = ('put', )

    def put(self, request, *args, **kwargs):
        """
        For each region in the object:
        Deletes all of the (carrier-less) FeedItems in the region.
        Batch create all of the FeedItems in order for each region.

        -- feed - object of regions that point to a list of feed
                  element IDs (as well as their type) .
        {
            'us': [
                ['app', 36L],
                ['app', 42L],
                ['collection', 12L],
                ['brand', 12L]
            ]
        }
        """
        regions = [
            mkt.regions.REGIONS_DICT[region].id
            for region in request.DATA.keys()
        ]
        FeedItem.objects.filter(carrier=None, region__in=regions).delete()

        feed_items = []
        for region, feed_elements in request.DATA.items():
            for order, feed_element in enumerate(feed_elements):
                try:
                    item_type, item_id = feed_element
                except ValueError:
                    return response.Response(
                        'Expected two-element arrays.',
                        status=status.HTTP_400_BAD_REQUEST)
                feed_item = {
                    'region': mkt.regions.REGIONS_DICT[region].id,
                    'order': order,
                    'item_type': item_type,
                }
                feed_item[item_type + '_id'] = item_id
                feed_items.append(FeedItem(**feed_item))

        FeedItem.objects.bulk_create(feed_items)

        # Index the feed items created. bulk_create doesn't call save or
        # post_save so get the IDs manually.
        feed_item_ids = list(
            FeedItem.objects.filter(region__in=regions).values_list('id',
                                                                    flat=True))
        FeedItem.get_indexer().index_ids(feed_item_ids, no_delay=True)

        return response.Response(status=status.HTTP_201_CREATED)
コード例 #22
0
class CollectionImageViewSet(CORSMixin, SlugOrIdMixin, MarketplaceView,
                             generics.GenericAPIView, viewsets.ViewSet):
    permission_classes = [
        AnyOf(AllowReadOnly, GroupPermission('Feed', 'Curate'))
    ]
    authentication_classes = [
        RestOAuthAuthentication, RestSharedSecretAuthentication,
        RestAnonymousAuthentication
    ]
    cors_allowed_methods = ('get', 'put', 'delete')

    hash_field = 'image_hash'
    image_suffix = ''

    # Dummy serializer to keep DRF happy when it's answering to OPTIONS.
    serializer_class = Serializer

    def perform_content_negotiation(self, request, force=False):
        """
        Force DRF's content negociation to not raise an error - It wants to use
        the format passed to the URL, but we don't care since we only deal with
        "raw" content: we don't even use the renderers.
        """
        return super(CollectionImageViewSet,
                     self).perform_content_negotiation(request, force=True)

    @cache_control(max_age=60 * 60 * 24 * 365)
    def retrieve(self, request, *args, **kwargs):
        obj = self.get_object()
        if not getattr(obj, 'image_hash', None):
            raise Http404
        return HttpResponseSendFile(request,
                                    obj.image_path(self.image_suffix),
                                    content_type='image/png')

    def update(self, request, *args, **kwargs):
        obj = self.get_object()
        try:
            img, hash_ = DataURLImageField().from_native(request.read())
        except ValidationError:
            return Response(status=status.HTTP_400_BAD_REQUEST)
        i = Image.open(img)
        with public_storage.open(obj.image_path(self.image_suffix), 'wb') as f:
            i.save(f, 'png')
        # Store the hash of the original image data sent.
        obj.update(**{self.hash_field: hash_})

        pngcrush_image.delay(obj.image_path(self.image_suffix))
        return Response(status=status.HTTP_204_NO_CONTENT)

    def destroy(self, request, *args, **kwargs):
        obj = self.get_object()
        if getattr(obj, 'image_hash', None):
            public_storage.delete(obj.image_path(self.image_suffix))
            obj.update(**{self.hash_field: None})
        return Response(status=status.HTTP_204_NO_CONTENT)
コード例 #23
0
class FeedElementSearchView(BaseFeedESView):
    """
    Search view for the Curation Tools.

    Returns an object keyed by feed element type
    ('apps', 'brands', 'collections').
    """
    authentication_classes = [
        RestOAuthAuthentication, RestSharedSecretAuthentication
    ]
    permission_classes = [GroupPermission('Feed', 'Curate')]
    cors_allowed_methods = ('get', )

    def _phrase(self, q):
        return {
            'query': q,
            'type': 'phrase',
            'slop': 2,
        }

    def get(self, request, *args, **kwargs):
        q = request.GET.get('q')

        # Make search.
        queries = [
            query.Q('match', slug=self._phrase(q)),  # Slug.
            query.Q('match', type=self._phrase(q)),  # Type.
            query.Q('match', search_names=self._phrase(q)),  # Name.
            query.Q('prefix', carrier=q),  # Shelf carrier.
            query.Q('term', region=q)  # Shelf region.
        ]
        sq = query.Bool(should=queries)

        # Search.
        res = {'apps': [], 'brands': [], 'collections': [], 'shelves': []}
        es = Search(using=FeedItemIndexer.get_es(),
                    index=self.get_feed_element_index())
        feed_elements = es.query(sq).execute().hits
        if not feed_elements:
            return response.Response(res, status=status.HTTP_404_NOT_FOUND)

        # Deserialize.
        ctx = {
            'app_map': self.get_apps(request,
                                     self.get_app_ids_all(feed_elements)),
            'request': request
        }
        for feed_element in feed_elements:
            item_type = feed_element.item_type
            serializer = self.SERIALIZERS[item_type]
            data = serializer(feed_element, context=ctx).data
            res[self.PLURAL_TYPES[item_type]].append(data)

        # Return.
        return response.Response(res, status=status.HTTP_200_OK)
コード例 #24
0
ファイル: views.py プロジェクト: miltonpereira/zamboni
class FeedShelfPublishView(CORSMixin, APIView):
    """
    put -- creates a FeedItem for a FeedShelf with respective carrier/region
        pair.  Deletes any currently existing FeedItems with the carrier/region
        pair to effectively "unpublish" it since only one shelf can be toggled
        at a time for a carrier/region.

    delete -- deletes the FeedItem for a FeedShelf with respective
        carrier/region.
    """
    authentication_classes = [RestOAuthAuthentication,
                              RestSharedSecretAuthentication]
    permission_classes = [GroupPermission('Feed', 'Curate')]
    cors_allowed_methods = ('delete', 'put',)

    def get_object(self, pk):
        if pk.isdigit():
            return FeedShelf.objects.get(pk=pk)
        else:
            return FeedShelf.objects.get(slug=pk)

    def put(self, request, *args, **kwargs):
        try:
            shelf = self.get_object(self.kwargs['pk'])
        except FeedShelf.DoesNotExist:
            return response.Response(status=status.HTTP_404_NOT_FOUND)

        feed_item_kwargs = {
            'item_type': feed.FEED_TYPE_SHELF,
            'carrier': shelf.carrier,
            'region': shelf.region
        }
        FeedItem.objects.filter(**feed_item_kwargs).delete()
        feed_item = FeedItem.objects.create(shelf_id=shelf.id,
                                            **feed_item_kwargs)

        # Return.
        return response.Response(FeedItemSerializer(feed_item).data,
                                 status=status.HTTP_201_CREATED)

    def delete(self, request, *args, **kwargs):
        try:
            shelf = self.get_object(self.kwargs['pk'])
        except FeedShelf.DoesNotExist:
            return response.Response(status=status.HTTP_404_NOT_FOUND)

        feed_item_kwargs = {
            'item_type': feed.FEED_TYPE_SHELF,
            'carrier': shelf.carrier,
            'region': shelf.region
        }
        FeedItem.objects.filter(**feed_item_kwargs).delete()

        # Return.
        return response.Response(status=status.HTTP_204_NO_CONTENT)
コード例 #25
0
ファイル: views.py プロジェクト: labibismaiel/zamboni
class FeedAppViewSet(CORSMixin, viewsets.ModelViewSet):
    authentication_classes = [
        RestOAuthAuthentication, RestSharedSecretAuthentication,
        RestAnonymousAuthentication
    ]
    permission_classes = [
        AnyOf(AllowReadOnly, GroupPermission('Feed', 'Curate'))
    ]
    queryset = FeedApp.objects.all()
    cors_allowed_methods = ('get', 'post')
    serializer_class = FeedAppSerializer
コード例 #26
0
ファイル: views.py プロジェクト: ayushagrawal288/zamboni
class WebsiteSubmissionViewSet(CORSMixin, MarketplaceView,
                               viewsets.ModelViewSet):
    cors_allowed_methods = ['get', 'post']
    authentication_classes = [
        RestSharedSecretAuthentication, RestOAuthAuthentication
    ]
    queryset = WebsiteSubmission.objects.all()
    permission_classes = [GroupPermission('Websites', 'Submit')]
    serializer_class = PublicWebsiteSubmissionSerializer

    def pre_save(self, obj):
        setattr(obj, 'submitter', self.request.user)
コード例 #27
0
ファイル: views.py プロジェクト: j-barron/zamboni
class ReviewerScoreViewSet(CORSMixin, MarketplaceView, viewsets.ModelViewSet):
    authentication_classes = (RestOAuthAuthentication,
                              RestSharedSecretAuthentication)
    permission_classes = [GroupPermission('Admin', 'ReviewerTools')]
    serializer_class = ReviewerScoreSerializer
    cors_allowed_methods = ['get', 'post', 'patch', 'put', 'delete']

    # amo.REVIEWED_MANUAL is the default so we don't need to set it on the
    # instance when we are creating a new one, but we do need to set it on
    # queryset to prevent instances with other note_key values from ever being
    # returned.
    queryset = ReviewerScore.objects.filter(note_key=amo.REVIEWED_MANUAL)
コード例 #28
0
ファイル: views.py プロジェクト: ayushagrawal288/zamboni
class WebsiteLookupSearchView(WebsiteSearchView):
    permission_classes = [GroupPermission('WebsiteLookup', 'View')]
    filter_backends = [SearchQueryFilter]
    serializer_class = WebsiteLookupSerializer
    paginate_by = lkp.SEARCH_LIMIT
    max_paginate_by = lkp.MAX_RESULTS

    def get_paginate_by(self, *args, **kwargs):
        if self.request.GET.get(self.paginate_by_param) == 'max':
            return self.max_paginate_by
        else:
            return super(WebsiteLookupSearchView,
                         self).get_paginate_by(*args, **kwargs)
コード例 #29
0
ファイル: views.py プロジェクト: ayushagrawal288/zamboni
class NoRegionSearchView(SearchView):
    """
    A search view that allows searching for public apps regardless of region
    exclusions, protected behind a permission class.

    A special class is needed because when RegionFilter is included, as it is
    in the default SearchView, it will always use whatever region was set on
    the request, and we default to setting restofworld when no region is
    passed.

    """
    authentication_classes = [
        RestSharedSecretAuthentication, RestOAuthAuthentication
    ]
    permission_classes = [
        AnyOf(GroupPermission('Feed', 'Curate'),
              GroupPermission('OperatorDashboard', '*'), IsOperatorPermission)
    ]
    filter_backends = [
        SearchQueryFilter, PublicSearchFormFilter, PublicAppsFilter,
        DeviceTypeFilter, ProfileFilter, SortingFilter
    ]
コード例 #30
0
class FeedElementListView(BaseFeedESView, MarketplaceView,
                          generics.GenericAPIView):
    """
    Fetches the five most recent of a feed element type for Curation Tools.
    With pagination.
    """
    authentication_classes = [
        RestOAuthAuthentication, RestSharedSecretAuthentication
    ]
    permission_classes = [GroupPermission('Feed', 'Curate')]
    cors_allowed_methods = ('get', )
    paginator_class = ESPaginator

    def get_recent_feed_elements(self, sq):
        """Matches all sorted by recent."""
        return sq.sort('-created').query(query.MatchAll())

    def get(self, request, item_type, **kwargs):
        item_type = self.ITEM_TYPES[item_type]

        # Hit ES.
        sq = self.get_recent_feed_elements(
            Search(using=FeedItemIndexer.get_es(),
                   index=self.INDICES[item_type]))
        feed_elements = self.paginate_queryset(sq)
        if not feed_elements:
            return response.Response({'objects': []},
                                     status=status.HTTP_404_NOT_FOUND)

        # Deserialize. Manually use pagination serializer because this view
        # uses multiple serializers.
        meta = mkt.api.paginator.CustomPaginationSerializer(feed_elements,
                                                            context={
                                                                'request':
                                                                request
                                                            }).data['meta']
        objects = self.SERIALIZERS[item_type](
            feed_elements,
            context={
                'app_map':
                self.get_apps(request, self.get_app_ids_all(feed_elements)),
                'request':
                request
            },
            many=True).data

        return response.Response({
            'meta': meta,
            'objects': objects
        },
                                 status=status.HTTP_200_OK)
コード例 #31
0
class StatusViewSet(mixins.RetrieveModelMixin, mixins.UpdateModelMixin,
                    GenericViewSet):
    queryset = Webapp.objects.all()
    authentication_classes = [
        RestOAuthAuthentication, RestSharedSecretAuthentication
    ]
    permission_classes = [AnyOf(AllowAppOwner, GroupPermission('Admin', '%s'))]
    serializer_class = AppStatusSerializer

    def update(self, request, *args, **kwargs):
        # PUT is disallowed, only PATCH is accepted for this endpoint.
        if request.method == 'PUT':
            raise MethodNotAllowed('PUT')
        return super(StatusViewSet, self).update(request, *args, **kwargs)
コード例 #32
0
class TestGroupPermission(TestCase):
    fixtures = fixture('user_2519')

    def setUp(self):
        self.permission = GroupPermission('Drinkers', 'Beer')
        self.obj = Mock()
        self.profile = UserProfile.objects.get(pk=2519)
        self.anonymous = AnonymousUser()
        self.request = RequestFactory().get('/')
        self.request.user = self.anonymous

    def test_has_permission_user_without(self):
        self.request.user = self.profile
        self.request.amo_user = self.profile
        self.request.groups = self.profile.groups.all()
        self.grant_permission(self.profile, 'Drinkers:Scotch')
        eq_(self.permission.has_permission(self.request, 'myview'), False)

    def test_has_permission_user_with(self):
        self.request.user = self.profile
        self.request.amo_user = self.profile
        self.request.groups = self.profile.groups.all()
        self.grant_permission(self.profile, 'Drinkers:Beer')
        eq_(self.permission.has_permission(self.request, 'myview'), True)

    def test_has_permission_anonymous(self):
        eq_(self.permission.has_permission(self.request, 'myview'), False)

    def test_has_object_permission_user_without(self):
        self.request.user = self.profile
        self.request.amo_user = self.profile
        self.request.groups = self.profile.groups.all()
        self.grant_permission(self.profile, 'Drinkers:Scotch')
        obj = Mock()
        eq_(self.permission.has_object_permission(self.request, 'myview', obj),
            False)

    def test_has_object_permission_user_with(self):
        self.request.user = self.profile
        self.request.amo_user = self.profile
        self.request.groups = self.profile.groups.all()
        self.grant_permission(self.profile, 'Drinkers:Beer')
        obj = Mock()
        eq_(self.permission.has_object_permission(self.request, 'myview', obj),
            True)

    def test_has_object_permission_anonymous(self):
        obj = Mock()
        eq_(self.permission.has_object_permission(self.request, 'myview', obj),
            False)
コード例 #33
0
class TestGroupPermission(TestCase):
    fixtures = fixture("user_2519")

    def setUp(self):
        self.permission = GroupPermission("Drinkers", "Beer")
        self.obj = Mock()
        self.profile = UserProfile.objects.get(pk=2519)
        self.anonymous = AnonymousUser()
        self.request = RequestFactory().get("/")
        self.request.user = self.anonymous

    def test_has_permission_user_without(self):
        self.request.user = self.profile.user
        self.request.amo_user = self.profile
        self.request.groups = self.profile.groups.all()
        self.grant_permission(self.profile, "Drinkers:Scotch")
        eq_(self.permission.has_permission(self.request, "myview"), False)

    def test_has_permission_user_with(self):
        self.request.user = self.profile.user
        self.request.amo_user = self.profile
        self.request.groups = self.profile.groups.all()
        self.grant_permission(self.profile, "Drinkers:Beer")
        eq_(self.permission.has_permission(self.request, "myview"), True)

    def test_has_permission_anonymous(self):
        eq_(self.permission.has_permission(self.request, "myview"), False)

    def test_has_object_permission_user_without(self):
        self.request.user = self.profile.user
        self.request.amo_user = self.profile
        self.request.groups = self.profile.groups.all()
        self.grant_permission(self.profile, "Drinkers:Scotch")
        obj = Mock()
        eq_(self.permission.has_object_permission(self.request, "myview", obj), False)

    def test_has_object_permission_user_with(self):
        self.request.user = self.profile.user
        self.request.amo_user = self.profile
        self.request.groups = self.profile.groups.all()
        self.grant_permission(self.profile, "Drinkers:Beer")
        obj = Mock()
        eq_(self.permission.has_object_permission(self.request, "myview", obj), True)

    def test_has_object_permission_anonymous(self):
        obj = Mock()
        eq_(self.permission.has_object_permission(self.request, "myview", obj), False)