示例#1
0
 def _search_group(self, cr, uid, obj, name, args, context=None):
     operand = args[0][2]
     operator = args[0][1]
     lst = True
     if isinstance(operand, bool):
         domains = [[('name', operator, operand)], [('category_id.name', operator, operand)]]
         if operator in expression.NEGATIVE_TERM_OPERATORS == (not operand):
             return expression.AND(domains)
         else:
             return expression.OR(domains)
     if isinstance(operand, basestring):
         lst = False
         operand = [operand]
     where = []
     for group in operand:
         values = filter(bool, group.split('/'))
         group_name = values.pop().strip()
         category_name = values and '/'.join(values).strip() or group_name
         group_domain = [('name', operator, lst and [group_name] or group_name)]
         category_domain = [('category_id.name', operator, lst and [category_name] or category_name)]
         if operator in expression.NEGATIVE_TERM_OPERATORS and not values:
             category_domain = expression.OR([category_domain, [('category_id', '=', False)]])
         if (operator in expression.NEGATIVE_TERM_OPERATORS) == (not values):
             sub_where = expression.AND([group_domain, category_domain])
         else:
             sub_where = expression.OR([group_domain, category_domain])
         if operator in expression.NEGATIVE_TERM_OPERATORS:
             where = expression.AND([where, sub_where])
         else:
             where = expression.OR([where, sub_where])
     return where
 def code_search(self, name, args=None, operator='ilike', limit=100):
     if not args:
         args = []
     if name:
         category_names = name.split(' / ')
         parents = list(category_names)
         child = parents.pop()
         domain = [('name', operator, child)]
         if parents:
             names_ids = self.name_search(' / '.join(parents),
                                          args=args,
                                          operator='ilike',
                                          limit=limit)
             category_ids = [name_id[0] for name_id in names_ids]
             if operator in expression.NEGATIVE_TERM_OPERATORS:
                 categories = self.search([('id', 'not in', category_ids)])
                 domain = expression.OR([[('parent_id', 'in',
                                           categories.ids)], domain])
             else:
                 domain = expression.AND([[('parent_id', 'in', category_ids)
                                           ], domain])
             for i in range(1, len(category_names)):
                 domain = [[('name', operator,
                             ' / '.join(category_names[-1 - i:]))], domain]
                 if operator in expression.NEGATIVE_TERM_OPERATORS:
                     domain = expression.AND(domain)
                 else:
                     domain = expression.OR(domain)
         categories = self.search(expression.AND([domain, args]),
                                  limit=limit)
     else:
         categories = self.search(args, limit=limit)
     return categories.name_get()
    def get_aml_domain_for_expr(self, expr,
                                date_from, date_to,
                                period_from, period_to,
                                target_move):
        """ Get a domain on account.move.line for an expression.

        Prerequisite: done_parsing() must have been invoked.

        Returns a domain that can be used to search on account.move.line.
        """
        aml_domains = []
        date_domain_by_mode = {}
        for mo in self.ACC_RE.finditer(expr):
            field, mode, account_codes, domain = self._parse_match_object(mo)
            aml_domain = list(domain)
            account_ids = set()
            for account_code in account_codes:
                account_ids.update(self._account_ids_by_code[account_code])
            aml_domain.append(('account_id', 'in', tuple(account_ids)))
            if field == 'crd':
                aml_domain.append(('credit', '>', 0))
            elif field == 'deb':
                aml_domain.append(('debit', '>', 0))
            aml_domains.append(expression.normalize_domain(aml_domain))
            if mode not in date_domain_by_mode:
                date_domain_by_mode[mode] = \
                    self.get_aml_domain_for_dates(date_from, date_to,
                                                  period_from, period_to,
                                                  mode, target_move)
        return expression.OR(aml_domains) + \
            expression.OR(date_domain_by_mode.values())
