def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False): if context is None: context = {} # inject searching for current relation date if we search for relation # properties and no explicit date was given date_args = [] for arg in args: if is_leaf(arg) and arg[0].startswith('search_relation'): if arg[0] == 'search_relation_date': date_args = [] break if not date_args: date_args = [ ('search_relation_date', '=', time.strftime( DEFAULT_SERVER_DATE_FORMAT))] # because of auto_join, we have to do the active test by hand active_args = [] if context.get('active_test', True): for arg in args: if is_leaf(arg) and\ arg[0].startswith('search_relation'): active_args = [('relation_all_ids.active', '=', True)] break return super(ResPartner, self).search( cr, uid, args + date_args + active_args, offset=offset, limit=limit, order=order, context=context, count=count)
def search(self, args, offset=0, limit=None, order=None, count=False): """Inject searching for current relation date if we search for relation properties and no explicit date was given. """ # pylint: disable=arguments-differ # pylint: disable=no-value-for-parameter date_args = [] for arg in args: if (is_leaf(arg) and isinstance(arg[0], basestring) and arg[0].startswith('search_relation')): if arg[0] == 'search_relation_date': date_args = [] break if not date_args: date_args = [ ('search_relation_date', '=', fields.Date.today()), ] # because of auto_join, we have to do the active test by hand active_args = [] if self.env.context.get('active_test', True): for arg in args: if (is_leaf(arg) and isinstance(arg[0], basestring) and arg[0].startswith('search_relation')): active_args = [('relation_all_ids.active', '=', True)] break return super(ResPartner, self).search( args + date_args + active_args, offset=offset, limit=limit, order=order, count=count)
def check_leaf(self): """ Leaf validity rules: - a valid leaf is an operator or a leaf - a valid leaf has a field objects unless - it is not a tuple - it is an inherited field - left is id, operator is 'child_of' - left is in MAGIC_COLUMNS """ if not is_operator(self.leaf) and not is_leaf(self.leaf, True): raise ValueError("Invalid leaf %s" % str(self.leaf))
def _is_frozen_get(self, cr, uid, ids, field_name, args, context=None): '''determine if this is fixed list of ids''' result = {} for this in self.browse(cr, uid, ids, context=context): try: domain = safe_eval(this.domain) except: domain = [expression.FALSE_LEAF] result[this.id] = (len(domain) == 1 and expression.is_leaf(domain[0]) and domain[0][0] == 'id') return result
def _evaluate_get(self, cr, uid, ids, field_name, args, context=None): """check if this filter contains references to x2many fields. If so, then negation goes wrong in nearly all cases, so we evaluate the filter and remove its resulting ids""" result = {} for this in self.read(cr, uid, ids, ['model_id', 'domain'], context=context): result[this['id']] = { 'evaluate_before_negate': False, 'evaluate_always': False, } domain = expression.normalize_domain( safe_eval(this['domain'] or 'False') or [expression.FALSE_LEAF]) for arg in domain: if not expression.is_leaf(arg) or not isinstance( arg[0], basestring): continue current_model = self.pool.get(this['model_id']) if not current_model: continue has_x2many = False has_auto_join = False for field_name in arg[0].split('.'): if field_name in MAGIC_COLUMNS: continue field = current_model._all_columns[field_name].column has_x2many |= field._type in self._evaluate_before_negate has_x2many |= isinstance(field, fields.function) has_auto_join |= field._auto_join has_auto_join |= isinstance(field, fields.function) if hasattr(field, '_obj'): current_model = self.pool.get(field._obj) if not current_model or has_x2many and has_auto_join: break result[this['id']]['evaluate_before_negate'] |= has_x2many result[this['id']]['evaluate_always'] |= has_auto_join if result[this['id']]['evaluate_before_negate'] and\ result[this['id']]['evaluate_always']: break return result
def read_group(self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True): """Restrict reading if we read an inaccessible field""" has_inaccessible_field = False has_inaccessible_field |= any( not self._restrict_field_access_is_field_accessible(f) for f in fields or self._fields.keys() ) has_inaccessible_field |= any( expression.is_leaf(term) and not self._restrict_field_access_is_field_accessible( term[0].split('.')[0] ) for term in domain ) if groupby: if isinstance(groupby, basestring): groupby = [groupby] has_inaccessible_field |= any( not self._restrict_field_access_is_field_accessible( f.split(':')[0] ) for f in groupby ) if orderby: has_inaccessible_field |= any( not self._restrict_field_access_is_field_accessible(f.split()) for f in orderby.split(',') ) # just like with search, we restrict read_group to the accessible # records, because we'd either leak data otherwise or have very wrong # results if has_inaccessible_field: self._restrict_field_access_inject_restrict_field_access_domain( domain ) return super(RestrictFieldAccessMixin, self).read_group( domain, fields, groupby, offset=offset, limit=limit, orderby=orderby, lazy=lazy )
def _create_indirect_sharing_rules(self, cr, current_user, wizard_data, group_id, fields_relations, context=None): rule_name = _('Indirect sharing filter created by user %s (%s) for group %s') % \ (current_user.name, current_user.login, group_id) try: domain = safe_eval(wizard_data.domain) if domain: for rel_field, model in fields_relations: # mail.message is transversal: it should not received directly the access rights if model.model in ['mail.message', 'mail.notification']: continue related_domain = [] if not rel_field: continue for element in domain: if expression.is_leaf(element): left, operator, right = element left = '%s.%s'%(rel_field, left) element = left, operator, right related_domain.append(element) self._create_or_combine_sharing_rule(cr, current_user, wizard_data, group_id, model_id=model.id, domain=str(related_domain), rule_name=rule_name, restrict=True, context=context) except Exception: _logger.info('Failed to create share access', exc_info=True) raise UserError(_('Sorry, the current screen and filter you are trying to share are not supported at the moment.\nYou may want to try a simpler filter.'))
def get_applicable_args(args, index): if expression.is_leaf(args[index]): #TODO: also check for inherited fields etc if (( args[index][0] in orm_model._columns or orm_model._log_access and args[index][0] in ['create_date','create_uid', 'write_date', 'write_uid'] ) and args[index][0] not in ['text','model']): return [args[index]], 1 else: return [], 1 else: op1=get_applicable_args(args, index+1) op2=get_applicable_args(args, index+op1[1]+1) return (([args[index]] if len(op1[0]) > 0 and len(op2[0]) > 0 else []) + op1[0] + op2[0], op1[1] + op2[1] + 1 )
def _search(self, args, offset=0, limit=None, order=None, count=False, access_rights_uid=None): if not args: return super(RestrictFieldAccessMixin, self)._search( args, offset=offset, limit=limit, order=order, count=count, access_rights_uid=access_rights_uid) args = expression.normalize_domain(args) has_inaccessible_field = False for term in args: if not expression.is_leaf(term): continue if not self._restrict_field_access_is_field_accessible( term[0], 'read'): has_inaccessible_field = True break if has_inaccessible_field: check_self = self if not access_rights_uid else self.sudo( access_rights_uid) check_self\ ._restrict_field_access_inject_restrict_field_access_domain( args) return super(RestrictFieldAccessMixin, self)._search( args, offset=offset, limit=limit, order=order, count=count, access_rights_uid=access_rights_uid)
def is_leaf(self, internal=False): return is_leaf(self.leaf, internal=internal)