~unifield-team/unifield-wm/us-826

« back to all changes in this revision

Viewing changes to msf_button_access_rights/osv_override.py

  • Committer: mmu-openerp
  • Date: 2013-03-13 11:05:40 UTC
  • mfrom: (1349.29.95 button-wm)
  • mto: This revision was merged to the branch mainline in revision 1524.
  • Revision ID: mmu@openerp.com-20130313110540-gk589kzzzkw5ojro
[MERGE] uf-1652 button access rights

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
# -*- encoding: utf-8 -*-
 
3
##############################################################################
 
4
#
 
5
#    OpenERP, Open Source Management Solution
 
6
#    Copyright (C) 2011 TeMPO Consulting, MSF. All Rights Reserved
 
7
#    Developer: Max Mumford 
 
8
#
 
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.
 
13
#
 
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.
 
18
#
 
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/>.
 
21
#
 
22
##############################################################################
 
23
 
 
24
from osv import osv, orm
 
25
from lxml import etree
 
26
import pooler
 
27
import random
 
28
import string
 
29
 
 
30
super_fields_view_get = orm.orm.fields_view_get
 
31
 
 
32
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
 
33
    """
 
34
    Dynamically change button groups based on button access rules
 
35
    """
 
36
 
 
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)
 
40
    
 
41
    if uid != 1:
 
42
        
 
43
        rules_pool = self.pool.get('msf_button_access_rights.button_access_rule')
 
44
        
 
45
        # view_id == 0 if view generated on fly by openerp because no custom view specified, therefore we will have no rules
 
46
        if view_id:
 
47
            search_ids = rules_pool._get_family_ids(cr, view_id)
 
48
        else:
 
49
            return fields_view
 
50
        
 
51
        rules_search = rules_pool.search(cr, 1, [('view_id', 'in', search_ids)])
 
52
 
 
53
        # if have rules
 
54
        if rules_search:
 
55
            rules = rules_pool.browse(cr, 1, rules_search, context=context)
 
56
            
 
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) ]")
 
60
            
 
61
            for button in buttons:
 
62
                
 
63
                button_name = button.attrib.get('name', '')
 
64
                
 
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]
 
67
                if rules_for_button:
 
68
                    
 
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]
 
71
                    groups = []
 
72
                    for group in groups_with_duplicates:
 
73
                        if isinstance(group, (list, tuple)):
 
74
                            for g in group:
 
75
                                if g.id not in groups:
 
76
                                    groups.append(g.id)
 
77
                    
 
78
                    access = False
 
79
                    
 
80
                    if groups:
 
81
                        user = self.pool.get('res.users').read(cr, 1, uid)
 
82
                        if set(user['groups_id']).intersection(groups):
 
83
                            access = True
 
84
                    else:
 
85
                        access = True
 
86
                            
 
87
                    if access:
 
88
                        if 'invisible' in button.attrib:
 
89
                            del button.attrib['invisible']
 
90
                    else:
 
91
                        button.attrib['invisible'] = '1'
 
92
                            
 
93
            fields_view['arch'] = etree.tostring(view_xml)
 
94
            
 
95
            return fields_view
 
96
 
 
97
        else:
 
98
            return fields_view
 
99
 
 
100
    else:
 
101
        return fields_view
 
102
 
 
103
orm.orm.fields_view_get = fields_view_get
 
104
 
 
105
module_whitelist = [
 
106
    'ir.module.module',
 
107
    'res.log',
 
108
    'ir.ui.menu',
 
109
    'ir.actions.act_window',
 
110
    'ir.ui.view_sc',
 
111
    'res.request',
 
112
    'ir.model',
 
113
    'ir.values',
 
114
]
 
115
 
 
116
method_whitelist = [
 
117
    'read',
 
118
    'write',
 
119
    'search',
 
120
    'fields_view_get',
 
121
    'fields_get',
 
122
    'name_get',
 
123
]
 
124
 
 
125
super_execute_cr = osv.object_proxy.execute_cr
 
126
 
 
127
 
 
128
def execute_cr(self, cr, uid, obj, method, *args, **kw):
 
129
    
 
130
    if uid == 1:
 
131
        return super_execute_cr(self, cr, uid, obj, method, *args, **kw)
 
132
    
 
133
    if '.' in method:
 
134
        module_name = obj.split('.')[0]
 
135
    else:
 
136
        module_name = obj
 
137
    
 
138
    if module_name in module_whitelist or method in method_whitelist:
 
139
        return super_execute_cr(self, cr, uid, obj, method, *args, **kw)
 
140
    else:
 
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')
 
145
        if rules_pool:
 
146
            rules_search = rules_pool.search(cr, 1, [('name','=',method),('model_id','=',model_id)])
 
147
            
 
148
            # do we have rules?
 
149
            if rules_search:
 
150
                rule = rules_pool.browse(cr, 1, rules_search[0])
 
151
                
 
152
                # does user have access? 
 
153
                access = False
 
154
                if rule.group_ids:
 
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]):
 
157
                        access = True
 
158
                else:
 
159
                    access = True
 
160
                
 
161
                if access:
 
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)
 
165
                
 
166
                    # continue action as admin user
 
167
                    if rule.type != 'action':
 
168
                        return super_execute_cr(self, cr, 1, obj, method, *args, **kw)
 
169
                    
 
170
                else:
 
171
                    # throw access denied
 
172
                    raise osv.except_osv('Access Denied', 'You do not have permission to use this button')
 
173
                
 
174
            else:
 
175
                return super_execute_cr(self, cr, uid, obj, method, *args, **kw)
 
176
        else:
 
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)
 
179
 
 
180
osv.object_proxy.execute_cr = execute_cr
 
181
 
 
182
 
 
183
super_execute_workflow_cr = osv.object_proxy.exec_workflow_cr
 
184
 
 
185
def exec_workflow_cr(self, cr, uid, obj, method, *args):
 
186
 
 
187
    if uid == 1:
 
188
        return super_execute_workflow_cr(self, cr, uid, obj, method, *args)
 
189
 
 
190
    if '.' in method:
 
191
        module_name = obj.split('.')[0]
 
192
    else:
 
193
        module_name = obj
 
194
    
 
195
    if module_name in module_whitelist or method in method_whitelist:
 
196
        return super_execute_workflow_cr(self, cr, uid, obj, method, *args)
 
197
    else:
 
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')
 
202
        if rules_pool:
 
203
            rules_search = rules_pool.search(cr, 1, [('name','=',method),('model_id','=',object_id)])
 
204
            
 
205
            # do we have rules?
 
206
            if rules_search:
 
207
                rule = rules_pool.browse(cr, 1, rules_search[0])
 
208
                
 
209
                # does user have access? 
 
210
                access = False
 
211
                if rule.group_ids:
 
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]):
 
214
                        access = True
 
215
                else:
 
216
                    access = True
 
217
                
 
218
                if access:
 
219
                    # execute workflow as admin
 
220
                    return super_execute_workflow_cr(self, cr, 1, obj, method, *args)
 
221
                else:
 
222
                    # throw access denied
 
223
                    raise osv.except_osv('Access Denied', 'You do not have permission to use this button')
 
224
            else:
 
225
                return super_execute_workflow_cr(self, cr, uid, obj, method, *args)
 
226
        else:
 
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)
 
229
    
 
230
osv.object_proxy.exec_workflow_cr = exec_workflow_cr
 
 
b'\\ No newline at end of file'