示例#4
0
 def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=100):
     if not args:
         args = []
     if not context:
         context = {}
     if name:
         # Be sure name_search is symetric to name_get
         categories = name.split('/')
         parents = list(categories)
         child = parents.pop()
         domain = [('name', operator, child)]
         if parents:
             names_ids = self.name_search(
                 cr, uid, '/'.join(parents), args=args, operator='ilike', context=context, limit=limit)
             category_ids = [name_id[0] for name_id in names_ids]
             if operator in expression.NEGATIVE_TERM_OPERATORS:
                 category_ids = self.search(
                     cr, uid, [('id', 'not in', category_ids)])
                 domain = expression.OR(
                     [[('parent_id', 'in', category_ids)], domain])
             else:
                 domain = expression.AND(
                     [[('parent_id', 'in', category_ids)], domain])
             for i in range(1, len(categories)):
                 domain = [
                     [('name', operator, '/'.join(categories[-1 - i:]))], domain]
                 if operator in expression.NEGATIVE_TERM_OPERATORS:
                     domain = expression.AND(domain)
                 else:
                     domain = expression.OR(domain)
         ids = self.search(
             cr, uid, expression.AND([domain, args]), limit=limit, context=context)
     else:
         ids = self.search(cr, uid, args, limit=limit, context=context)
     return self.name_get(cr, uid, ids, context)
示例#5
0
    def _domain_get(self, cr, uid, ids, field_name, args, context=None):
        '''combine our domain with all domains to union/complement,
        this works recursively'''
        def eval_n(domain):
            '''parse a domain and normalize it'''
            try:
                domain = safe_eval(domain)
            except:
                domain = [expression.FALSE_LEAF]
            return expression.normalize_domain(
                domain or [expression.FALSE_LEAF])

        result = {}
        for this in self.read(
                cr, uid, ids,
                ['domain_this', 'union_filter_ids', 'complement_filter_ids'],
                context=context):
            domain = eval_n(this['domain_this'])
            for u in self.read(cr, uid, this['union_filter_ids'],
                               ['domain', 'evaluate_always', 'model_id'],
                               context=context):
                if u['evaluate_always']:
                    matching_ids = self.pool[u['model_id']].search(
                        cr, uid, eval_n(u['domain']),
                        context=context)
                    domain = expression.OR([
                        domain,
                        [('id', 'in', matching_ids)],
                    ])
                else:
                    domain = expression.OR([domain, eval_n(u['domain'])])
            for c in self.read(cr, uid, this['complement_filter_ids'],
                               ['domain', 'evaluate_before_negate',
                                'model_id'],
                               context=context):
                if c['evaluate_before_negate']:
                    matching_ids = self.pool[c['model_id']].search(
                        cr, uid, eval_n(c['domain']),
                        context=context)
                    domain = expression.AND([
                        domain,
                        [('id', 'not in', matching_ids)],
                    ])
                else:
                    domain = expression.AND([
                        domain,
                        ['!'] + eval_n(c['domain'])])
            result[this['id']] = str(expression.normalize_domain(domain))
        return result
示例#6
0
def check_record_rule_cause_error(self, model_name, user, rule, mode="read"):
    """
    Evaluate the rule to check whether it cause the access right error
    or not.
    This function is the combination of 2 functions:
        + domain_get
        + _check_record_rules_result_count
    """
    model_pooler = self.pool[model_name]
    global_domains = []  # list of domains
    group_domains = {}  # map: group -> list of domains
    rule_domain = rule.domain
    dom = expression.normalize_domain(rule_domain)
    for group in rule.groups:
        if group in user.groups_id:
            group_domains.setdefault(group, []).append(dom)
    if not rule.groups:
        global_domains.append(dom)
    # combine global domains and group domains
    if group_domains:
        group_domain = expression.OR(map(expression.OR,
                                         group_domains.values()))
    else:
        group_domain = []
    domain = expression.AND(global_domains + [group_domain])
    if domain:
        # _where_calc is called as superuser. This means that rules can
        # involve objects on which the real uid has no acces rights.
        # This means also there is no implicit restriction (e.g. an object
        # references another object the user can't see).
        query = self.pool.get(model_name)._where_calc(self._cr,
                                                      SUPERUSER_ID,
                                                      domain,
                                                      active_test=False)
        where_clause, where_params, tables = query.where_clause, \
            query.where_clause_params, query.tables
        if where_clause:
            where_clause = ' and ' + ' and '.join(where_clause)
            self._cr.execute(
                'SELECT ' + model_pooler._table + '.id FROM ' +
                ','.join(tables) + ' WHERE ' + model_pooler._table +
                '.id IN %s' + where_clause,
                ([tuple(self._ids)] + where_params))
            result_ids = [x['id'] for x in self._cr.dictfetchall()]

            ids, result_ids = set(self._ids), set(result_ids)
            missing_ids = ids - result_ids
            if missing_ids:
                # Attempt to distinguish record rule
                # restriction vs deleted records,
                # to provide a more specific error message -
                # check if the missinf
                self._cr.execute(
                    'SELECT id FROM ' + model_pooler._table +
                    ' WHERE id IN %s', (tuple(missing_ids), ))
                # the missing ids are (at least partially)
                # hidden by access rules
                if self._cr.rowcount or mode not in ('read', 'unlink'):
                    return True
    return False
