[MERGE] forward port of branch 8.0 up to 7041b25
This commit is contained in:
@@ -96,7 +96,11 @@ class CompanyLDAP(osv.osv):
|
||||
return False
|
||||
|
||||
entry = False
|
||||
filter = filter_format(conf['ldap_filter'], (login,))
|
||||
try:
|
||||
filter = filter_format(conf['ldap_filter'], (login,))
|
||||
except TypeError:
|
||||
_logger.warning('Could not format LDAP filter. Your filter should contain one \'%s\'.')
|
||||
return False
|
||||
try:
|
||||
results = self.query(conf, filter)
|
||||
|
||||
|
||||
@@ -43,9 +43,18 @@ def format_tz(pool, cr, uid, dt, tz=False, format=False, context=None):
|
||||
if tz:
|
||||
context['tz'] = tz or pool.get('res.users').read(cr, SUPERUSER_ID, uid, ['tz'])['tz'] or "UTC"
|
||||
timestamp = datetime.datetime.strptime(dt, tools.DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
|
||||
ts = fields.datetime.context_timestamp(cr, uid, timestamp, context)
|
||||
|
||||
# Babel allows to format datetime in a specific language without change locale
|
||||
# So month 1 = January in English, and janvier in French
|
||||
# Be aware that the default value for format is 'medium', instead of 'short'
|
||||
# medium: Jan 5, 2016, 10:20:31 PM | 5 janv. 2016 22:20:31
|
||||
# short: 1/5/16, 10:20 PM | 5/01/16 22:20
|
||||
if context.get('use_babel'):
|
||||
# Formatting available here : http://babel.pocoo.org/en/latest/dates.html#date-fields
|
||||
from babel.dates import format_datetime
|
||||
return format_datetime(ts, format or 'medium', locale=context.get("lang") or 'en_US')
|
||||
|
||||
if format:
|
||||
return ts.strftime(format)
|
||||
else:
|
||||
|
||||
@@ -106,7 +106,7 @@
|
||||
<tr>
|
||||
<td colspan="4"><strong>Consumed Products</strong></td>
|
||||
</tr>
|
||||
<tr t-foreach="o.move_lines2" t-as="line2">>
|
||||
<tr t-foreach="o.move_lines2" t-as="line2">
|
||||
<td>
|
||||
<span t-field="line2.product_id.code"/>
|
||||
<span t-field="line2.product_id.name"/>
|
||||
|
||||
@@ -774,7 +774,7 @@ class product_template(osv.osv):
|
||||
ctx.update(active_test=False)
|
||||
product_ids = []
|
||||
for product in self.browse(cr, uid, ids, context=ctx):
|
||||
product_ids = map(int,product.product_variant_ids)
|
||||
product_ids += map(int, product.product_variant_ids)
|
||||
self.pool.get("product.product").write(cr, uid, product_ids, {'active': vals.get('active')}, context=ctx)
|
||||
return res
|
||||
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_test_access_right_some_obj,access_test_access_right_some_obj,model_test_access_right_some_obj,,1,1,1,1
|
||||
access_test_access_right_container,access_test_access_right_container,model_test_access_right_container,,1,1,1,1
|
||||
|
||||
|
@@ -4,3 +4,9 @@ class SomeObj(models.Model):
|
||||
_name = 'test_access_right.some_obj'
|
||||
|
||||
val = fields.Integer()
|
||||
|
||||
|
||||
class Container(models.Model):
|
||||
_name = 'test_access_right.container'
|
||||
|
||||
some_ids = fields.Many2many('test_access_right.some_obj', 'test_access_right_rel', 'container_id', 'some_id')
|
||||
|
||||
@@ -31,3 +31,25 @@ class TestRules(TransactionCase):
|
||||
# but this should
|
||||
with self.assertRaises(openerp.exceptions.AccessError):
|
||||
self.assertEqual(browse2.val, -1)
|
||||
|
||||
def test_many2many(self):
|
||||
""" Test assignment of many2many field where rules apply. """
|
||||
ids = [self.id1, self.id2]
|
||||
|
||||
# create container as superuser, connected to all some_objs
|
||||
container_admin = self.env['test_access_right.container'].create({'some_ids': [(6, 0, ids)]})
|
||||
self.assertItemsEqual(container_admin.some_ids.ids, ids)
|
||||
|
||||
# check the container as the public user
|
||||
container_user = container_admin.sudo(self.browse_ref('base.public_user'))
|
||||
self.assertItemsEqual(container_user.some_ids.ids, [self.id1])
|
||||
|
||||
# this should not fail
|
||||
container_user.write({'some_ids': [(6, 0, ids)]})
|
||||
self.assertItemsEqual(container_user.some_ids.ids, [self.id1])
|
||||
self.assertItemsEqual(container_admin.some_ids.ids, ids)
|
||||
|
||||
# this removes accessible records only
|
||||
container_user.write({'some_ids': [(5,)]})
|
||||
self.assertItemsEqual(container_user.some_ids.ids, [])
|
||||
self.assertItemsEqual(container_admin.some_ids.ids, [self.id2])
|
||||
|
||||
+23
-15
@@ -1007,6 +1007,25 @@ class many2many(_column):
|
||||
return
|
||||
rel, id1, id2 = self._sql_names(model)
|
||||
obj = model.pool[self._obj]
|
||||
|
||||
def link(ids):
|
||||
# beware of duplicates when inserting
|
||||
query = """ INSERT INTO {rel} ({id1}, {id2})
|
||||
(SELECT %s, unnest(%s)) EXCEPT (SELECT {id1}, {id2} FROM {rel} WHERE {id1}=%s)
|
||||
""".format(rel=rel, id1=id1, id2=id2)
|
||||
for sub_ids in cr.split_for_in_conditions(ids):
|
||||
cr.execute(query, (id, list(sub_ids), id))
|
||||
|
||||
def unlink_all():
|
||||
# remove all records for which user has access rights
|
||||
clauses, params, tables = obj.pool.get('ir.rule').domain_get(cr, user, obj._name, context=context)
|
||||
cond = " AND ".join(clauses) if clauses else "1=1"
|
||||
query = """ DELETE FROM {rel} USING {tables}
|
||||
WHERE {rel}.{id1}=%s AND {rel}.{id2}={table}.id AND {cond}
|
||||
""".format(rel=rel, id1=id1, id2=id2,
|
||||
table=obj._table, tables=','.join(tables), cond=cond)
|
||||
cr.execute(query, [id] + params)
|
||||
|
||||
for act in values:
|
||||
if not (isinstance(act, list) or isinstance(act, tuple)) or not act:
|
||||
continue
|
||||
@@ -1020,23 +1039,12 @@ class many2many(_column):
|
||||
elif act[0] == 3:
|
||||
cr.execute('delete from '+rel+' where ' + id1 + '=%s and '+ id2 + '=%s', (id, act[1]))
|
||||
elif act[0] == 4:
|
||||
# following queries are in the same transaction - so should be relatively safe
|
||||
cr.execute('SELECT 1 FROM '+rel+' WHERE '+id1+' = %s and '+id2+' = %s', (id, act[1]))
|
||||
if not cr.fetchone():
|
||||
cr.execute('insert into '+rel+' ('+id1+','+id2+') values (%s,%s)', (id, act[1]))
|
||||
link([act[1]])
|
||||
elif act[0] == 5:
|
||||
cr.execute('delete from '+rel+' where ' + id1 + ' = %s', (id,))
|
||||
unlink_all()
|
||||
elif act[0] == 6:
|
||||
|
||||
d1, d2,tables = obj.pool.get('ir.rule').domain_get(cr, user, obj._name, context=context)
|
||||
if d1:
|
||||
d1 = ' and ' + ' and '.join(d1)
|
||||
else:
|
||||
d1 = ''
|
||||
cr.execute('delete from '+rel+' where '+id1+'=%s AND '+id2+' IN (SELECT '+rel+'.'+id2+' FROM '+rel+', '+','.join(tables)+' WHERE '+rel+'.'+id1+'=%s AND '+rel+'.'+id2+' = '+obj._table+'.id '+ d1 +')', [id, id]+d2)
|
||||
|
||||
for act_nbr in act[2]:
|
||||
cr.execute('insert into '+rel+' ('+id1+','+id2+') values (%s, %s)', (id, act_nbr))
|
||||
unlink_all()
|
||||
link(act[2])
|
||||
|
||||
#
|
||||
# TODO: use a name_search
|
||||
|
||||
Reference in New Issue
Block a user