Skip to content

Commit

Permalink
Merge pull request #41 from davidbgk/40-better-api-doc
Browse files Browse the repository at this point in the history
Adding API documentation related to PUT and DELETE, fixes #40
  • Loading branch information
davidbgk committed Jun 2, 2015
2 parents dd7f661 + 454cf55 commit b0279a4
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 49 deletions.
7 changes: 4 additions & 3 deletions udata/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ def page_parser(self):
return parser


api = UDataApi(apiv1, ui=False,
api = UDataApi(
apiv1, ui=False,
decorators=[csrf.exempt, cors.crossdomain(origin='*', credentials=True)],
version='1.0', title='uData API',
description='uData API', default='site', default_label='Site global namespace'
Expand All @@ -150,8 +151,9 @@ def set_api_language():

@api.errorhandler(PermissionDenied)
def handle_permission_denied(error):
message = 'You do not have the permission to modify that object.'
return {
'message': str(error),
'message': message,
'status': 403
}, 403

Expand Down Expand Up @@ -259,7 +261,6 @@ def delete(self, **kwargs):
}, description='Base model for reference field, aka. inline model reference')



def marshal_page(page, page_fields):
return api.marshal(page, fields.pager(page_fields))

Expand Down
13 changes: 3 additions & 10 deletions udata/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,23 +31,16 @@ def __init__(self, *needs):
'''Let administrator bypass all permissions'''
super(Permission, self).__init__(RoleNeed('admin'), *needs)

# def require(self, http_exception=403):
# '''Set the default status code to 403 Forbidden'''
# return super(Permission, self).require(http_exception)

# def test(self, http_exception=403):
# '''Set the default status code to 403 Forbidden'''
# return super(Permission, self).test(http_exception)

admin_permission = Permission()


@bp.before_app_request
def ensure_https_authenticated_users():
# Force authenticated users to use https
if (not current_app.config.get('TESTING', False)
and current_app.config.get('USE_SSL', False)
and current_user.is_authenticated() and not request.is_secure):
and current_app.config.get('USE_SSL', False)
and current_user.is_authenticated()
and not request.is_secure):
return redirect(request.url.replace('http://', 'https://'))


Expand Down
41 changes: 8 additions & 33 deletions udata/core/organization/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ def get(self, org):

@api.secure
@api.doc('update_organization')
@api.marshal_with(org_fields)
@api.response(400, 'Validation error')
def put(self, org):
'''Update a organization given its identifier'''
Expand All @@ -91,8 +92,11 @@ def delete(self, org):


requests_parser = api.parser()
requests_parser.add_argument('status', type=unicode,
help='If provided, only return requests ith a given status', location='args'
requests_parser.add_argument(
'status',
type=unicode,
help='If provided, only return requests ith a given status',
location='args'
)


Expand Down Expand Up @@ -164,8 +168,8 @@ def post(self, org, id):


refuse_parser = api.parser()
refuse_parser.add_argument('comment', type=unicode,
help='The refusal reason', location='json'
refuse_parser.add_argument(
'comment', type=unicode, help='The refusal reason', location='json'
)


Expand Down Expand Up @@ -268,7 +272,6 @@ def get(self):
]



logo_parser = api.parser()
logo_parser.add_argument('file', type=FileStorage, location='files')
logo_parser.add_argument('bbox', type=str, location='form')
Expand Down Expand Up @@ -299,34 +302,6 @@ def put(self, org):
'''Set the logo BBox'''
EditOrganizationPermission(org).test()
args = logo_parser.parse_args()

print args
logo = args['file']

org.logo.save(logo, bbox=args.get('bbox'))

return org

# storage = storages.logo

# prefix = self.get_prefix(dataset)

# filename = storage.save(file, prefix=prefix)

# extension = fileutils.extension(filename)

# file.seek(0)
# sha1 = storages.utils.sha1(file)

# size = os.path.getsize(storage.path(filename)) if storage.root else None

# resource = Resource(
# title=os.path.basename(filename),
# url=storage.url(filename, external=True),
# checksum=Checksum(value=sha1),
# format=extension,
# mime=storages.utils.mime(filename),
# size=size
# )
# dataset.add_resource(resource)
# return resource, 201
76 changes: 73 additions & 3 deletions udata/templates/apidoc.html
Original file line number Diff line number Diff line change
Expand Up @@ -280,15 +280,85 @@ <h3>{% trans %}Modifying and deleting data{% endtrans %}</h3>
<pre><code class="json">$ http PUT $API'organizations/premier-ministre/' X-API-KEY:your.api.key.here</code></pre>

<pre><code class="json">
HTTP/1.1 400 BAD REQUEST
HTTP/1.1 401 UNAUTHORIZED
... LOTS OF HEADERS ...

{
"message": "Invalid API Key",
"status": 401
}
</code></pre>

<p>{% trans %}This is the message you will end up with if you specified the wrong API Key. There is another potential error message that you can encounter:
{% endtrans %}</p>

<pre><code class="json">
HTTP/1.1 403 FORBIDDEN
... LOTS OF HEADERS ...

{
"message": "Bad Request",
"status": 400
"message": "You do not have the permission to modify that object.",
"status": 403
}
</code></pre>

<p>{% trans %}It occurs if you try to access a resource that you cannot edit with your credentials. If your Key is valid you should have something like this:
{% endtrans %}</p>


<pre><code class="json">
HTTP/1.1 200 OK
... LOTS OF HEADERS ...

{
...
}
</code></pre>

<p>{% trans %}But it didn't change anything! This is perfectly normal, we forgot to specify the right data to send to the server.
{% endtrans %}</p>

<pre><code class="json">$ http PUT $API'organizations/premier-ministre/' X-API-KEY:your.api.key.here name="Premier ministre fr" description="Administration du Premier ministre." | jq '{name: .name, description: .description}'</code></pre>

<pre><code class="json">
{
"name": "Premier ministre fr",
"description": "Administration du Premier ministre."
}
</code></pre>

<p>{% trans %}The resource has been modified with your new values. Finally, you can delete a resource with the appropriated HTTP verb (beware, no rollback is possible using the API at the moment):
{% endtrans %}</p>


<pre><code class="json">$ http DELETE $API'organizations/premier-ministre/' X-API-KEY:your.api.key.here</code></pre>

<pre><code class="json">
HTTP/1.0 204 NO CONTENT
... LOTS OF HEADERS ...

</code></pre>

<p>{% trans %}Once you did it, you can verify that it's effective issuing a GET against the previous URI:
{% endtrans %}</p>


<pre><code class="json">$ http GET $API'organizations/premier-ministre/'</code></pre>

<pre><code class="json">
HTTP/1.0 410 GONE
... LOTS OF HEADERS ...

{
"message": "Organization has been deleted",
"status": 410
}

</code></pre>

<p>{% trans %}Please consult the reference documentation below for further interactions with the API or ask us for questions related to it!
{% endtrans %}</p>

</div>
</div>

Expand Down

0 comments on commit b0279a4

Please sign in to comment.