summaryrefslogtreecommitdiff
path: root/addons/website_form/models/models.py
diff options
context:
space:
mode:
authorXavier Morel <xmo@odoo.com>2015-11-25 09:40:34 +0100
committerChristophe Simonis <chs@odoo.com>2015-11-30 16:39:13 +0100
commit2afb5b43ef0c7aa69b63145052a8d183d3d9d14b (patch)
tree106228e7191b04819576cf070b450d27d7bc2f61 /addons/website_form/models/models.py
parent2769029eefd9456259c664ea846156fc9bd26a91 (diff)
[IMP] form builder fields blacklisting
* blacklist all fields by default * don't use blacklist in get_authorized_fields which is called to see if a field can be added to a form, instead only use it afterwards to see if the field can be written to by the formbuilder. That way formbuilder can whitelist fields which are actually added to forms on-demand resulting in a more secure interaction
Diffstat (limited to 'addons/website_form/models/models.py')
-rw-r--r--addons/website_form/models/models.py66
1 files changed, 60 insertions, 6 deletions
diff --git a/addons/website_form/models/models.py b/addons/website_form/models/models.py
index e6e769f59e5..b1a2934e3f5 100644
--- a/addons/website_form/models/models.py
+++ b/addons/website_form/models/models.py
@@ -1,3 +1,5 @@
+import itertools
+
from openerp import tools
from openerp import models, fields, api
@@ -16,18 +18,36 @@ class website_form_model(models.Model):
website_form_default_field_id = fields.Many2one('ir.model.fields', 'Field for custom form data', domain="[('model', '=', model), ('ttype', '=', 'text')]", help="Specify the field wich will contain meta and custom form fields datas.")
website_form_label = fields.Char("Label for form action", help="Form action label. Ex: crm.lead could be 'Send an e-mail' and project.issue could be 'Create an Issue'.")
+ def _all_inherited_model_ids(self):
+ return list(itertools.chain(
+ [self.id],
+ *(m._all_inherited_model_ids() for m in self.inherited_model_ids)
+ ))
- def all_inherited_model_ids(self):
- return [self.id] + [m.all_inherited_model_ids() for m in self.inherited_model_ids]
+ def _get_form_writable_fields(self):
+ """
+ Restriction of "authorized fields" (fields which can be used in the
+ form builders) to fields which have actually been opted into form
+ builders and are writable. By default no field is writable by the
+ form builder.
+ """
+ excluded = {
+ field.name
+ for field in self.env['ir.model.fields'].sudo().search([
+ ('model_id', 'in', self._all_inherited_model_ids()),
+ ('website_form_blacklisted', '=', True)
+ ])
+ }
+ return {
+ k: v for k, v in self.get_authorized_fields().iteritems()
+ if k not in excluded
+ }
@api.multi
def get_authorized_fields(self):
model = self.env[self.model]
fields_get = model.fields_get()
- for elem in self.env['ir.model.fields'].search([('model_id', 'in', self.all_inherited_model_ids())]):
- if elem.website_form_blacklisted:
- fields_get.pop(elem.name, None)
for key, val in model._inherits.iteritems():
fields_get.pop(val,None)
@@ -49,4 +69,38 @@ class website_form_model_fields(models.Model):
_name = 'ir.model.fields'
_inherit = 'ir.model.fields'
- website_form_blacklisted = fields.Boolean('Blacklisted in web forms', help='Blacklist this field for web forms')
+ def init(self, cr):
+ # set all existing unset website_form_blacklisted fields to ``true``
+ # (so that we can use it as a whitelist rather than a blacklist)
+ cr.execute('UPDATE ir_model_fields'
+ ' SET website_form_blacklisted=true'
+ ' WHERE website_form_blacklisted IS NULL')
+ # add an SQL-level default value on website_form_blacklisted to that
+ # pure-SQL ir.model.field creations (e.g. in _field_create) generate
+ # the right default value for a whitelist (aka fields should be
+ # blacklisted by default)
+ cr.execute('ALTER TABLE ir_model_fields '
+ ' ALTER COLUMN website_form_blacklisted SET DEFAULT true')
+
+ @api.model
+ def formbuilder_whitelist(self, model, fields):
+ """
+ :param str model: name of the model on which to whitelist fields
+ :param list(str) fields: list of fields to whitelist on the model
+ :return: nothing of import
+ """
+ # todo: check access rights yo
+ # the ORM only allows writing on custom fields and will trigger a
+ # registry reload once that's happened. We want to be able to
+ # whitelist non-custom fields and the registry reload absolutely
+ # isn't desirable, so go with a method and raw SQL
+ self.env.cr.execute(
+ "UPDATE ir_model_fields"
+ " SET website_form_blacklisted=false"
+ " WHERE model=%s AND name in %s", (model, tuple(fields)))
+ return False
+
+ website_form_blacklisted = fields.Boolean(
+ 'Blacklisted in web forms', default=True, select=True, # required=True,
+ help='Blacklist this field for web forms'
+ )