diff options
| author | Xavier Morel <xmo@odoo.com> | 2015-11-25 09:40:34 +0100 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2015-11-30 16:39:13 +0100 |
| commit | 2afb5b43ef0c7aa69b63145052a8d183d3d9d14b (patch) | |
| tree | 106228e7191b04819576cf070b450d27d7bc2f61 /addons/website_form/models/models.py | |
| parent | 2769029eefd9456259c664ea846156fc9bd26a91 (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.py | 66 |
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' + ) |
