[FIX] improve multi-company and rule system
bzr revid: fp@tinyerp.com-20091222190158-lwknqi2vcgj1e94d
This commit is contained in:
@@ -137,10 +137,9 @@ class ir_rule(osv.osv):
|
||||
if not (field_id or operator or operand):
|
||||
return {}
|
||||
|
||||
def domain_get(self, cr, uid, model_name):
|
||||
# root user above constraint
|
||||
def domain_get2(self, cr, uid, model_name):
|
||||
if uid == 1:
|
||||
return '', []
|
||||
return []
|
||||
|
||||
cr.execute("""SELECT r.id FROM
|
||||
ir_rule r
|
||||
@@ -152,64 +151,14 @@ class ir_rule(osv.osv):
|
||||
JOIN res_groups_users_rel u_rel ON (g_rel.group_id = u_rel.gid)
|
||||
WHERE u_rel.uid = %s) OR g.global)""", (model_name, uid))
|
||||
ids = map(lambda x:x[0], cr.fetchall())
|
||||
if not ids:
|
||||
return '', []
|
||||
obj = self.pool.get(model_name)
|
||||
add = []
|
||||
add_str = []
|
||||
sub = []
|
||||
sub_str = []
|
||||
clause={}
|
||||
clause_global={}
|
||||
dom = []
|
||||
for rule in self.browse(cr, uid, ids):
|
||||
dom = rule.domain
|
||||
if rule.rule_group['global']:
|
||||
clause_global.setdefault(rule.rule_group.id, [])
|
||||
clause_global[rule.rule_group.id].append(obj._where_calc(cr, uid, dom, active_test=False))
|
||||
else:
|
||||
clause.setdefault(rule.rule_group.id, [])
|
||||
clause[rule.rule_group.id].append(obj._where_calc(cr, uid, dom, active_test=False))
|
||||
|
||||
def _query(clause, test):
|
||||
query = ''
|
||||
val = []
|
||||
for g in clause.values():
|
||||
if not g:
|
||||
continue
|
||||
if len(query):
|
||||
query += ' '+test+' '
|
||||
query += '('
|
||||
first = True
|
||||
for c in g:
|
||||
if not first:
|
||||
query += ' AND '
|
||||
first = False
|
||||
query += '('
|
||||
first2 = True
|
||||
for clause in c[0]:
|
||||
if not first2:
|
||||
query += ' AND '
|
||||
first2 = False
|
||||
query += clause
|
||||
query += ')'
|
||||
val += c[1]
|
||||
query += ')'
|
||||
return query, val
|
||||
|
||||
query, val = _query(clause, 'OR')
|
||||
query_global, val_global = _query(clause_global, 'OR')
|
||||
if query_global:
|
||||
if query:
|
||||
query = '('+query+') OR '+query_global
|
||||
val.extend(val_global)
|
||||
else:
|
||||
query = query_global
|
||||
val = val_global
|
||||
|
||||
|
||||
if query:
|
||||
query = '('+query+')'
|
||||
return query, val
|
||||
dom += rule.domain
|
||||
return dom
|
||||
def domain_get(self, cr, uid, model_name):
|
||||
dom = self.domain_get2(cr, uid, model_name)
|
||||
d1,d2,tables = self.pool.get(model_name)._where_calc(cr, uid, dom, active_test=False)
|
||||
return ' and '.join(d1), d2, tables
|
||||
domain_get = tools.cache()(domain_get)
|
||||
|
||||
def unlink(self, cr, uid, ids, context=None):
|
||||
|
||||
@@ -115,14 +115,14 @@ class expression(object):
|
||||
main_table = table
|
||||
fargs = left.split('.', 1)
|
||||
index = i
|
||||
if left in table._inherit_fields:
|
||||
if fargs[0] in table._inherit_fields:
|
||||
while True:
|
||||
field = main_table._columns.get(fargs[0], False)
|
||||
if field:
|
||||
working_table = main_table
|
||||
self.__tables[i] = working_table
|
||||
break
|
||||
working_table = main_table.pool.get(main_table._inherit_fields[left][0])
|
||||
working_table = main_table.pool.get(main_table._inherit_fields[fargs[0]][0])
|
||||
if working_table not in self.__tables.values():
|
||||
self.__joins.append(('%s.%s=%s.%s' % (working_table._table, 'id', main_table._table, main_table._inherits[working_table._name]), working_table._table))
|
||||
self.__tables[index] = working_table
|
||||
|
||||
+4
-4
@@ -506,12 +506,12 @@ class many2many(_column):
|
||||
limit_str = self._limit is not None and ' limit %d' % self._limit or ''
|
||||
obj = obj.pool.get(self._obj)
|
||||
|
||||
d1, d2 = obj.pool.get('ir.rule').domain_get(cr, user, obj._name)
|
||||
d1, d2, tables = obj.pool.get('ir.rule').domain_get(cr, user, obj._name)
|
||||
if d1:
|
||||
d1 = ' and ' + d1
|
||||
|
||||
cr.execute('SELECT '+self._rel+'.'+self._id2+','+self._rel+'.'+self._id1+' \
|
||||
FROM '+self._rel+' , '+obj._table+' \
|
||||
FROM '+self._rel+' , '+(','.join(tables))+' \
|
||||
WHERE '+self._rel+'.'+self._id1+' = ANY (%s) \
|
||||
AND '+self._rel+'.'+self._id2+' = '+obj._table+'.id '+d1
|
||||
+limit_str+' order by '+obj._table+'.'+obj._order+' offset %s',
|
||||
@@ -544,10 +544,10 @@ class many2many(_column):
|
||||
cr.execute('update '+self._rel+' set '+self._id2+'=null where '+self._id2+'=%s', (id,))
|
||||
elif act[0] == 6:
|
||||
|
||||
d1, d2 = obj.pool.get('ir.rule').domain_get(cr, user, obj._name)
|
||||
d1, d2,tables = obj.pool.get('ir.rule').domain_get(cr, user, obj._name)
|
||||
if d1:
|
||||
d1 = ' and ' + d1
|
||||
cr.execute('delete from '+self._rel+' where '+self._id1+'=%s AND '+self._id2+' IN (SELECT '+self._rel+'.'+self._id2+' FROM '+self._rel+', '+obj._table+' WHERE '+self._rel+'.'+self._id1+'=%s AND '+self._rel+'.'+self._id2+' = '+obj._table+'.id '+ d1 +')', [id, id]+d2)
|
||||
cr.execute('delete from '+self._rel+' where '+self._id1+'=%s AND '+self._id2+' IN (SELECT '+self._rel+'.'+self._id2+' FROM '+self._rel+', '+','.join(tables)+' WHERE '+self._rel+'.'+self._id1+'=%s AND '+self._rel+'.'+self._id2+' = '+obj._table+'.id '+ d1 +')', [id, id]+d2)
|
||||
|
||||
for act_nbr in act[2]:
|
||||
cr.execute('insert into '+self._rel+' ('+self._id1+','+self._id2+') values (%s, %s)', (id, act_nbr))
|
||||
|
||||
+17
-33
@@ -2343,7 +2343,6 @@ class orm(orm_template):
|
||||
|
||||
select = map(lambda x: isinstance(x,dict) and x['id'] or x, select)
|
||||
result = self._read_flat(cr, user, select, fields, context, load)
|
||||
|
||||
for r in result:
|
||||
for key, v in r.items():
|
||||
if v == None:
|
||||
@@ -2361,8 +2360,7 @@ class orm(orm_template):
|
||||
id_exist = cr.fetchone()
|
||||
if not id_exist:
|
||||
cr.execute('update "'+self._table+'" set "'+key+'"=NULL where "%s"=%s' %(key,''.join("'"+str(v)+"'")))
|
||||
r[key] = ''
|
||||
|
||||
r[key] = ''
|
||||
if isinstance(ids, (int, long, dict)):
|
||||
return result and result[0] or False
|
||||
return result
|
||||
@@ -2377,7 +2375,7 @@ class orm(orm_template):
|
||||
fields_to_read = self._columns.keys()
|
||||
|
||||
# construct a clause for the rules :
|
||||
d1, d2 = self.pool.get('ir.rule').domain_get(cr, user, self._name)
|
||||
d1, d2, tables = self.pool.get('ir.rule').domain_get(cr, user, self._name)
|
||||
|
||||
# all inherited fields + all non inherited fields for which the attribute whose name is in load is True
|
||||
fields_pre = [f for f in fields_to_read if
|
||||
@@ -2392,7 +2390,7 @@ class orm(orm_template):
|
||||
return "date_trunc('second', %s) as %s" % (f, f)
|
||||
if f == self.CONCURRENCY_CHECK_FIELD:
|
||||
if self._log_access:
|
||||
return "COALESCE(write_date, create_date, now())::timestamp AS %s" % (f,)
|
||||
return "COALESCE(%s.write_date, %s.create_date, now())::timestamp AS %s" % (self._table, self._table, f,)
|
||||
return "now()::timestamp AS %s" % (f,)
|
||||
if isinstance(self._columns[f], fields.binary) and context.get('bin_size', False):
|
||||
return 'length("%s") as "%s"' % (f, f)
|
||||
@@ -2401,8 +2399,8 @@ class orm(orm_template):
|
||||
for i in range(0, len(ids), cr.IN_MAX):
|
||||
sub_ids = ids[i:i+cr.IN_MAX]
|
||||
if d1:
|
||||
cr.execute('SELECT %s FROM \"%s\" WHERE id = ANY (%%s) AND %s ORDER BY %s' % \
|
||||
(','.join(fields_pre2 + ['id']), self._table, d1,
|
||||
cr.execute('SELECT %s FROM %s WHERE %s.id = ANY (%%s) AND %s ORDER BY %s' % \
|
||||
(','.join(fields_pre2 + [self._table + '.id']), ','.join(tables), self._table, d1,
|
||||
self._order),[sub_ids,]+d2)
|
||||
if not cr.rowcount == len({}.fromkeys(sub_ids)):
|
||||
raise except_orm(_('AccessError'),
|
||||
@@ -2588,7 +2586,7 @@ class orm(orm_template):
|
||||
# ids2 = [x[self._inherits[key]] for x in res]
|
||||
# self.pool.get(key).unlink(cr, uid, ids2)
|
||||
|
||||
d1, d2 = self.pool.get('ir.rule').domain_get(cr, uid, self._name)
|
||||
d1, d2,tables = self.pool.get('ir.rule').domain_get(cr, uid, self._name)
|
||||
if d1:
|
||||
d1 = ' AND '+d1
|
||||
|
||||
@@ -2596,19 +2594,15 @@ class orm(orm_template):
|
||||
sub_ids = ids[i:i+cr.IN_MAX]
|
||||
str_d = string.join(('%s',)*len(sub_ids), ',')
|
||||
if d1:
|
||||
cr.execute('SELECT id FROM "'+self._table+'" ' \
|
||||
'WHERE id IN ('+str_d+')'+d1, sub_ids+d2)
|
||||
cr.execute('SELECT '+self._table+'.id FROM '+','.join(tables)+' ' \
|
||||
'WHERE '+self._table+'.id IN ('+str_d+')'+d1, sub_ids+d2)
|
||||
if not cr.rowcount == len(sub_ids):
|
||||
raise except_orm(_('AccessError'),
|
||||
_('You try to bypass an access rule (Document type: %s).') % \
|
||||
self._description)
|
||||
|
||||
if d1:
|
||||
cr.execute('delete from "'+self._table+'" ' \
|
||||
'where id in ('+str_d+')'+d1, sub_ids+d2)
|
||||
else:
|
||||
cr.execute('delete from "'+self._table+'" ' \
|
||||
'where id in ('+str_d+')', sub_ids)
|
||||
cr.execute('delete from '+self._table+' ' \
|
||||
'where id in ('+str_d+')', sub_ids)
|
||||
|
||||
for order, object, store_ids, fields in result_store:
|
||||
if object<>self._name:
|
||||
@@ -2708,7 +2702,7 @@ class orm(orm_template):
|
||||
|
||||
if len(upd0):
|
||||
|
||||
d1, d2 = self.pool.get('ir.rule').domain_get(cr, user, self._name)
|
||||
d1, d2,tables = self.pool.get('ir.rule').domain_get(cr, user, self._name)
|
||||
if d1:
|
||||
d1 = ' and '+d1
|
||||
|
||||
@@ -2716,8 +2710,8 @@ class orm(orm_template):
|
||||
sub_ids = ids[i:i+cr.IN_MAX]
|
||||
ids_str = string.join(map(str, sub_ids), ',')
|
||||
if d1:
|
||||
cr.execute('SELECT id FROM "'+self._table+'" ' \
|
||||
'WHERE id IN ('+ids_str+')'+d1, d2)
|
||||
cr.execute('SELECT '+self._table+'.id FROM '+','.join(tables)+' ' \
|
||||
'WHERE '+self._table+'.id IN ('+ids_str+')'+d1, d2)
|
||||
if not cr.rowcount == len({}.fromkeys(sub_ids)):
|
||||
raise except_orm(_('AccessError'),
|
||||
_('You try to bypass an access rule (Document type: %s).') % \
|
||||
@@ -2728,12 +2722,8 @@ class orm(orm_template):
|
||||
raise except_orm(_('AccessError'),
|
||||
_('You try to write on an record that doesn\'t exist ' \
|
||||
'(Document type: %s).') % self._description)
|
||||
if d1:
|
||||
cr.execute('update "'+self._table+'" set '+string.join(upd0, ',')+' ' \
|
||||
'where id in ('+ids_str+')'+d1, upd1+ d2)
|
||||
else:
|
||||
cr.execute('update "'+self._table+'" set '+string.join(upd0, ',')+' ' \
|
||||
'where id in ('+ids_str+')', upd1)
|
||||
cr.execute('update '+self._table+' set '+string.join(upd0, ',')+' ' \
|
||||
'where id in ('+ids_str+')', upd1)
|
||||
|
||||
if totranslate:
|
||||
# TODO: optimize
|
||||
@@ -3161,8 +3151,8 @@ class orm(orm_template):
|
||||
if not context:
|
||||
context = {}
|
||||
# compute the where, order by, limit and offset clauses
|
||||
(qu1, qu2, tables) = self._where_calc(cr, user, args, context=context)
|
||||
|
||||
dom = self.pool.get('ir.rule').domain_get2(cr, user, self._name)
|
||||
(qu1, qu2, tables) = self._where_calc(cr, user, args+dom, context=context)
|
||||
if len(qu1):
|
||||
qu1 = ' where '+string.join(qu1, ' and ')
|
||||
else:
|
||||
@@ -3176,12 +3166,6 @@ class orm(orm_template):
|
||||
offset_str = offset and ' offset %d' % offset or ''
|
||||
|
||||
|
||||
# construct a clause for the rules :
|
||||
d1, d2 = self.pool.get('ir.rule').domain_get(cr, user, self._name)
|
||||
if d1:
|
||||
qu1 = qu1 and qu1+' and '+d1 or ' where '+d1
|
||||
qu2 += d2
|
||||
|
||||
if count:
|
||||
cr.execute('select count(%s.id) from ' % self._table +
|
||||
','.join(tables) +qu1 + limit_str + offset_str, qu2)
|
||||
|
||||
Reference in New Issue
Block a user