Skip to content

Commit

Permalink
Merge pull request #101 from plone/thet-allowedtypesjson
Browse files Browse the repository at this point in the history
allowUpload JSON view, content-type json for all
  • Loading branch information
jensens authored Aug 2, 2016
2 parents f22b950 + cc68354 commit 02be455
Show file tree
Hide file tree
Showing 10 changed files with 129 additions and 10 deletions.
6 changes: 6 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,17 @@ Breaking changes:

New features:

- Add ``@@allow_upload`` view, which returns a JSON string to indicate if File or Image uploads are allowed in the current container.
[thet]

- Factor out the available columns ignored list which can be used to narrow down the available columns list to a user friendly set.
[thet]

Bug fixes:

- Explicitly set ``application/json`` content type for JSON responses and declare an ``utf-8`` charset.
[thet]

- Properly deprecated ``_permissions`` in favor of ``PERMISSIONS``.
Since 3.1, the ``_permissions`` variable was ``None`` instead of a
backwards compatibility alias for ``PERMISSIONS`` due to a wrong
Expand Down
7 changes: 7 additions & 0 deletions plone/app/content/browser/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -180,4 +180,11 @@
permission="zope2.View"
/>

<browser:page
for="*"
name="allow_upload"
class=".file.AllowUploadView"
permission="cmf.AddPortalContent"
/>

</configure>
5 changes: 3 additions & 2 deletions plone/app/content/browser/constraintypes.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# -*- coding: utf-8 -*-
from plone.autoform.form import AutoExtensibleForm
from Products.CMFPlone import PloneMessageFactory as PC_
from Products.CMFPlone.interfaces import ISelectableConstrainTypes
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from plone.autoform.form import AutoExtensibleForm
from z3c.form import button
from z3c.form import form
from z3c.form.browser.checkbox import CheckBoxFieldWidget
from zope.interface import Interface
from zope.interface import implementer
from zope.interface import Interface
from zope.interface import invariant
from zope.interface.exceptions import Invalid
from zope.schema import Choice
Expand All @@ -16,6 +16,7 @@
from zope.schema.vocabulary import SimpleTerm
from zope.schema.vocabulary import SimpleVocabulary


# XXX
# acquire locallyAllowedTypes from parent (default)
ACQUIRE = -1
Expand Down
11 changes: 10 additions & 1 deletion plone/app/content/browser/contents/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,9 @@ def protect(self):
checkpost(self.request)

def json(self, data):
self.request.response.setHeader("Content-Type", "application/json")
self.request.response.setHeader(
'Content-Type', 'application/json; charset=utf-8'
)
return json_dumps(data)

def get_selection(self):
Expand Down Expand Up @@ -283,6 +285,9 @@ def get_options(self):
return options

def __call__(self):
self.request.response.setHeader(
'Content-Type', 'application/json; charset=utf-8'
)
self.options = json_dumps(self.get_options())
return super(FolderContentsView, self).__call__()

Expand Down Expand Up @@ -360,6 +365,10 @@ def __call__(self):
if key == 'path':
val = val[len(base_path):]
item[key] = val

self.request.response.setHeader(
'Content-Type', 'application/json; charset=utf-8'
)
return json_dumps({
'addButtons': factories,
'defaultPage': self.context.getDefaultPage(),
Expand Down
4 changes: 3 additions & 1 deletion plone/app/content/browser/contents/delete.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ def __call__(self):
catalog = getToolByName(self.context, 'portal_catalog')
brains = catalog(UID=selection)
items = [i.getObject() for i in brains]
self.request.response.setHeader('Content-Type', 'application/json')
self.request.response.setHeader(
'Content-Type', 'application/json; charset=utf-8'
)
return json.dumps({
'html': confirm_view(items)
})
Expand Down
31 changes: 28 additions & 3 deletions plone/app/content/browser/file.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
# -*- coding: utf-8 -*-
from AccessControl import getSecurityManager
from Products.CMFCore.utils import getToolByName
from Products.CMFPlone.permissions import AddPortalContent
from Products.Five.browser import BrowserView
from plone.app.dexterity.interfaces import IDXFileFactory
from plone.dexterity.interfaces import IDexterityFTI
from plone.uuid.interfaces import IUUID
from Products.CMFCore.utils import getToolByName
from Products.CMFPlone.permissions import AddPortalContent
from Products.Five.browser import BrowserView

import json
import logging
import mimetypes
import os


logger = logging.getLogger('plone')


Expand Down Expand Up @@ -187,4 +189,27 @@ def __call__(self):
'UID': IUUID(obj),
'filename': filename
})