示例#7
0
    def _needaction_domain_get(self, cr, uid, context=None):
        """ Returns the domain to filter records that require an action
            :return: domain or False is no action
        """
        # get domain from parent object if exists
        dom = super(res_partner_needaction, self)._needaction_domain_get(
            cr, uid, context=context)
        obj = self.pool['ir.model.data']
        followers = obj.get_object(
            cr, uid,
            'account_streamline',
            'group_account_creators'
        ).message_follower_ids

        user = self.pool['res.users'].browse(cr, uid, uid, context=context)

        if user.partner_id in followers:
            mydom = [
                '|', ('supplier_account_check', '=', True),
                ('customer_account_check', '=', True),
            ]

            dom = expression.OR([
                expression.normalize_domain(mydom),
                expression.normalize_domain(dom)
            ])

        return dom
示例#8
0
 def search(self,
            cr,
            user,
            args,
            offset=0,
            limit=None,
            order=None,
            context=None,
            count=False):
     """ Display only standalone contact matching ``args`` or having
     attached contact matching ``args`` """
     if context is None:
         context = {}
     if context.get('search_show_all_positions') is False:
         args = expression.normalize_domain(args)
         attached_contact_args = expression.AND(
             (args, [('contact_type', '=', 'attached')]))
         attached_contact_ids = super(res_partner,
                                      self).search(cr,
                                                   user,
                                                   attached_contact_args,
                                                   context=context)
         args = expression.OR((
             expression.AND(([('contact_type', '=', 'standalone')], args)),
             [('other_contact_ids', 'in', attached_contact_ids)],
         ))
     return super(res_partner, self).search(cr,
                                            user,
                                            args,
                                            offset=offset,
                                            limit=limit,
                                            order=order,
                                            context=context,
                                            count=count)
示例#9
0
    def test_40_negating_long_expression(self):
        source = ['!','&',('user_id','=',4),('partner_id','in',[1,2])]
        expect = ['|',('user_id','!=',4),('partner_id','not in',[1,2])]
        self.assertEqual(expression.distribute_not(source), expect,
            "distribute_not on expression applied wrongly")

        pos_leaves = [[('a', 'in', [])], [('d', '!=', 3)]]
        neg_leaves = [[('a', 'not in', [])], [('d', '=', 3)]]

        source = expression.OR([expression.AND(pos_leaves)] * 1000)
        expect = source
        self.assertEqual(expression.distribute_not(source), expect,
            "distribute_not on long expression without negation operator should not alter it")

        source = ['!'] + source
        expect = expression.AND([expression.OR(neg_leaves)] * 1000)
        self.assertEqual(expression.distribute_not(source), expect,
            "distribute_not on long expression applied wrongly")
