Commit eb30b76f authored by Tomáš Peterka's avatar Tomáš Peterka

[hal_json] Restrict Reports in callDialogMethod for skins Hal and OOx

parent 8d9575de
......@@ -6,26 +6,25 @@ from Products.ERP5Type.Log import log, DEBUG, INFO, WARNING
# XXX We should not use meta_type properly,
# XXX We need to discuss this problem.(yusei)
def isListBox(field):
if field.meta_type=='ListBox':
return True
elif field.meta_type=='ProxyField':
template_field = field.getRecursiveTemplateField()
if template_field.meta_type=='ListBox':
return True
return False
from Products.Formulator.Errors import FormValidationError
def isFieldType(field, type_name):
if field.meta_type == 'ProxyField':
field = field.getRecursiveTemplateField()
return field.meta_type == type_name
from Products.Formulator.Errors import FormValidationError, ValidationError
from ZTUtils import make_query
request = REQUEST
if REQUEST is None:
request = container.REQUEST
# request.form holds POST data thus containing 'field_' + field.id items
# such as 'field_your_some_field'
request_form = request.form
error_message = ''
translate = context.Base_translateString
# Make this script work alike wether called from another script or by a request
# Make this script work alike no matter if called by a script or a request
kw.update(request_form)
# Exceptions for UI
......@@ -63,6 +62,7 @@ if dialog_method == 'Base_editRelation':
listbox_uid=kw.get('listbox_uid', None),
saved_form_data=kw['saved_form_data'])
# Exception for create relation
# Not used in new UI - relation field implemented using JIO calls from JS
if dialog_method == 'Base_createRelation':
return context.Base_createRelation(form_id=kw['form_id'],
selection_name=kw['list_selection_name'],
......@@ -80,6 +80,25 @@ if dialog_method == 'Folder_delete':
selection_name=kw['selection_name'],
md5_object_uid_list=kw['md5_object_uid_list'])
def handleFormError(form, validation_errors):
"""Return correctly rendered form with all errors assigned to its fields."""
field_errors = form.ErrorFields(validation_errors)
# Pack errors into the request
request.set('field_errors', field_errors)
# Make sure editors are pushed back as values into the REQUEST object
for f in form.get_fields():
field_id = f.id
if request.has_key(field_id):
value = request.get(field_id)
if callable(value):
value(request)
if silent_mode:
return context.ERP5Document_getHateoas(form=form, REQUEST=request, mode='form'), 'form'
request.RESPONSE.setStatus(400)
return context.ERP5Document_getHateoas(form=form, REQUEST=request, mode='form')
form = getattr(context, dialog_id)
# form can be a python script that returns the form
......@@ -95,54 +114,54 @@ try:
request.set('editable_mode', 1)
form.validate_all_to_request(request)
request.set('editable_mode', editable_mode)
except FormValidationError, validation_errors:
# Pack errors into the request
field_errors = form.ErrorFields(validation_errors)
request.set('field_errors', field_errors)
# Make sure editors are pushed back as values into the REQUEST object
for f in form.get_fields():
field_id = f.id
if request.has_key(field_id):
value = request.get(field_id)
if callable(value):
value(request)
if silent_mode: return context.ERP5Document_getHateoas(form=form, REQUEST=request, mode='form'), 'form'
request.RESPONSE.setStatus(400)
return context.ERP5Document_getHateoas(form=form, REQUEST=request, mode='form')
# Use REQUEST.redirect if possible. It will not be possible if at least one of these is true :
# * we got an import_file,
# * we got a listbox
# * a value is None or [] or (), because this is not supported by make_query
can_redirect = 1
default_skin = context.getPortalObject().portal_skins.getDefaultSkin()
allowed_styles = ("ODT", "ODS", "Hal", "HalRestricted")
if getattr(getattr(context, dialog_method), 'pt', None) == "report_view" and \
request.get('your_portal_skin', default_skin) not in allowed_styles:
# RJS own validation - only ODS/ODT and Hal* skins work for reports
# Form is OK, it's just this field - style so we return back form-wide error
# for which we don't have support out-of-the-box thus we manually craft it
# XXX TODO: Form-wide validation errors
return handleFormError(
form,
FormValidationError([
ValidationError(
error_key=None,
field=form.get_field('your_portal_skin'),
error_text=translate(
'Only ODT, ODS, Hal and HalRestricted skins are allowed for reports '\
'in Preferences - User Interface - Report Style'))
], {}))
except FormValidationError as validation_errors:
return handleFormError(form, validation_errors)
MARKER = [] # A recognisable default value. Use with 'is', not '=='.
listbox_id_list = [] # There should not be more than one listbox - but this give us a way to check.
file_id_list = [] # For uploaded files.
for field in form.get_fields():
k = field.id
v = request.get(k, MARKER)
if v is not MARKER:
if isListBox(field):
listbox_id_list.append(k)
elif can_redirect and (v in (None, [], ()) or hasattr(v, 'read')) : # If we cannot redirect, useless to test it again
can_redirect = 0
# Cleanup my_ and your_ prefixes
splitted = k.split('_', 1)
if len(splitted) == 2 and splitted[0] in ('my', 'your'):
if hasattr(v, 'as_dict'):
# This is an encapsulated editor
# convert it
kw.update(v.as_dict())
field_id = field.id
field_value = request.get(field_id, MARKER)
if field_value is not MARKER:
if isFieldType(field, "ListBox"):
listbox_id_list.append(field_id)
# Cleanup my_ and your_ prefixes if present
if field_id.startswith("my_") or field_id.startswith("your_"):
_, field_name = field_id.split('_', 1)
if hasattr(field_value, 'as_dict'):
# This is an encapsulated editor - convert it
kw.update(field_value.as_dict())
else:
kw[splitted[1]] = request_form[splitted[1]] = v
kw[field_name] = request_form[field_name] = field_value
else:
kw[k] = request_form[k] = v
kw[field_id] = request_form[field_id] = field_value
if len(listbox_id_list):
can_redirect = 0
# Warn if there are more than one listbox in form ...
if len(listbox_id_list) > 1:
log('Base_callDialogMethod', 'There are %s listboxes in form %s.' % (len(listbox_id_list), form.id))
......@@ -183,21 +202,33 @@ if listbox_uid is not None and kw.has_key('list_selection_name'):
selected_uids = context.portal_selections.updateSelectionCheckedUidList(
kw['list_selection_name'],
listbox_uid, uids)
# Remove unused parameter
clean_kw = {}
for k, v in kw.items() :
if v not in (None, [], ()) :
clean_kw[k] = kw[k]
# Remove empty values for make_query.
clean_kw = dict((k, v) for k, v in kw.items() if v not in (None, [], ()))
# Handle deferred style, unless we are executing the update action
if dialog_method != update_method and clean_kw.get('deferred_style', 0):
clean_kw['deferred_portal_skin'] = clean_kw.get('portal_skin', None)
# XXX Hardcoded Deferred style name
clean_kw['portal_skin'] = 'Deferred'
dialog_form = getattr(context, dialog_method)
page_template = getattr(dialog_form, 'pt', None)
# If the action form has report_view as it's method, it
page_template = getattr(getattr(context, dialog_method), 'pt', None)
if page_template == 'report_view':
# Limit Reports in Deferred style to known working styles
if request_form.get('your_portal_skin', None) not in ("ODT", "ODS"):
# RJS own validation - deferred option works here only with ODS/ODT skins
return handleFormError(
form,
FormValidationError([
ValidationError(
error_key=None,
field=form.get_field('your_deferred_style'),
error_text=translate(
'Deferred reports are possible only with preference '\
'"Report Style" set to "ODT" or "ODS"'))
], {}))
# If the action form has report_view as it's method, it
if page_template != 'report_view':
# use simple wrapper
clean_kw['deferred_style_dialog_method'] = dialog_method
......@@ -205,14 +236,13 @@ if dialog_method != update_method and clean_kw.get('deferred_style', 0):
request.set('deferred_style_dialog_method', dialog_method)
dialog_method = 'Base_activateSimpleView'
url_params_string = make_query(clean_kw)
# XXX: We always redirect in report mode to make sure portal_skin
# parameter is taken into account by SkinTool.
# If url is too long, we do not redirect to avoid crash.
# XXX: 2000 is an arbitrary value resulted from trial and error.
if (not(can_redirect) or len(url_params_string) > 2000):
# Never redirect in JSON style - do as much as possible here.
# At this point the 'dialog_method' should point to a form (if we are in report)
# if we are not in Deferred mode - then it points to `Base_activateSimpleView`
if True:
if dialog_method != update_method:
# When we are not executing the update action, we have to change the skin
# manually,
......@@ -222,6 +252,7 @@ if (not(can_redirect) or len(url_params_string) > 2000):
request.set('portal_skin', new_skin_name)
deferred_portal_skin = clean_kw.get('deferred_portal_skin')
if deferred_portal_skin:
# has to be either ODS or ODT because only those contain `form_list`
request.set('deferred_portal_skin', deferred_portal_skin)
# and to cleanup formulator's special key in request
# XXX unless we are in Folder_modifyWorkflowStatus which validates again !
......@@ -230,15 +261,28 @@ if (not(can_redirect) or len(url_params_string) > 2000):
if str(key).startswith('field') or str(key).startswith('subfield'):
request.form.pop(key, None)
# If we cannot redirect, then call the form directly.
dialog_form = getattr(context, dialog_method)
# XXX: this is a hack that should not be needed anymore with the new listbox.
# set the URL in request, so that we can immediatly call method
# that depend on it (eg. Show All). This is really related to
# current ListBox implementation which edit Selection's last_url
# with the content of REQUEST.URL
request.set('URL', '%s/%s' % (context.absolute_url(), dialog_method))
return dialog_form(**kw)
dialog_method = getattr(context, dialog_method)
return dialog_method(**clean_kw)
# now get dialog_method after skin re-selection and dialog_method mingling
dialog_form = getattr(context, dialog_method)
# XXX: this is a hack that should not be needed anymore with the new listbox.
# set the URL in request, so that we can immediatly call method
# that depend on it (eg. Show All). This is really related to
# current ListBox implementation which edit Selection's last_url
# with the content of REQUEST.URL
request.set('URL', '%s/%s' % (context.absolute_url(), dialog_method))
# RJS: If we are in deferred mode - call the form directly and return
# dialog method is now `Base_activateSimpleView` - the only script in
# deferred portal_skins folder
if clean_kw.get('deferred_style', 0):
return dialog_form(**kw) # deferred form should return redirect with a message
# RJS: If skin selection is different than Hal* then ERP5Document_getHateoas
# does not exist and we call form method directly
if clean_kw.get("portal_skin", context.getPortalObject().portal_skins.getDefaultSkin()) not in ("Hal", "HalRestricted"):
return dialog_form(**kw)
return context.ERP5Document_getHateoas(REQUEST=request, form=dialog_form, mode="form")
# XXX If somebody knows in which case this gets executed ... please tell me.
return getattr(context, dialog_method)(**kw)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment