Browse Source

[FIX] restrict exports and read_group

* Add implementation for restricted exporting and grouping

* Use original __export_rows() for models not using the mixin

* Assume all fields if not specified, like in original read_group()

* Return inaccessible fields in read_group() with null values

* No need to remove 'restrict_field_access'
pull/396/head
Danny Adair 8 years ago
committed by Holger Brunn
parent
commit
536adf4055
No known key found for this signature in database GPG Key ID: 1C9760FECA3AE18
  1. 97
      base_mixin_restrict_field_access/models/restrict_field_access_mixin.py

97
base_mixin_restrict_field_access/models/restrict_field_access_mixin.py

@ -4,6 +4,8 @@
import json
from lxml import etree
from openerp import _, api, fields, models, SUPERUSER_ID
from openerp.addons.web.controllers.main import Export
from openerp.http import request
from openerp.osv import expression # pylint: disable=W0402
@ -11,8 +13,6 @@ class RestrictFieldAccessMixin(models.AbstractModel):
"""Mixin to restrict access to fields on record level"""
_name = 'restrict.field.access.mixin'
# TODO: read_group, __export_rows, everything that was forgotten
@api.multi
def _compute_restrict_field_access(self):
"""determine if restricted field access is active on records.
@ -72,6 +72,85 @@ class RestrictFieldAccessMixin(models.AbstractModel):
self._fields[field].null(self.env))
return result
def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False, lazy=True):
"""
Remove inaccessible fields from 'fields', 'groupby' and 'orderby'.
If this removes all 'fields', return no records.
If this removes all 'groupby', group by first remaining field.
If this removes 'orderby', don't specify order.
"""
requested_fields = fields or self._columns.keys()
sanitised_fields = [
f for f in requested_fields if self._restrict_field_access_is_field_accessible(
cr, uid, [], f
)
]
if not sanitised_fields:
return []
sanitised_groupby = []
groupby = [groupby] if isinstance(groupby, basestring) else groupby
for groupby_part in groupby:
groupby_field = groupby_part.split(':')[0]
if self._restrict_field_access_is_field_accessible(cr, uid, [], groupby_field):
sanitised_groupby.append(groupby_part)
if not sanitised_groupby:
sanitised_groupby.append(sanitised_fields[0])
if orderby:
sanitised_orderby = []
for orderby_part in orderby.split(','):
orderby_field = orderby_part.split()[0]
if self._restrict_field_access_is_field_accessible(cr, uid, [], orderby_field):
sanitised_orderby.append(orderby_part)
sanitised_orderby = sanitised_orderby and ','.join(sanitised_orderby) or False
else:
sanitised_orderby = False
result = super(RestrictFieldAccessMixin, self).read_group(
cr,
uid,
domain,
sanitised_fields,
sanitised_groupby,
offset=offset,
limit=limit,
context=context,
orderby=sanitised_orderby,
lazy=lazy
)
# Add inaccessible fields back in with null values
inaccessible_fields = [f for f in requested_fields if f not in sanitised_fields]
for field_name in inaccessible_fields:
field = self._columns[field_name]
if lazy:
result.append(
{
'__domain': [(True, '=', True)],
field_name: field.null(self.env),
field_name + '_count': 0L
}
)
else:
result.append(
{
'__domain': [(True, '=', True)],
field_name: field.null(self.env),
'__count': 0L
}
)
return result
@api.multi
def _BaseModel__export_rows(self, fields):
"""Don't export inaccessible fields"""
if isinstance(self, RestrictFieldAccessMixin):
sanitised_fields = [f for f in fields if f and self._restrict_field_access_is_field_accessible(f[0])]
return super(RestrictFieldAccessMixin, self)._BaseModel__export_rows(sanitised_fields)
else:
return super(RestrictFieldAccessMixin, self)._BaseModel__export_rows(fields)
@api.multi
def write(self, vals):
for this in self:
@ -229,3 +308,17 @@ class RestrictFieldAccessMixin(models.AbstractModel):
whitelist = self._restrict_field_access_get_field_whitelist(
action=action)
return field_name in whitelist
class RestrictedExport(Export):
"""Don't (even offer to) export inaccessible fields"""
def fields_get(self, model):
Model = request.session.model(model)
fields = Model.fields_get(False, request.context)
model = request.env[model]
if isinstance(model, RestrictFieldAccessMixin):
sanitised_fields = {k:fields[k] for k in fields if model._restrict_field_access_is_field_accessible(k)}
return sanitised_fields
else:
return fields
Loading…
Cancel
Save