self.request.response.setHeader(
'Content-Type', 'application/json; charset=utf-8'
)
return json.dumps(result)


class AllowUploadView(BrowserView):

def __call__(self):
"""Return JSON structure to indicate if File or Image uploads are
allowed in the current container.
"""
self.request.response.setHeader(
'Content-Type', 'application/json; charset=utf-8'
)
allowed_types = [t.getId() for t in self.context.allowedContentTypes()]
allow_images = u'Image' in allowed_types
allow_files = u'File' in allowed_types
return json.dumps({
'allowUpload': allow_images or allow_files,
'allowImages': allow_images,
'allowFiles': allow_files
})
2 changes: 1 addition & 1 deletion plone/app/content/browser/i18n.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ def __call__(self, domain, language=None):

catalog = self._gettext_catalog(domain, language)
response = self.request.response
response.setHeader('content-type', 'application/json')
response.setHeader('Content-Type', 'application/json; charset=utf-8')
response.setBody(json.dumps(catalog))
return response
4 changes: 3 additions & 1 deletion plone/app/content/browser/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,7 @@ class QueryStringIndexOptions(BrowserView):
def __call__(self):
registry = getUtility(IRegistry)
config = IQuerystringRegistryReader(registry)()
self.request.response.setHeader("Content-Type", "application/json")
self.request.response.setHeader(
'Content-Type', 'application/json; charset=utf-8'
)
return json.dumps(config)
4 changes: 3 additions & 1 deletion plone/app/content/browser/vocabulary.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,9 @@ def __call__(self):
}
"""
context = self.get_context()
self.request.response.setHeader("Content-type", "application/json")
self.request.response.setHeader(
'Content-Type', 'application/json; charset=utf-8'
)

try:
vocabulary = self.get_vocabulary()
Expand Down
65 changes: 65 additions & 0 deletions plone/app/content/tests/test_contents.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,68 @@ def test_paste_fail_constraint(self):
res = json.loads(res)
self.assertEqual(res['status'], 'warning')
self.assertEqual(len(self.portal.it1.contentIds()), 0)


class AllowUploadViewTests(unittest.TestCase):
layer = PLONE_APP_CONTENT_DX_INTEGRATION_TESTING

def setUp(self):
self.portal = self.layer['portal']
self.request = self.layer['request']

# TYPE 1
type1_fti = DexterityFTI('type1')
type1_fti.klass = 'plone.dexterity.content.Container'
type1_fti.filter_content_types = True
type1_fti.allowed_content_types = []
type1_fti.behaviors = (
'plone.app.dexterity.behaviors.metadata.IBasic'
)
self.portal.portal_types._setObject('type1', type1_fti)
self.type1_fti = type1_fti

login(self.portal, TEST_USER_NAME)
setRoles(self.portal, TEST_USER_ID, ['Manager'])

self.portal.invokeFactory('type1', id='it1', title='Item 1')

def test_allow_upload(self):
"""Test, if file or images are allowed in a container in different FTI
configurations.
"""

# Test none allowed
self.type1_fti.allowed_content_types = []
allow_upload = self.portal.it1.restrictedTraverse('@@allow_upload')
allow_upload = json.loads(allow_upload())

self.assertEqual(allow_upload['allowUpload'], False)
self.assertEqual(allow_upload['allowImages'], False)
self.assertEqual(allow_upload['allowFiles'], False)

# Test images allowed
self.type1_fti.allowed_content_types = ['Image']
allow_upload = self.portal.it1.restrictedTraverse('@@allow_upload')
allow_upload = json.loads(allow_upload())

self.assertEqual(allow_upload['allowUpload'], True)
self.assertEqual(allow_upload['allowImages'], True)
self.assertEqual(allow_upload['allowFiles'], False)

# Test files allowed
self.type1_fti.allowed_content_types = ['File']
allow_upload = self.portal.it1.restrictedTraverse('@@allow_upload')
allow_upload = json.loads(allow_upload())

self.assertEqual(allow_upload['allowUpload'], True)
self.assertEqual(allow_upload['allowImages'], False)
self.assertEqual(allow_upload['allowFiles'], True)

# Test images and files allowed
self.type1_fti.allowed_content_types = ['Image', 'File']
allow_upload = self.portal.it1.restrictedTraverse('@@allow_upload')
allow_upload = json.loads(allow_upload())

self.assertEqual(allow_upload['allowUpload'], True)
self.assertEqual(allow_upload['allowImages'], True)
self.assertEqual(allow_upload['allowFiles'], True)

0 comments on commit 02be455

Please sign in to comment.