Remove unsafe methods form swagger ui

Also add custom exception handling to the api, uniforming how failures
are reported to the consumer
This commit is contained in:
mdoglio 2014-05-09 15:59:40 +02:00
Родитель 25e57fd3ba
Коммит 52700b1a90
8 изменённых файлов: 69 добавлений и 33 удалений

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

@ -56,5 +56,5 @@ def test_artifact_detail_bad_project(webapp, jm):
expect_errors=True
)
assert resp.status_int == 404
assert resp.json == {"message": "No project with name foo"}
assert resp.json == {"detail": "No project with name foo"}

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

@ -108,7 +108,7 @@ def test_note_detail_bad_project(webapp, jm):
expect_errors=True
)
assert resp.status_int == 404
assert resp.json == {"message": "No project with name foo"}
assert resp.json == {"detail": "No project with name foo"}
def test_create_note(webapp, eleven_jobs_processed, mock_message_broker, jm):

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

@ -98,7 +98,7 @@ def test_resultset_list_bad_project(webapp, jm):
)
assert resp.status_int == 404
assert resp.json == {"message": "No project with name foo"}
assert resp.json == {"detail": "No project with name foo"}
def test_resultset_list_empty_rs_still_show(webapp, initial_data,
@ -250,7 +250,7 @@ def test_result_set_detail_bad_project(webapp, jm):
expect_errors=True
)
assert resp.status_int == 404
assert resp.json == {"message": "No project with name foo"}
assert resp.json == {"detail": "No project with name foo"}
def test_resultset_create(sample_resultset, jm, initial_data):

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

@ -100,10 +100,7 @@ class TreeherderModelBase(object):
candidate_sources.append(source)
if not candidate_sources:
raise DatasetNotFoundError(
"No dataset found for project %r, contenttype %r."
% (self.project, contenttype)
)
raise DatasetNotFoundError(self.project, contenttype)
candidate_sources.sort(key=lambda s: s.dataset, reverse=True)
@ -111,7 +108,16 @@ class TreeherderModelBase(object):
class DatasetNotFoundError(ValueError):
pass
def __init__(self, project, contenttype, *args, **kwargs):
super(DatasetNotFoundError, self).__init__(*args, **kwargs)
self.project = project
self.contenttype = contenttype
def __unicode__(self):
return u"No dataset found for project {0} and contenttype '{1}'".format(
self.project,
self.contenttype,
)
class ObjectNotFoundException(Exception):

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

@ -209,7 +209,8 @@ REST_FRAMEWORK = {
),
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRenderer',
)
),
'EXCEPTION_HANDLER': 'treeherder.webapp.api.exceptions.exception_handler'
}
SITE_URL = "http://local.treeherder.mozilla.org"
@ -281,3 +282,5 @@ def obtain_username(email):
return email
BROWSERID_USERNAME_ALGO = obtain_username
SWAGGER_SETTINGS = {"enabled_methods": ['get',]}

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

@ -0,0 +1,35 @@
from rest_framework import exceptions
from rest_framework.response import Response
from rest_framework.views import exception_handler as drf_exc_handler
from django.conf import settings
from treeherder.model.derived import DatasetNotFoundError, ObjectNotFoundException
class ResourceNotFoundException(exceptions.APIException):
status_code = 404
default_detail = "Resource not found"
def exception_handler(exc):
"""
Add treeherder-specific exception handling to the rest framework
Mostly a conversion of treeherders ORM exceptions to drf APIExceptions
"""
if isinstance(exc, DatasetNotFoundError):
exc = ResourceNotFoundException(
"No project with name {0}".format(exc.project)
)
if isinstance(exc, ObjectNotFoundException):
exc = ResourceNotFoundException(
"{0} object not found using: {1}".format(
exc.table, unicode(exc.extra_info)))
response = drf_exc_handler(exc)
if response is None:
msg = {"detail": unicode(exc)}
if settings.DEBUG:
import traceback
msg["traceback"] = traceback.format_exc()
response = Response(msg, status=500)
return response

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

@ -1,6 +1,7 @@
from django.conf import settings
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework.exceptions import ParseError
from rest_framework.authentication import SessionAuthentication
from treeherder.webapp.api.permissions import IsStaffOrReadOnly
@ -32,11 +33,19 @@ class NoteViewSet(viewsets.ViewSet):
def list(self, request, project, jm):
"""
GET method implementation for list view
job_id -- Mandatory filter indicating which job these notes belong to.
"""
job_id = request.QUERY_PARAMS.get('job_id')
objs = jm.get_job_note_list(job_id=job_id)
return Response(objs)
job_id = request.QUERY_PARAMS.get('job_id')
if not job_id:
raise ParseError(detail="The job_id parameter is mandatory for this endpoint")
try:
job_id = int(job_id)
except:
raise ParseError(detail="The job_id parameter must be an integer")
job_note_list = jm.get_job_note_list(job_id=job_id)
return Response(job_note_list)
@with_jobs
def create(self, request, project, jm):
@ -80,4 +89,3 @@ class NoteViewSet(viewsets.ViewSet):
else:
return Response("No note with id: {0}".format(pk), 404)

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

@ -7,8 +7,7 @@ import oauth2 as oauth
from django.conf import settings
from rest_framework.response import Response
from treeherder.model.derived import (JobsModel, DatasetNotFoundError,
ObjectNotFoundException)
from treeherder.model.derived import JobsModel
from treeherder.etl.oauth_utils import OAuthCredentials
@ -185,28 +184,13 @@ def with_jobs(model_func):
``func`` must take a jobsmodel object and return a response object
Catches exceptions
"""
def use_jobs_model(*args, **kwargs):
project = kwargs["project"]
jm = JobsModel(project)
try:
jm = JobsModel(project)
return model_func(*args, jm=jm, **kwargs)
except DatasetNotFoundError as e:
return Response(
{"message": "No project with name {0}".format(project)},
status=404,
)
except ObjectNotFoundException as e:
return Response({"message": unicode(e)}, status=404)
except Exception as e: # pragma nocover
msg = {"message": unicode(e)}
if settings.DEBUG:
import traceback
msg["traceback"] = traceback.format_exc()
return Response(msg, status=500)
finally:
jm.disconnect()