2
# -*- encoding: utf-8 -*-
3
##############################################################################
5
# OpenERP, Open Source Management Solution
6
# Copyright (C) 2011 TeMPO Consulting, MSF. All Rights Reserved
7
# Developer: Max Mumford
9
# This program is free software: you can redistribute it and/or modify
10
# it under the terms of the GNU Affero General Public License as
11
# published by the Free Software Foundation, either version 3 of the
12
# License, or (at your option) any later version.
14
# This program is distributed in the hope that it will be useful,
15
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
# GNU Affero General Public License for more details.
19
# You should have received a copy of the GNU Affero General Public License
20
# along with this program. If not, see <http://www.gnu.org/licenses/>.
22
##############################################################################
24
from osv import osv, orm
25
from lxml import etree
30
super_fields_view_get = orm.orm.fields_view_get
32
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
34
Dynamically change button groups based on button access rules
37
context = context or {}
38
fields_view = super_fields_view_get(self, cr, uid, view_id, view_type, context, toolbar, submenu)
39
view_id = view_id or fields_view.get('view_id', False)
43
rules_pool = self.pool.get('msf_button_access_rights.button_access_rule')
45
# view_id == 0 if view generated on fly by openerp because no custom view specified, therefore we will have no rules
47
search_ids = rules_pool._get_family_ids(cr, view_id)
51
rules_search = rules_pool.search(cr, 1, [('view_id', 'in', search_ids)])
55
rules = rules_pool.browse(cr, 1, rules_search, context=context)
57
# parse view and get all buttons with a name, a type that is not 'special', no position attribute, and may or may not have an invisible attribute (But not set to '1')
58
view_xml = etree.fromstring(fields_view['arch'])
59
buttons = view_xml.xpath("//button[ @name and @type != 'special' and not (@position) and @invisible != '1' or not (@invisible) ]")
61
for button in buttons:
63
button_name = button.attrib.get('name', '')
65
# check if rule gives user access to button
66
rules_for_button = [rule for rule in rules if getattr(rule, 'name', False) == button_name]
69
# might have multiple rules (from inherited views), so concatenate groups lists
70
groups_with_duplicates = [r.group_ids for r in rules_for_button]
72
for group in groups_with_duplicates:
73
if isinstance(group, (list, tuple)):
75
if g.id not in groups:
81
user = self.pool.get('res.users').read(cr, 1, uid)
82
if set(user['groups_id']).intersection(groups):
88
if 'invisible' in button.attrib:
89
del button.attrib['invisible']
91
button.attrib['invisible'] = '1'
93
fields_view['arch'] = etree.tostring(view_xml)
103
orm.orm.fields_view_get = fields_view_get
109
'ir.actions.act_window',
125
super_execute_cr = osv.object_proxy.execute_cr
128
def execute_cr(self, cr, uid, obj, method, *args, **kw):
131
return super_execute_cr(self, cr, uid, obj, method, *args, **kw)
134
module_name = obj.split('.')[0]
138
if module_name in module_whitelist or method in method_whitelist:
139
return super_execute_cr(self, cr, uid, obj, method, *args, **kw)
141
# load button access rights for this method
142
pool = pooler.get_pool(cr.dbname)
143
model_id = pool.get('ir.model').search(cr, 1, [('model','=',obj)])
144
rules_pool = pool.get('msf_button_access_rights.button_access_rule')
146
rules_search = rules_pool.search(cr, 1, [('name','=',method),('model_id','=',model_id)])
150
rule = rules_pool.browse(cr, 1, rules_search[0])
152
# does user have access?
155
user = pool.get('res.users').read(cr, 1, uid)
156
if set(user['groups_id']).intersection([g.id for g in rule.group_ids]):
162
# if method type = action, continue as normal, otherwise
163
if rule.type == 'action':
164
return super_execute_cr(self, cr, uid, obj, method, *args, **kw)
166
# continue action as admin user
167
if rule.type != 'action':
168
return super_execute_cr(self, cr, 1, obj, method, *args, **kw)
171
# throw access denied
172
raise osv.except_osv('Access Denied', 'You do not have permission to use this button')
175
return super_execute_cr(self, cr, uid, obj, method, *args, **kw)
177
logging.getLogger(self._name).warn('Could not get model pool for button_access_rule')
178
return super_execute_cr(self, cr, uid, obj, method, *args, **kw)
180
osv.object_proxy.execute_cr = execute_cr
183
super_execute_workflow_cr = osv.object_proxy.exec_workflow_cr
185
def exec_workflow_cr(self, cr, uid, obj, method, *args):
188
return super_execute_workflow_cr(self, cr, uid, obj, method, *args)
191
module_name = obj.split('.')[0]
195
if module_name in module_whitelist or method in method_whitelist:
196
return super_execute_workflow_cr(self, cr, uid, obj, method, *args)
198
# load button access rights for this method
199
pool = pooler.get_pool(cr.dbname)
200
object_id = pool.get('ir.model').search(cr, 1, [('model','=',obj)])
201
rules_pool = pool.get('msf_button_access_rights.button_access_rule')
203
rules_search = rules_pool.search(cr, 1, [('name','=',method),('model_id','=',object_id)])
207
rule = rules_pool.browse(cr, 1, rules_search[0])
209
# does user have access?
212
user = pool.get('res.users').read(cr, 1, uid)
213
if set(user['groups_id']).intersection([g.id for g in rule.group_ids]):
219
# execute workflow as admin
220
return super_execute_workflow_cr(self, cr, 1, obj, method, *args)
222
# throw access denied
223
raise osv.except_osv('Access Denied', 'You do not have permission to use this button')
225
return super_execute_workflow_cr(self, cr, uid, obj, method, *args)
227
logging.getLogger(self._name).warn('Could not get model pool for button_access_rule')
228
return super_execute_workflow_cr(self, cr, uid, obj, method, *args)
230
osv.object_proxy.exec_workflow_cr = exec_workflow_cr
b'\\ No newline at end of file'