From 0874e7b2910da28a1a70b802a98fef1dcc96af07 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Fri, 18 Feb 2011 15:10:12 +0100 Subject: [PATCH] [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 --- addons/document/document.py | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/addons/document/document.py b/addons/document/document.py index 79fb83b5b1f..1a553b23ed1 100644 --- a/addons/document/document.py +++ b/addons/document/document.py @@ -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):