filter the menu on the user's groups and the access rights on objects linked to the menu (cached)

bzr revid: christophe@tinyerp.com-20081009072900-6tqvlinbjqljvqvc
This commit is contained in:
Christophe Simonis 2008-10-09 09:29:00 +02:00
parent 3e0ca97993
commit e7e9ac879c
2 changed files with 68 additions and 17 deletions

View File

@ -333,6 +333,7 @@ class ir_model_access(osv.osv):
# Check rights on actions
#
def write(self, cr, uid, *args, **argv):
self.pool.get('ir.ui.menu').clear_cache()
res = super(ir_model_access, self).write(cr, uid, *args, **argv)
self.check()
return res
@ -341,6 +342,7 @@ class ir_model_access(osv.osv):
self.check()
return res
def unlink(self, cr, uid, *args, **argv):
self.pool.get('ir.ui.menu').clear_cache()
res = super(ir_model_access, self).unlink(cr, uid, *args, **argv)
self.check()
return res

View File

@ -58,33 +58,74 @@ class many2many_unique(fields.many2many):
class ir_ui_menu(osv.osv):
_name = 'ir.ui.menu'
def __init__(self, *args, **kwargs):
self._cache = {}
return super(ir_ui_menu, self).__init__(*args, **kwargs)
def clear_cache(self):
# radical but this doesn't frequently happen
self._cache = {}
def search(self, cr, uid, args, offset=0, limit=2000, order=None,
context=None, count=False):
if context is None:
context = {}
ids = osv.orm.orm.search(self, cr, uid, args, offset, limit, order,
context=context)
ids = osv.orm.orm.search(self, cr, uid, args, offset, limit, order, context=context, count=(count and uid==1))
if uid==1:
return ids
user_groups = set(self.pool.get('res.users').browse(cr, uid, uid)['groups_id'] or [])
if not ids:
if count:
return 0
return []
modelaccess = self.pool.get('ir.model.access')
user_groups = set(self.pool.get('res.users').read(cr, 1, uid)['groups_id'])
result = []
for menu in self.browse(cr, uid, ids):
restrict_to_groups = menu.groups_id
if not restrict_to_groups:
if menu.action:
# if the menu itself has no restrictions, we get the groups of
# the action of the menu
try:
m, oid = menu.action.split(',', 1)
data = self.pool.get(m).browse(cr, uid, int(oid), context=context)
if data and 'groups_id' in data:
restrict_to_groups = data['groups_id']
except:
pass
if restrict_to_groups and not user_groups.intersection(restrict_to_groups):
# this key works because user access rights are all based on user's groups (cfr ir_model_access.check)
key = (cr.dbname, menu.id, tuple(user_groups))
if key in self._cache:
if self._cache[key]:
result.append(menu.id)
continue
self._cache[key] = False
if menu.groups_id:
restrict_to_groups = [g.id for g in menu.groups_id]
if not user_groups.intersection(restrict_to_groups):
continue
if menu.action: # FIXME elif ?
# we check if the user has access to the action of the menu
m, oid = menu.action.split(',', 1)
data = self.pool.get(m).browse(cr, 1, int(oid))
if data:
model_field = { 'ir.actions.act_window': 'res_model',
'ir.actions.report.custom': 'model',
'ir.actions.report.xml': 'model',
'ir.actions.wizard': 'model',
'ir.actions.server': 'model_id',
}
field = model_field.get(m)
if field and data[field]:
if not modelaccess.check(cr, uid, data[field], raise_exception=False):
continue
else:
# if there is no action, it's a 'folder' menu
if not menu.child_id:
# not displayed if there is no children
continue
self._cache[key] = True
result.append(menu.id)
if count:
return len(result)
return result
def _get_full_name(self, cr, uid, ids, name, args, context):
@ -102,6 +143,14 @@ class ir_ui_menu(osv.osv):
parent_path = ''
return parent_path + menu.name
def write(self, *args, **kwargs):
self.clear_cache()
return super(ir_ui_menu, self).write(*args, **kwargs)
def unlink(self, *args, **kwargs):
self.clear_cache()
return super(ir_ui_menu, self).unlink(*args, **kwargs)
def copy(self, cr, uid, id, default=None, context=None):
ir_values_obj = self.pool.get('ir.values')
res = super(ir_ui_menu, self).copy(cr, uid, id, context=context)