[FIX] document: search() must filter out documents in disallowed directories

Permissions on ir.attachments must not only respect the access rights
of the object they are attached to, but must also be careful about
directory permissions as introduced by the document module.

Minor fix in copy() method to avoid reading all fields of the
attachment including the binary data itself, when only the name
is needed. Also made the "(copy)" suffix translatable.

bzr revid: odo@openerp.com-20110218141012-a7wjqn2f48iioca9
This commit is contained in:
Olivier Dony 2011-02-18 15:10:12 +01:00
parent 2dd77dd687
commit 0874e7b291
1 changed files with 29 additions and 7 deletions

View File

@ -38,9 +38,9 @@ class document_file(osv.osv):
def _attach_parent_id(self, cr, uid, ids=None, context=None):
"""Migrate ir.attachments to the document module.
When the 'document' module is loaded on a db that has had plain attachments,
they will need to be attached to some parent folder, and be converted from
they will need to be attached to some parent folder, and be converted from
base64-in-bytea to raw-in-bytea format.
This function performs the internal migration, once and forever, for these
attachments. It cannot be done through the nominal ORM maintenance code,
@ -50,7 +50,7 @@ class document_file(osv.osv):
should have had (but would have failed if plain attachments contained null
values).
"""
parent_id = self.pool.get('document.directory')._get_root_directory(cr,uid)
if not parent_id:
logging.getLogger('document').warning("at _attach_parent_id(), still not able to set the parent!")
@ -64,7 +64,7 @@ class document_file(osv.osv):
"WHERE parent_id IS NULL", (parent_id,))
cr.execute("ALTER TABLE ir_attachment ALTER parent_id SET NOT NULL")
return True
def _get_filestore(self, cr):
return os.path.join(DMS_ROOT_PATH, cr.dbname)
@ -167,19 +167,41 @@ class document_file(osv.osv):
def check(self, cr, uid, ids, mode, context=None, values=None):
"""Check access wrt. res_model, relax the rule of ir.attachment parent
With 'document' installed, everybody will have access to attachments of
any resources they can *read*.
"""
return super(document_file, self).check(cr, uid, ids, mode='read',
context=context, values=values)
def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
# Grab ids, bypassing 'count'
ids = super(document_file, self).search(cr, uid, args, offset=offset,
limit=limit, order=order,
context=context, count=False)
if not ids:
return 0 if count else []
# Filter out documents that are in directories that the user is not allowed to read.
# Must use pure SQL to avoid access rules exceptions (we want to remove the records,
# not fail), and the records have been filtered in parent's search() anyway.
cr.execute('SELECT id, parent_id from "%s" WHERE id in %%s' % self._table, (tuple(ids),))
doc_pairs = cr.fetchall()
parent_ids = set(zip(*doc_pairs)[1])
visible_parent_ids = self.pool.get('document.directory').search(cr, uid, [('id', 'in', list(parent_ids))])
disallowed_parents = parent_ids.difference(visible_parent_ids)
for doc_id, parent_id in doc_pairs:
if parent_id in disallowed_parents:
ids.remove(doc_id)
return len(ids) if count else ids
def copy(self, cr, uid, id, default=None, context=None):
if not default:
default = {}
if 'name' not in default:
name = self.read(cr, uid, [id])[0]['name']
default.update({'name': name + " (copy)"})
name = self.read(cr, uid, [id], ['name'])[0]['name']
default.update({'name': name + " " + _("(copy)")})
return super(document_file, self).copy(cr, uid, id, default, context=context)
def write(self, cr, uid, ids, vals, context=None):