示例#10
0
    def message_read(
        self, cr, uid, ids=None, domain=None, message_unload_ids=None,
        thread_level=0, context=None, parent_id=False, limit=None
    ):
        """Override this function to include account.move.line notifications
        within account.move notification lists.

        :todo This applies to every mail.message object; maybe find a better
        solution that doesn't involve modifying objects globally.
        """

        # Example domain: [['model', '=', 'account.move'], ['res_id', '=', 7]]

        # Avoid recursion...
        if domain and ['model', '=', 'account.move.line'] not in domain:

            am_obj = self.pool['account.move']

            line_domain = []

            # Look for a "res_id = X" domain part.
            for domain_index, domain_part in enumerate(domain):
                if (domain_index < len(domain) - 1 and
                    domain_part == ['model', '=', 'account.move']
                ):
                    next_part = domain[domain_index + 1]
                    if next_part[0] == 'res_id' and next_part[1] == '=':

                        move_id = next_part[2]
                        line_ids = am_obj.read(
                            cr, uid,
                            move_id,
                            ['line_id'],
                            context=context
                        )['line_id']

                        line_domain = [
                            ('model', '=', 'account.move.line'),
                            ('res_id', 'in', line_ids)
                        ]

            if line_domain:
                domain = expression.OR([
                    expression.normalize_domain(line_domain),
                    expression.normalize_domain(domain)
                ])

                # Make sure our domain is applied. When "ids" is set, the
                # domain is ignored.
                ids = None

        return super(mail_message, self).message_read(
            cr, uid, ids=ids, domain=domain,
            message_unload_ids=message_unload_ids, thread_level=thread_level,
            context=context, parent_id=parent_id, limit=limit
        )
示例#11
0
    def _compute_domain(self, cr, uid, model_name, mode="read", context=None):
        context = context or {}
        if mode not in self._MODES:
            raise ValueError('Invalid mode: %r' % (mode, ))

        if uid == SUPERUSER_ID:
            return None
        cr.execute(
            """SELECT r.id
                FROM ir_rule r
                JOIN ir_model m ON (r.model_id = m.id)
                WHERE m.model = %s
                AND r.active is True
                AND r.perm_""" + mode + """
                AND (r.id IN (SELECT rule_group_id FROM rule_group_rel g_rel
                            JOIN res_groups_users_rel u_rel ON (g_rel.group_id = u_rel.gid)
                            WHERE u_rel.uid = %s) OR r.global)""",
            (model_name, uid))
        rule_ids = [x[0] for x in cr.fetchall()]
        if rule_ids:
            # browse user as super-admin root to avoid access errors!
            user = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid)
            global_domains = []  # list of domains
            group_domains = {}  # map: group -> list of domains
            context['_compute_domain_rules'] = [
            ]  #Used to show a comprensive rule error message
            for rule in self.browse(cr, SUPERUSER_ID, rule_ids):
                # read 'domain' as UID to have the correct eval context for the rule.
                rule_domain = self.read(cr, uid, rule.id, ['domain'])['domain']
                dom = expression.normalize_domain(rule_domain)
                for group in rule.groups:
                    if group in user.groups_id:
                        group_domains.setdefault(group, []).append(dom)
                if not rule.groups:
                    global_domains.append(dom)
                context['_compute_domain_rules'].append({
                    'id':
                    rule.id,
                    'name':
                    rule.name,
                    'domain':
                    dom,
                    'groups': [g.name for g in rule.groups],
                    'model':
                    rule.model_id.name
                })
            # combine global domains and group domains
            if group_domains:
                group_domain = expression.OR(
                    map(expression.OR, group_domains.values()))
            else:
                group_domain = []
            domain = expression.AND(global_domains + [group_domain])
            return domain
        return []
示例#12
0
 def get_mention_suggestions(self, search, limit=8):
     """ Return 'limit'-first channels' id, name and public fields such that the name matches a
         'search' string. Exclude channels of type chat (DM), and private channels the current
         user isn't registered to. """
     domain = expression.AND([[('name', 'ilike', search)],
                              [('channel_type', '=', 'channel')],
                              expression.OR(
                                  [[('public', '!=', 'private')],
                                   [('channel_partner_ids', 'in',
                                     [self.env.user.partner_id.id])]])])
     return self.search_read(domain, ['id', 'name', 'public'], limit=limit)
 def domain_move_lines_for_reconciliation(self,
                                          excluded_ids=None,
                                          str=False):
     """ Add move display name in search of move lines"""
     _super = super(AccountMoveLine, self)
     _get_domain = _super.domain_move_lines_for_reconciliation
     domain = _get_domain(excluded_ids=excluded_ids, str=str)
     if not str and str != '/':
         return domain
     domain_trans_ref = [('move_id.display_name', 'ilike', str)]
     return expression.OR([domain, domain_trans_ref])
示例#14
0
    def get_mention_suggestions(self, search, channel, exclude=None, limit=8):
        """ Return 'limit'-first partners' id, name and email such that the name or email matches a
            'search' string. Prioritize partners registered to channel 'channel[channel_id]' if
            given, or partners that are followers of a document identified by 'channel[res_model]'
            and 'channel[res_id]' otherwise, then users, and finally extend the research to all
            partners. Exclude partners whose id is in 'exclude'. """
        if exclude is None:
            exclude = []
        members = []
        users = []
        partners = []
        search_dom = expression.AND([
            expression.OR([[('name', 'ilike', search)],
                           [('email', 'ilike', search)]]),
            [('id', 'not in', exclude)]
        ])
        fields = ['id', 'name', 'email']

        def search_partners(domain, fields, limit, exclude):
            partners = self.search_read(domain, fields, limit=limit)
            limit -= len(partners)
            exclude += [partner['id'] for partner in partners]
            return partners, limit, exclude

        # Search users registered to the channel
        if 'channel_id' in channel:
            domain = expression.AND([[('channel_ids', 'in',
                                       [channel['channel_id']])], search_dom])
            members, limit, exclude = search_partners(domain, fields, limit,
                                                      exclude)
        else:
            domain = expression.AND([[('res_model', '=', channel['res_model'])
                                      ], [('res_id', '=', channel['res_id'])]])
            followers = self.env['mail.followers'].search(domain)
            domain = expression.AND([[('id', 'in',
                                       followers.mapped('partner_id').ids)],
                                     search_dom])
            members, limit, exclude = search_partners(domain, fields, limit,
                                                      exclude)

        if limit > 0:
            # Search users
            domain = expression.AND([[('user_ids.id', '!=', False)],
                                     search_dom])
            users, limit, exclude = search_partners(domain, fields, limit,
                                                    exclude)

            if limit > 0:
                # Search partners
                partners = self.search_read(search_dom, fields, limit=limit)

        return [members, users, partners]
示例#15
0
    def get_mention_suggestions(self, search, limit=8):
        """ Return 'limit'-first partners' id, name and email such that the name or email matches a
            'search' string. Prioritize users, and then extend the research to all partners. """
        search_dom = expression.OR([[('name', 'ilike', search)], [('email', 'ilike', search)]])
        fields = ['id', 'name', 'email']

        # Search users
        domain = expression.AND([[('user_ids.id', '!=', False)], search_dom])
        users = self.search_read(domain, fields, limit=limit)

        # Search partners if less than 'limit' users found
        partners = []
        if len(users) < limit:
            partners = self.search_read(search_dom, fields, limit=limit)
            # Remove duplicates
            partners = [p for p in partners if not len([u for u in users if u['id'] == p['id']])] 

        return [users, partners]
示例#16
0
 def search(self, args, offset=0, limit=None, order=None, count=False):
     """ Display only standalone contact matching ``args`` or having
     attached contact matching ``args`` """
     ctx = self.env.context
     if (ctx.get('search_show_all_positions', {}).get('is_set')
             and not ctx['search_show_all_positions']['set_value']):
         args = expression.normalize_domain(args)
         attached_contact_args = expression.AND(
             (args, [('contact_type', '=', 'attached')]))
         attached_contacts = super(ResPartner,
                                   self).search(attached_contact_args)
         args = expression.OR((
             expression.AND(([('contact_type', '=', 'standalone')], args)),
             [('other_contact_ids', 'in', attached_contacts.ids)],
         ))
     return super(ResPartner, self).search(args,
                                           offset=offset,
                                           limit=limit,
                                           order=order,
                                           count=count)
示例#17
0
    def get_move_lines_for_reconciliation(self, excluded_ids=None, str=False, offset=0, limit=None, additional_domain=None, overlook_partner=False):
        """ Return account.move.line records which can be used for bank statement reconciliation.

            :param excluded_ids:
            :param str:
            :param offset:
            :param limit:
            :param additional_domain:
            :param overlook_partner:
        """
        # Domain to fetch registered payments (use case where you encode the payment before you get the bank statement)
        reconciliation_aml_accounts = [self.journal_id.default_credit_account_id.id, self.journal_id.default_debit_account_id.id]
        domain_reconciliation = ['&', ('statement_id', '=', False), ('account_id', 'in', reconciliation_aml_accounts)]

        # Domain to fetch unreconciled payables/receivables (use case where you close invoices/refunds by reconciling your bank statements)
        domain_matching = [('reconciled', '=', False)]
        if self.partner_id.id or overlook_partner:
            domain_matching = expression.AND([domain_matching, [('account_id.internal_type', 'in', ['payable', 'receivable'])]])
        else:
            # TODO : find out what use case this permits (match a check payment, registered on a journal whose account type is other instead of liquidity)
            domain_matching = expression.AND([domain_matching, [('account_id.reconcile', '=', True)]])

        # Let's add what applies to both
        domain = expression.OR([domain_reconciliation, domain_matching])
        if self.partner_id.id and not overlook_partner:
            domain = expression.AND([domain, [('partner_id', '=', self.partner_id.id)]])

        # Domain factorized for all reconciliation use cases
        ctx = dict(self._context or {})
        ctx['bank_statement_line'] = self
        generic_domain = self.env['account.move.line'].with_context(ctx).domain_move_lines_for_reconciliation(excluded_ids=excluded_ids, str=str)
        domain = expression.AND([domain, generic_domain])

        # Domain from caller
        if additional_domain is None:
            additional_domain = []
        else:
            additional_domain = expression.normalize_domain(additional_domain)
        domain = expression.AND([domain, additional_domain])

        return self.env['account.move.line'].search(domain, offset=offset, limit=limit, order="date_maturity asc, id asc")
 def _compute_activity_rule_domain(self, activity_id):
     if self._uid == SUPERUSER_ID or isinstance(self.env.uid,
                                                BaseSuspendSecurityUid):
         return None
     self._cr.execute(
         """SELECT r.id
             FROM activity_record_rule r
             WHERE r.active is True
             AND r.activity_id = %s
             AND (r.id IN (SELECT rule_group_id FROM activity_rule_group_rel g_rel
             JOIN res_groups_users_rel u_rel ON (g_rel.group_id = u_rel.gid)
             WHERE u_rel.uid = %s) OR r.global)""",
         (activity_id, self._uid))
     rule_ids = [x[0] for x in self._cr.fetchall()]
     if rule_ids:
         # browse user as super-admin root to avoid access errors!
         user = self.env['res.users'].sudo().browse([self._uid])
         global_domains = []  # list of domains
         group_domains = {}  # map: group -> list of domains
         for rule in self.sudo().browse(rule_ids):
             # read 'domain' as UID to have the correct eval context for
             # the rule.
             rule_domain = rule.sudo(user=user.id)\
                 .read(['domain'])[0]['domain']
             dom = expression.normalize_domain(rule_domain)
             for group in rule.groups:
                 if group in user.groups_id:
                     group_domains.setdefault(group, []).append(dom)
             if not rule.groups:
                 global_domains.append(dom)
         # combine global domains and group domains
         if group_domains:
             group_domain = expression.OR(
                 map(expression.OR, group_domains.values()))
         else:
             group_domain = []
         domain = expression.AND(global_domains + [group_domain])
         return domain
     return []
