Skip to content
This repository has been archived by the owner on Mar 28, 2019. It is now read-only.

Commit

Permalink
Merge pull request #11 from mozilla-services/11-implement-delete
Browse files Browse the repository at this point in the history
Implement DELETE
  • Loading branch information
almet committed Sep 3, 2015
2 parents 47abcda + 5f40cb5 commit 97eb29b
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 26 deletions.
10 changes: 2 additions & 8 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
REQUIREMENTS = [
'waitress',
'cliquet[postgresql,monitoring]',
'fxsync-client>=0.0.1'
'syncclient'
]

if PY2:
Expand All @@ -30,11 +30,6 @@
'main = syncto:main',
]}

DEPENDENCY_LINKS = [
"https://github.com/mozilla-services/syncclient/tarball/master"
"#egg=fxsync-client-0.0.1"
]

setup(name='syncto',
version='1.0.0.dev0',
description='Read Firefox Sync server using Kinto API.',
Expand All @@ -54,5 +49,4 @@
include_package_data=True,
zip_safe=False,
install_requires=REQUIREMENTS,
entry_points=ENTRY_POINTS,
dependency_links=DEPENDENCY_LINKS)
entry_points=ENTRY_POINTS)
20 changes: 2 additions & 18 deletions syncto/authentication.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
from pyramid import httpexceptions
from pyramid.security import forget
from requests.exceptions import HTTPError

from cliquet.errors import http_error, ERRORS
from cliquet.views.errors import service_unavailable
from sync.client import SyncClient
from syncclient.client import SyncClient

from syncto import AUTHORIZATION_HEADER, CLIENT_STATE_HEADER

Expand Down Expand Up @@ -40,19 +38,5 @@ def build_sync_client(request):

bid_assertion = authorization_header.split(" ", 1)[1]
client_state = request.headers[CLIENT_STATE_HEADER]
try:
sync_client = SyncClient(bid_assertion, client_state)
except HTTPError as e:
if e.response.status_code in (400, 401):
message = '%s %s: %s' % (e.response.status_code,
e.response.reason,
e.response.text)
response = http_error(httpexceptions.HTTPUnauthorized(),
errno=ERRORS.INVALID_AUTH_TOKEN,
message=message)
# Forget the current user credentials.
response.headers.extend(forget(request))
raise response
else:
raise service_unavailable(e, request)
sync_client = SyncClient(bid_assertion, client_state)
return sync_client
32 changes: 32 additions & 0 deletions syncto/tests/test_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,3 +184,35 @@ def setUp(self):
def test_record_handle_cors_headers(self):
resp = self.app.get(RECORD_URL, headers=self.headers, status=200)
self.assertIn('Access-Control-Allow-Origin', resp.headers)

def test_can_delete_record(self):
self.sync_client.return_value.delete_record.return_value = None
self.app.delete(RECORD_URL, headers=self.headers, status=204)

def test_delete_return_a_503_in_case_of_unknown_error(self):
response = mock.MagicMock()
response.status_code = 500
self.sync_client.return_value.delete_record.side_effect = HTTPError(
response=response)
self.app.delete(RECORD_URL, headers=self.headers, status=503)

def test_delete_return_a_400_in_case_of_bad_request(self):
response = mock.MagicMock()
response.status_code = 400
self.sync_client.return_value.delete_record.side_effect = HTTPError(
response=response)
self.app.delete(RECORD_URL, headers=self.headers, status=400)

def test_delete_return_a_403_in_case_of_forbidden_resource(self):
response = mock.MagicMock()
response.status_code = 403
self.sync_client.return_value.delete_record.side_effect = HTTPError(
response=response)
self.app.delete(RECORD_URL, headers=self.headers, status=403)

def test_delete_return_a_404_in_case_of_unknown_resource(self):
response = mock.MagicMock()
response.status_code = 404
self.sync_client.return_value.delete_record.side_effect = HTTPError(
response=response)
self.app.delete(RECORD_URL, headers=self.headers, status=404)
41 changes: 41 additions & 0 deletions syncto/views/errors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from pyramid import httpexceptions
from pyramid.security import NO_PERMISSION_REQUIRED, forget
from pyramid.view import view_config
from requests.exceptions import HTTPError

from cliquet import logger
from cliquet.errors import http_error, ERRORS
from cliquet.utils import reapply_cors
from cliquet.views.errors import service_unavailable


@view_config(context=HTTPError, permission=NO_PERMISSION_REQUIRED)
def error(context, request):
"""Catch server errors and trace them."""
logger.error(context, exc_info=True)

message = '%s %s: %s' % (context.response.status_code,
context.response.reason,
context.response.text)
if context.response.status_code == 400:
response = http_error(httpexceptions.HTTPBadRequest(),
errno=ERRORS.INVALID_PARAMETERS,
message=message)
elif context.response.status_code == 401:
response = http_error(httpexceptions.HTTPUnauthorized(),
errno=ERRORS.INVALID_AUTH_TOKEN,
message=message)
# Forget the current user credentials.
response.headers.extend(forget(request))
elif context.response.status_code == 403:
response = http_error(httpexceptions.HTTPForbidden(),
errno=ERRORS.FORBIDDEN,
message=message)
elif context.response.status_code == 404:
response = http_error(httpexceptions.HTTPNotFound(),
errno=ERRORS.INVALID_RESOURCE_ID,
message=message)
else:
response = service_unavailable(context, request)

return reapply_cors(request, response)
14 changes: 14 additions & 0 deletions syncto/views/record.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,17 @@ def record_get(request):
convert_headers(sync_client.raw_resp, request.response)

return {'data': record}


@record.delete(permission=NO_PERMISSION_REQUIRED)
def record_delete(request):
collection_name = request.matchdict['collection_name']
record_id = request.matchdict['record_id']
sync_id = uuid4_to_base64(record_id)

sync_client = build_sync_client(request)
sync_client.delete_record(collection_name, sync_id)

request.response.status_code = 204
del request.response.headers['Content-Type']
return request.response

0 comments on commit 97eb29b

Please sign in to comment.