Add a new API endpoint for ScannerResult(s) (#13335)

This commit is contained in:
William Durand 2020-01-24 15:14:43 +01:00 коммит произвёл GitHub
Родитель 2897d12735
Коммит 95d694b45f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
10 изменённых файлов: 166 добавлений и 0 удалений

Просмотреть файл

@ -43,4 +43,5 @@ using the API.
hero
ratings
reviewers
scanners
signing

Просмотреть файл

@ -366,6 +366,7 @@ v4 API changelog
* 2019-10-17: moved /authenticate endpoint from api/v4/accounts/authenticate to version-less api/auth/authenticate-callback https://github.com/mozilla/addons-server/issues/10487
* 2019-11-14: removed ``is_source_public`` property from addons API https://github.com/mozilla/addons-server/issues/12514
* 2019-12-05: removed /addons/featured endpoint from v4+ and featured support from other addon api endpoints. https://github.com/mozilla/addons-server/issues/12937
* 2020-01-23: added /scanner/results (internal API endpoint).
.. _`#11380`: https://github.com/mozilla/addons-server/issues/11380/
.. _`#11379`: https://github.com/mozilla/addons-server/issues/11379/

Просмотреть файл

@ -0,0 +1,22 @@
============
Scanners
============
.. note::
These APIs are subject to change at any time and are for internal use only.
---------------------
Scanner Results
---------------------
.. _scanner-results:
This endpoint returns a list of labelled scanner results.
.. http:get:: /api/v4/scanner/results/
:>json int id: The scanner result ID.
:>json string scanner: The scanner name.
:>json object results: The scanner (raw) results.

Просмотреть файл

@ -29,6 +29,7 @@ v4_api_urls = [
url(r'^', include('olympia.signing.urls')),
url(r'^', include(amo_api_patterns)),
url(r'^hero/', include('olympia.hero.urls')),
url(r'^scanner/', include('olympia.scanners.api_urls')),
]
urlpatterns = [

Просмотреть файл

@ -0,0 +1,7 @@
from django.conf.urls import url
from .views import ScannerResultViewSet
urlpatterns = [
url(r'^results/$', ScannerResultViewSet.as_view(), name='scanner-results'),
]

Просмотреть файл

@ -0,0 +1,21 @@
# Generated by Django 2.2.9 on 2020-01-22 16:49
from django.db import migrations
def create_waffle_switch(apps, schema_editor):
Switch = apps.get_model('waffle', 'Switch')
Switch.objects.create(
name='enable-scanner-results-api',
active=False,
note='Enable the API endpoint that exposes the scanner results',
)
class Migration(migrations.Migration):
dependencies = [
('scanners', '0022_auto_20200122_1644'),
]
operations = [migrations.RunPython(create_waffle_switch)]

Просмотреть файл

@ -0,0 +1,15 @@
from rest_framework import serializers
from .models import ScannerResult
class ScannerResultSerializer(serializers.ModelSerializer):
scanner = serializers.SerializerMethodField()
results = serializers.JSONField()
class Meta:
model = ScannerResult
fields = ('id', 'scanner', 'results')
def get_scanner(self, obj):
return obj.get_scanner_name()

Просмотреть файл

@ -0,0 +1,15 @@
from olympia.amo.tests import TestCase
from olympia.constants.scanners import CUSTOMS
from olympia.scanners.models import ScannerResult
from olympia.scanners.serializers import ScannerResultSerializer
class TestScannerResultSerializer(TestCase):
def test_serialize(self):
result = ScannerResult.objects.create(scanner=CUSTOMS)
data = ScannerResultSerializer(instance=result).data
assert data == {
'id': result.id,
'scanner': result.get_scanner_name(),
'results': result.results,
}

Просмотреть файл

@ -0,0 +1,51 @@
from olympia.amo.tests import (
APITestClient,
TestCase,
reverse_ns,
user_factory,
)
from olympia.constants.scanners import YARA
from olympia.scanners.models import ScannerResult
from olympia.scanners.serializers import ScannerResultSerializer
class TestScannerResultViewSet(TestCase):
client_class = APITestClient
def setUp(self):
super().setUp()
self.user = user_factory()
self.grant_permission(self.user, 'Admin:ScannersResultsView')
self.client.login_api(self.user)
self.url = reverse_ns('scanner-results', api_version='v5')
def test_endpoint_requires_authentication(self):
self.client.logout_api()
response = self.client.get(self.url)
assert response.status_code == 401
def test_endpoint_requires_permissions(self):
self.user = user_factory()
self.client.login_api(self.user)
response = self.client.get(self.url)
assert response.status_code == 403
def test_endpoint_can_be_disabled(self):
self.create_switch('enable-scanner-results-api', active=False)
response = self.client.get(self.url)
assert response.status_code == 404
def test_get(self):
yara_result = ScannerResult.objects.create(scanner=YARA)
self.create_switch('enable-scanner-results-api', active=True)
response = self.client.get(self.url)
assert response.status_code == 200
json = response.json()
assert 'results' in json
results = json['results']
assert len(results) == 1
assert (results[0] ==
ScannerResultSerializer(instance=yara_result).data)

Просмотреть файл

@ -0,0 +1,32 @@
import waffle
from django.db.transaction import non_atomic_requests
from django.http import Http404
from rest_framework.generics import ListAPIView
from olympia import amo
from olympia.api.permissions import GroupPermission
from .models import ScannerResult
from .serializers import ScannerResultSerializer
class ScannerResultViewSet(ListAPIView):
permission_classes = [
GroupPermission(amo.permissions.ADMIN_SCANNERS_RESULTS_VIEW)
]
queryset = ScannerResult.objects.all()
serializer_class = ScannerResultSerializer
def get(self, request, format=None):
if not waffle.switch_is_active('enable-scanner-results-api'):
raise Http404
return super().get(request, format)
@classmethod
def as_view(cls, **initkwargs):
"""The API is read-only so we can turn off atomic requests."""
return non_atomic_requests(
super(ScannerResultViewSet, cls).as_view(**initkwargs)
)