示例#19
0
 def _get_stuck_jobs_domain(self, queue_dl, started_dl):
     domain = []
     now = fields.datetime.now()
     if queue_dl:
         queue_dl = now - timedelta(minutes=queue_dl)
         domain.append([
             '&',
             ('date_enqueued', '<=', fields.Datetime.to_string(queue_dl)),
             ('state', '=', 'enqueued'),
         ])
     if started_dl:
         started_dl = now - timedelta(minutes=started_dl)
         domain.append([
             '&',
             ('date_started', '<=', fields.Datetime.to_string(started_dl)),
             ('state', '=', 'started'),
         ])
     if not domain:
         raise exceptions.ValidationError(
             _("If both parameters are 0, ALL jobs will be requeued!")
         )
     return expression.OR(domain)
 def _restrict_field_access_adjust_field_modifiers(self, field_node,
                                                   modifiers):
     """inject a readonly modifier to make non-writable fields in a form
     readonly"""
     # TODO: this can be fooled by embedded views
     if not self._restrict_field_access_is_field_accessible(
             field_node.attrib['name'], action='write'):
         for modifier, value in [('readonly', True), ('required', False)]:
             domain = modifiers.get(modifier, [])
             if isinstance(domain, list) and domain:
                 domain = expression.normalize_domain(domain)
             elif bool(domain) == value:
                 # readonly/nonrequired anyways
                 return modifiers
             else:
                 domain = []
             restrict_domain = [('restrict_field_access', '=', value)]
             if domain:
                 restrict_domain = expression.OR([
                     restrict_domain,
                     domain
                 ])
             modifiers[modifier] = restrict_domain
     return modifiers
示例#21
0
 def get_rule_ids(self, cr, uid, ids, check_uid, model_name, mode="read"):
     if check_uid == SUPERUSER_ID:
         return []
     res_ids = []
     model_pooler = self.pool[model_name]
     cr.execute(
         """
             SELECT r.id
             FROM ir_rule r
             JOIN ir_model m ON (r.model_id = m.id)
             WHERE m.model = %s
             AND r.active is True
             AND r.perm_""" + mode + """
             AND (r.id IN (SELECT rule_group_id FROM rule_group_rel g_rel
                         JOIN res_groups_users_rel u_rel ON (g_rel.group_id = u_rel.gid)
                         WHERE u_rel.uid = %s) OR r.global)""",
         (model_name, check_uid))
     rule_ids = [x[0] for x in cr.fetchall()]
     if rule_ids:
         # browse user as super-admin root to avoid access errors!
         user = self.pool['res.users'].browse(cr, SUPERUSER_ID, check_uid)
         rule_datas = self.pool['ir.rule'].browse(cr, SUPERUSER_ID,
                                                  rule_ids)
         for rule in rule_datas:
             global_domains = []  # list of domains
             # map: group -> list of domains
             group_domains = {}
             # read 'domain' as UID to have the correct eval context for the
             # rule.
             rule_domain = rule.domain
             #                rule_domain = rule_domain['domain']
             dom = expression.normalize_domain(rule_domain)
             for group in rule.groups:
                 if group in user.groups_id:
                     group_domains.setdefault(group, []).append(dom)
             if not rule.groups:
                 global_domains.append(dom)
             # combine global domains and group domains
             if group_domains:
                 group_domain = expression.OR(
                     map(expression.OR, group_domains.values()))
             else:
                 group_domain = []
             domain = expression.AND(global_domains + [group_domain])
             if domain:
                 # _where_calc is called as superuser. This means that rules can
                 # involve objects on which the real uid has no acces rights.
                 # This means also there is no implicit restriction (e.g. an object
                 # references another object the user can't see).
                 query = self.pool.get(model_name)._where_calc(
                     cr, SUPERUSER_ID, domain, active_test=False)
                 where_clause, where_params, tables = query.where_clause, query.where_clause_params, query.tables
                 if where_clause:
                     where_clause = ' and ' + ' and '.join(where_clause)
                     cr.execute(
                         'SELECT ' + model_pooler._table + '.id FROM ' +
                         ','.join(tables) + ' WHERE ' +
                         model_pooler._table + '.id IN %s' + where_clause,
                         ([tuple(ids)] + where_params))
                     returned_ids = [x['id'] for x in cr.dictfetchall()]
                     check_rs = self.profile_check_record_rules_result_count(
                         cr,
                         check_uid,
                         ids,
                         returned_ids,
                         mode,
                         model_pooler,
                         context={})
                     if not check_rs:
                         res_ids.append(rule.id)
     return res_ids