diff --git a/trytond/ir/model.py b/trytond/ir/model.py index 1245180c24..d3aadb1d8f 100644 --- a/trytond/ir/model.py +++ b/trytond/ir/model.py @@ -526,6 +526,38 @@ class ModelAccess(ModelSQL, ModelView): return False return True + @classmethod + def check_relation(cls, model_name, field_name, mode='read'): + 'Check access to relation field for model_name and mode' + pool = Pool() + Model = pool.get(model_name) + field = getattr(Model, field_name) + if field._type in ('one2many', 'many2one'): + return cls.check(field.model_name, mode=mode, + raise_exception=False) + elif field._type in ('many2many', 'one2one'): + if (field.target + and not cls.check(field.target, mode=mode, + raise_exception=False)): + return False + elif (field.relation_name + and not cls.check(field.relation_name, mode=mode, + raise_exception=False)): + return False + else: + return True + elif field._type == 'reference': + selection = field.selection + if isinstance(selection, basestring): + selection = getattr(Model, field.selection)() + for model_name, _ in selection: + if not cls.check(model_name, mode=mode, + raise_exception=False): + return False + return True + else: + return True + @classmethod def write(cls, accesses, values, *args): super(ModelAccess, cls).write(accesses, values, *args) diff --git a/trytond/model/model.py b/trytond/model/model.py index 8563f4bfa0..a6426bf581 100644 --- a/trytond/model/model.py +++ b/trytond/model/model.py @@ -226,6 +226,7 @@ class Model(WarningErrorMixin, URLMixin, PoolBase): pool = Pool() Translation = pool.get('ir.translation') FieldAccess = pool.get('ir.model.field.access') + ModelAccess = pool.get('ir.model.access') #Add translation to cache language = Transaction().language @@ -389,11 +390,13 @@ class Model(WarningErrorMixin, URLMixin, PoolBase): if attr in res[field]: res[field][attr] = encoder.encode(res[field][attr]) - if fields_names: + for i in res.keys(): # filter out fields which aren't in the fields_names list - for i in res.keys(): + if fields_names: if i not in fields_names: del res[i] + elif not ModelAccess.check_relation(cls.__name__, i, mode='read'): + del res[i] return res def on_change_with(self, fieldnames): diff --git a/trytond/model/modelsql.py b/trytond/model/modelsql.py index 3fcfc91189..b3cf9cf2da 100644 --- a/trytond/model/modelsql.py +++ b/trytond/model/modelsql.py @@ -417,12 +417,16 @@ class ModelSQL(ModelStorage): pool = Pool() Rule = pool.get('ir.rule') Translation = pool.get('ir.translation') + ModelAccess = pool.get('ir.model.access') + if not fields_names: + fields_names = [] + for field_name in cls._fields.keys(): + if ModelAccess.check_relation(cls.__name__, field_name, + mode='read'): + fields_names.append(field_name) super(ModelSQL, cls).read(ids, fields_names=fields_names) cursor = Transaction().cursor - if not fields_names: - fields_names = cls._fields.keys() - if not ids: return [] diff --git a/trytond/model/modelstorage.py b/trytond/model/modelstorage.py index 5fb41b3e3d..8c7132386f 100644 --- a/trytond/model/modelstorage.py +++ b/trytond/model/modelstorage.py @@ -120,9 +120,15 @@ class ModelStorage(Model): ModelAccess = pool.get('ir.model.access') ModelFieldAccess = pool.get('ir.model.field.access') + if not fields_names: + fields_names = [] + for field_name in cls._fields.keys(): + if ModelAccess.check_relation(cls.__name__, field_name, + mode='read'): + fields_names.append(field_name) + ModelAccess.check(cls.__name__, 'read') - ModelFieldAccess.check(cls.__name__, - fields_names or cls._fields.keys(), 'read') + ModelFieldAccess.check(cls.__name__, fields_names, 'read') return [] @classmethod diff --git a/trytond/model/modelview.py b/trytond/model/modelview.py index eec4db9812..ae853e21e5 100644 --- a/trytond/model/modelview.py +++ b/trytond/model/modelview.py @@ -295,33 +295,9 @@ class ModelView(Model): fields_to_remove = list(x for x, y in fread_accesses.iteritems() if not y) - def check_relation(model, field): - if field._type in ('one2many', 'many2one'): - if not ModelAccess.check(field.model_name, mode='read', - raise_exception=False): - return False - if field._type in ('many2many', 'one2one'): - if (field.target - and not ModelAccess.check(field.target, mode='read', - raise_exception=False)): - return False - elif (field.relation_name - and not ModelAccess.check(field.relation_name, - mode='read', raise_exception=False)): - return False - if field._type == 'reference': - selection = field.selection - if isinstance(selection, basestring): - selection = getattr(model, field.selection)() - for model_name, _ in selection: - if not ModelAccess.check(model_name, mode='read', - raise_exception=False): - return False - return True - # Find relation field without read access for name, field in cls._fields.iteritems(): - if not check_relation(cls, field): + if not ModelAccess.check_relation(cls.__name__, name, mode='read'): fields_to_remove.append(name) for name, field in cls._fields.iteritems():