Check relation access in fields_get and for default fields in read
issue3750 review4261002
This commit is contained in:
1 parent
4306811fe6
commit
f72b983c0f
5 files changed
+53
-32
No files matched your search
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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 []
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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():
|
||||
|
||||
Reference in new issue
Block a user