From ddd65ab5c143f23df75205f274ce70b46e858310 Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Fri, 12 Aug 2011 14:41:28 +0200 Subject: [PATCH] [REF] osv: removed orm_memory, adapted the distinguished bits to osv_memory, so yes, there are still two user-visible classes instead of a boolean flag. bzr revid: vmt@openerp.com-20110812124128-43rr422swy6h2vs8 --- openerp/osv/expression.py | 7 ++ openerp/osv/orm.py | 200 +------------------------------------- openerp/osv/osv.py | 39 +++++++- 3 files changed, 44 insertions(+), 202 deletions(-) diff --git a/openerp/osv/expression.py b/openerp/osv/expression.py index 54726a289f2..4de6ae295c5 100644 --- a/openerp/osv/expression.py +++ b/openerp/osv/expression.py @@ -91,6 +91,13 @@ def OR(domains): """ OR([D1,D2,...]) returns a domain representing D1 or D2 or ... """ return combine(OR_OPERATOR, FALSE_DOMAIN, TRUE_DOMAIN, domains) +# Probably bad style: the domain should be already normalized (and non-empty). +def expression_and(term, domain): + if domain: + return ['&', term] + normalize(domain) + else: + return term + class expression(object): """ diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index efd93f75e1b..3dd0f38caec 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -2246,205 +2246,6 @@ class orm_template(object): values = defaults return values -class orm_memory(orm_template): - - _protected = ['read', 'write', 'create', 'default_get', 'perm_read', 'unlink', 'fields_get', 'fields_view_get', 'search', 'name_get', 'distinct_field_get', 'name_search', 'copy', 'import_data', 'search_count', 'exists'] - _inherit_fields = {} - _check_time = 20 - - @classmethod - def createInstance(cls, pool, cr): - return cls.makeInstance(pool, cr, ['_columns', '_defaults']) - - def __init__(self, pool, cr): - super(orm_memory, self).__init__(pool, cr) - self.datas = {} - self.next_id = 0 - cr.execute('delete from wkf_instance where res_type=%s', (self._name,)) - - def _check_access(self, uid, object_id, mode): - if uid != 1 and self.datas[object_id]['internal.create_uid'] != uid: - raise except_orm(_('AccessError'), '%s access is only allowed on your own records for osv_memory objects except for the super-user' % mode.capitalize()) - - def read(self, cr, user, ids, fields_to_read=None, context=None, load='_classic_read'): - if not context: - context = {} - if not fields_to_read: - fields_to_read = self._columns.keys() - result = [] - if self.datas: - ids_orig = ids - if isinstance(ids, (int, long)): - ids = [ids] - for id in ids: - r = {'id': id} - for f in fields_to_read: - record = self.datas.get(id) - if record: - self._check_access(user, id, 'read') - r[f] = record.get(f, False) - if r[f] and isinstance(self._columns[f], fields.binary) and context.get('bin_size', False): - r[f] = len(r[f]) - result.append(r) - if id in self.datas: - self.datas[id]['internal.date_access'] = time.time() - fields_post = filter(lambda x: x in self._columns and not getattr(self._columns[x], load), fields_to_read) - for f in fields_post: - res2 = self._columns[f].get_memory(cr, self, ids, f, user, context=context, values=result) - for record in result: - record[f] = res2[record['id']] - if isinstance(ids_orig, (int, long)): - return result[0] - return result - - def write(self, cr, user, ids, vals, context=None): - if not ids: - return True - vals2 = {} - upd_todo = [] - for field in vals: - if self._columns[field]._classic_write: - vals2[field] = vals[field] - else: - upd_todo.append(field) - for object_id in ids: - self._check_access(user, object_id, mode='write') - self.datas[object_id].update(vals2) - self.datas[object_id]['internal.date_access'] = time.time() - for field in upd_todo: - self._columns[field].set_memory(cr, self, object_id, field, vals[field], user, context) - self._validate(cr, user, [object_id], context) - wf_service = netsvc.LocalService("workflow") - wf_service.trg_write(user, self._name, object_id, cr) - return object_id - - def create(self, cr, user, vals, context=None): - self.vacuum(cr, user) - self.next_id += 1 - id_new = self.next_id - - vals = self._add_missing_default_values(cr, user, vals, context) - - vals2 = {} - upd_todo = [] - for field in vals: - if self._columns[field]._classic_write: - vals2[field] = vals[field] - else: - upd_todo.append(field) - self.datas[id_new] = vals2 - self.datas[id_new]['internal.date_access'] = time.time() - self.datas[id_new]['internal.create_uid'] = user - - for field in upd_todo: - self._columns[field].set_memory(cr, self, id_new, field, vals[field], user, context) - self._validate(cr, user, [id_new], context) - if self._log_create and not (context and context.get('no_store_function', False)): - message = self._description + \ - " '" + \ - self.name_get(cr, user, [id_new], context=context)[0][1] + \ - "' "+ _("created.") - self.log(cr, user, id_new, message, True, context=context) - wf_service = netsvc.LocalService("workflow") - wf_service.trg_create(user, self._name, id_new, cr) - return id_new - - def _where_calc(self, cr, user, args, active_test=True, context=None): - if not context: - context = {} - args = args[:] - res = [] - # if the object has a field named 'active', filter out all inactive - # records unless they were explicitely asked for - if 'active' in self._columns and (active_test and context.get('active_test', True)): - if args: - active_in_args = False - for a in args: - if a[0] == 'active': - active_in_args = True - if not active_in_args: - args.insert(0, ('active', '=', 1)) - else: - args = [('active', '=', 1)] - if args: - import expression - e = expression.expression(args) - e.parse(cr, user, self, context) - res = e.exp - return res or [] - - def _search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False, access_rights_uid=None): - if not context: - context = {} - - # implicit filter on current user except for superuser - if user != 1: - if not args: - args = [] - args.insert(0, ('internal.create_uid', '=', user)) - - result = self._where_calc(cr, user, args, context=context) - if result == []: - return self.datas.keys() - - res = [] - counter = 0 - #Find the value of dict - f = False - if result: - for id, data in self.datas.items(): - counter = counter + 1 - data['id'] = id - if limit and (counter > int(limit)): - break - f = True - for arg in result: - if arg[1] == '=': - val = eval('data[arg[0]]'+'==' +' arg[2]', locals()) - elif arg[1] in ['<', '>', 'in', 'not in', '<=', '>=', '<>']: - val = eval('data[arg[0]]'+arg[1] +' arg[2]', locals()) - elif arg[1] in ['ilike']: - val = (str(data[arg[0]]).find(str(arg[2]))!=-1) - - f = f and val - - if f: - res.append(id) - if count: - return len(res) - return res or [] - - def unlink(self, cr, uid, ids, context=None): - for id in ids: - self._check_access(uid, id, 'unlink') - self.datas.pop(id, None) - if len(ids): - cr.execute('delete from wkf_instance where res_type=%s and res_id IN %s', (self._name, tuple(ids))) - return True - - def perm_read(self, cr, user, ids, context=None, details=True): - result = [] - credentials = self.pool.get('res.users').name_get(cr, user, [user])[0] - create_date = time.strftime('%Y-%m-%d %H:%M:%S') - for id in ids: - self._check_access(user, id, 'read') - result.append({ - 'create_uid': credentials, - 'create_date': create_date, - 'write_uid': False, - 'write_date': False, - 'id': id, - 'xmlid' : False, - }) - return result - - def _check_removed_columns(self, cr, log=False): - # nothing to check in memory... - pass - - def exists(self, cr, uid, id, context=None): - return id in self.datas - class orm(orm_template): _sql_constraints = [] _table = None @@ -3541,6 +3342,7 @@ class orm(orm_template): vals[field] = False return res + # TODO check READ access def perm_read(self, cr, user, ids, context=None, details=True): """ Returns some metadata about the given records. diff --git a/openerp/osv/osv.py b/openerp/osv/osv.py index b231abd54ab..335be93464f 100644 --- a/openerp/osv/osv.py +++ b/openerp/osv/osv.py @@ -215,6 +215,7 @@ class osv_memory(orm.orm): self.check_id = 0 self._max_count = config.get('osv_memory_count_limit') self._max_hours = config.get('osv_memory_age_limit') + cr.execute('delete from wkf_instance where res_type=%s', (self._name,)) def _clean_transient_rows_older_than(self, cr, seconds): if not self._log_access: @@ -222,9 +223,9 @@ class osv_memory(orm.orm): "Transient model without write_date: %s" % (self._name,)) return - cr.execute("SELECT id FROM " + self._table + " WHERE " - "COALESCE(write_date, create_date, now())::timestamp < " - "(now() - interval %s)", ("%s seconds" % seconds,)) + cr.execute("SELECT id FROM " + self._table + " WHERE" + " COALESCE(write_date, create_date, now())::timestamp <" + " (now() - interval %s)", ("%s seconds" % seconds,)) ids = [x[0] for x in cr.fetchall()] self.unlink(cr, openerp.SUPERUSER, ids) @@ -263,6 +264,38 @@ class osv_memory(orm.orm): return True + def check_access_rule(self, cr, uid, ids, operation, context=None): + # No access rules for osv_memory + if self._log_access and uid != openerp.SUPERUSER: + cr.execute("SELECT distinct create_uid FROM " + self._table + " WHERE" + " id in ", (tuple(ids),)) + uids = [x[0] for x in cr.fetchall()] + if len(uids) != 1 or uids[0] != uid: + raise orm.except_orm(_('AccessError'), '%s access is ' + 'restricted to your own records for osv_memory objects ' + '(except for the super-user).' % mode.capitalize()) + + def create(self, cr, uid, vals, context=None): + self.vacuum(cr, uid) + super(osv_memory, self).create(cr, uid, vals, context) + + def unlink(self, cr, uid, ids, context=None): + super(osv_memory, self).unlink(cr, uid, ids, context) + if isinstance(ids, (int, long)): + ids = [ids] + if ids: + cr.execute('delete from wkf_instance where res_type=%s and res_id IN %s', (self._name, tuple(ids))) + return True + + def _search(self, cr, uid, domain, offset=0, limit=None, order=None, context=None, count=False, access_rights_uid=None): + + # Restrict acces to the current user, except for the super-user. + if self._log_access and uid != openerp.SUPERUSER: + domain = expression.expression_and(('create_uid', '=', uid), domain) + + # TODO unclear: shoudl access_rights_uid be set to None (effectively ignoring it) or used instead of uid? + return self._search(cr, uid, domain, offset, limit, order, context, count, access_rights_uid) + class osv(orm.orm): """ Deprecated class. """