[FIX] improve multi-company and rule system

bzr revid: fp@tinyerp.com-20091222190158-lwknqi2vcgj1e94d
This commit is contained in:
Fabien Pinckaers
2009-12-22 20:01:58 +01:00
parent 6afb2769d8
commit eb665f6e1d
4 changed files with 32 additions and 99 deletions
+9 -60
View File
@@ -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):
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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)