Skip to content

Commit

Permalink
Fix StringIO on py3. Add documentation and missing changelog
Browse files Browse the repository at this point in the history
  • Loading branch information
sneridagh committed Mar 18, 2019
1 parent 8a79f6f commit 2910a7f
Show file tree
Hide file tree
Showing 10 changed files with 124 additions and 2 deletions.
17 changes: 17 additions & 0 deletions docs/source/users.rst
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,23 @@ A successful response to a PATCH request will be indicated by a :term:`204 No Co

Any user is able to update their own properties and password (if allowed) by using the same request.

The user portrait/avatar can also be updated using the same serialization as the file one:

.. http:example:: curl httpie python-requests
:request: ../../src/plone/restapi/tests/http-examples/users_update_portrait.req

A successful response to a PATCH request will be indicated by a :term:`204 No Content` response.
Then asking for the user the portrait URL should be on the response:

.. literalinclude:: ../../src/plone/restapi/tests/http-examples/users_update_portrait_get.resp
:language: http

Adding the portrait via the @user endpoint does not scale it since it's assumed that the frontend will take care of it (resizing/cropping).
If you still want that Plone to take care of the scaling using the default Plone behavior for portraits, you have to add the ``scale`` attribute to the request:

.. http:example:: curl httpie python-requests
:request: ../../src/plone/restapi/tests/http-examples/users_update_portrait_scale.req

Delete User
-----------

Expand Down
2 changes: 2 additions & 0 deletions news/701.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Add support for add/update user portraits (@user endpoint)
[sneridagh]
3 changes: 1 addition & 2 deletions src/plone/restapi/services/users/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from Products.CMFCore.utils import getToolByName
from Products.CMFPlone.utils import set_own_login_name
from Products.PlonePAS.utils import scale_image
from StringIO import StringIO
from zope.component import getAdapter
from zope.component.hooks import getSite
from zope.interface import alsoProvides
Expand Down Expand Up @@ -164,7 +163,7 @@ def set_member_portrait(self, user, portrait):
if portrait.get('scale', False):
# Only scale if the scale (default Plone behavior) boolean is set
# This should be handled by the core in the future
scaled, mimetype = scale_image(StringIO(data))
scaled, mimetype = scale_image(six.StringIO(data))
else:
# Normally, the scale and cropping is going to be handled in the
# frontend
Expand Down
13 changes: 13 additions & 0 deletions src/plone/restapi/tests/http-examples/users_update_portrait.req
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
PATCH /plone/@users/noam HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
Content-Type: application/json

{
"portrait": {
"content-type": "image/png",
"data": "R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=",
"encoding": "base64",
"filename": "image.png"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
HTTP/1.1 204 No Content

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
GET /plone/@users/noam HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
Content-Type: application/json

{
"portrait": {
"content-type": "image/png",
"data": "R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=",
"encoding": "base64",
"filename": "image.png"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
HTTP/1.1 200 OK
Content-Type: application/json

{
"@id": "http://localhost:55001/plone/@users/noam",
"description": null,
"email": "noam.chomsky@example.com",
"fullname": null,
"home_page": null,
"id": "noam",
"location": null,
"portrait": "http://localhost:55001/plone/portal_memberdata/portraits/noam",
"roles": [
"Member"
],
"username": "noam"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
PATCH /plone/@users/noam HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
Content-Type: application/json

{
"portrait": {
"content-type": "image/png",
"data": "R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=",
"encoding": "base64",
"filename": "image.png",
"scale": true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
HTTP/1.1 204 No Content

43 changes: 43 additions & 0 deletions src/plone/restapi/tests/test_documentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,49 @@ def test_documentation_users_update(self):
)
save_request_and_response_for_docs('users_update', response)

def test_documentation_users_update_portrait(self):
payload = {
'portrait': {
'filename': 'image.png',
'encoding': 'base64',
'data': 'R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=',
'content-type': 'image/png'
}
}
api.user.create(
email='noam.chomsky@example.com',
username='noam'
)
transaction.commit()
response = self.api_session.patch('/@users/noam', json=payload)
transaction.commit()

response_get = self.api_session.get('/@users/noam', json=payload)

save_request_and_response_for_docs('users_update_portrait', response)
save_request_and_response_for_docs(
'users_update_portrait_get', response_get)

def test_documentation_users_update_portrait_with_scale(self):
payload = {
'portrait': {
'filename': 'image.png',
'encoding': 'base64',
'data': 'R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=',
'content-type': 'image/png',
'scale': True
}
}
api.user.create(
email='noam.chomsky@example.com',
username='noam'
)
transaction.commit()
response = self.api_session.patch('/@users/noam', json=payload)

save_request_and_response_for_docs(
'users_update_portrait_scale', response)

def test_documentation_users_delete(self):
properties = {
'email': 'noam.chomsky@example.com',
Expand Down

0 comments on commit 2910a7f

Please sign in to comment.