Пример #1
0
 def test_ir_action_window(self):
     'Test action windows are correctly defined'
     pool = Pool()
     ModelData = pool.get('ir.model.data')
     ActionWindow = pool.get('ir.action.act_window')
     for model_data in ModelData.search([
                 ('module', '=', self.module),
                 ('model', '=', 'ir.action.act_window'),
                 ]):
         action_window = ActionWindow(model_data.db_id)
         if not action_window.res_model:
             continue
         Model = pool.get(action_window.res_model)
         decoder = PYSONDecoder({
                 'active_id': None,
                 'active_ids': [],
                 'active_model': action_window.res_model,
                 })
         domain = decoder.decode(action_window.pyson_domain)
         order = decoder.decode(action_window.pyson_order)
         context = decoder.decode(action_window.pyson_context)
         with Transaction().set_context(context):
             Model.search(domain, order=order, limit=action_window.limit)
         for action_domain in action_window.act_window_domains:
             if not action_domain.domain:
                 continue
             Model.search(decoder.decode(action_domain.domain))
Пример #2
0
 def check_fields_pyson(self):
     encoder = PYSONDecoder(noeval=True)
     for field in [
             'recipients_pyson',
             'recipients_secondary_pyson',
             'recipients_hidden_pyson',
     ]:
         value = getattr(self, field)
         if not value:
             continue
         try:
             pyson = encoder.decode(value)
         except Exception as exception:
             raise EmailTemplateError(
                 gettext('ir.msg_email_template_invalid_field_pyson',
                         template=self.rec_name,
                         field=self.__names__(field)['field'],
                         exception=exception)) from exception
         if not isinstance(pyson, list) and pyson.types() != {list}:
             raise EmailTemplateError(
                 gettext(
                     'ir.msg_email_template_invalid_field_pyson_type',
                     template=self.rec_name,
                     field=self.__names__(field)['field'],
                 ))
Пример #3
0
 def check_fields_pyson(cls, templates, field_names=None):
     pyson_fields = {
         'recipients_pyson',
         'recipients_secondary_pyson',
         'recipients_hidden_pyson',
     }
     if field_names:
         pyson_fields &= field_names
     if not pyson_fields:
         return
     encoder = PYSONDecoder(noeval=True)
     for template in templates:
         for field in pyson_fields:
             value = getattr(template, field)
             if not value:
                 continue
             try:
                 pyson = encoder.decode(value)
             except Exception as exception:
                 raise EmailTemplateError(
                     gettext('ir.msg_email_template_invalid_field_pyson',
                             template=template.rec_name,
                             field=cls.__names__(field)['field'],
                             exception=exception)) from exception
             if not isinstance(pyson, list) and pyson.types() != {list}:
                 raise EmailTemplateError(
                     gettext(
                         'ir.msg_email_template_invalid_field_pyson_type',
                         template=template.rec_name,
                         field=cls.__names__(field)['field'],
                     ))
Пример #4
0
 def check_domain(cls, searches, field_names):
     decoder = PYSONDecoder()
     if field_names and 'domain' not in field_names:
         return
     for search in searches:
         try:
             value = decoder.decode(search.domain)
         except Exception as exception:
             raise DomainError(
                 gettext('ir.msg_view_search_invalid_domain',
                         domain=search.domain,
                         search=search.rec_name)) from exception
         if isinstance(value, PYSON):
             if not value.types() == set([list]):
                 raise DomainError(
                     gettext('ir.msg_view_search_invalid_domain',
                             domain=search.domain,
                             search=search.rec_name))
         elif not isinstance(value, list):
             raise DomainError(
                 gettext('ir.msg_view_search_invalid_domain',
                         domain=search.domain,
                         search=search.rec_name))
         else:
             try:
                 fields.domain_validate(value)
             except Exception as exception:
                 raise DomainError(
                     gettext('ir.msg_view_search_invalid_domain',
                             domain=search.domain,
                             search=search.rec_name)) from exception
Пример #5
0
 def get_search(cls, user_id=None):
     if user_id is None:
         user_id = Transaction().user
     decoder = PYSONDecoder()
     searches = cls.search([("user", "=", user_id)], order=[("model", "ASC"), ("name", "ASC")])
     result = {}
     for search in searches:
         result.setdefault(search.model, []).append((search.id, search.name, decoder.decode(search.domain)))
     return result
Пример #6
0
 def get_search(cls, user_id=None):
     if user_id is None:
         user_id = Transaction().user
     decoder = PYSONDecoder()
     searches = cls.search([
             ('user', '=', user_id),
             ], order=[('model', 'ASC'), ('name', 'ASC')])
     result = {}
     for search in searches:
         result.setdefault(search.model, []).append(
             (search.id, search.name, decoder.decode(search.domain)))
     return result
Пример #7
0
    def test_button_change(self):
        "Test button change"
        pool = Pool()
        Model = pool.get('test.modelview.button_change')

        decoder = PYSONDecoder()
        view = Model.fields_view_get()
        tree = etree.fromstring(view['arch'])
        button = tree.xpath('//button[@name="test"]')[0]

        self.assertEqual(set(decoder.decode(button.attrib['change'])),
                         {'name', 'extra'})
Пример #8
0
 def get_search(cls, user_id=None):
     if user_id is None:
         user_id = Transaction().user
     decoder = PYSONDecoder()
     searches = cls.search([
             ('user', '=', user_id),
             ], order=[('model', 'ASC'), ('name', 'ASC')])
     result = {}
     for search in searches:
         result.setdefault(search.model, []).append(
             (search.id, search.name, decoder.decode(search.domain)))
     return result
Пример #9
0
 def get_search(cls):
     decoder = PYSONDecoder()
     searches = cls.search_read(
         [],
         order=[('model', 'ASC'), ('name', 'ASC')],
         fields_names=['id', 'name', 'model', 'domain', '_delete'])
     result = {}
     for search in searches:
         result.setdefault(search['model'], []).append(
             (search['id'], search['name'],
              decoder.decode(search['domain']), search['_delete']))
     return result
Пример #10
0
 def test_action_window(action_window):
     if not action_window.res_model:
         return
     Model = pool.get(action_window.res_model)
     for active_id, active_ids in [
         (None, []),
         (1, [1]),
         (1, [1, 2]),
     ]:
         decoder = PYSONDecoder({
             'active_id': active_id,
             'active_ids': active_ids,
             'active_model': action_window.res_model,
         })
         domain = decoder.decode(action_window.pyson_domain)
         order = decoder.decode(action_window.pyson_order)
         context = decoder.decode(action_window.pyson_context)
         search_value = decoder.decode(action_window.pyson_search_value)
         if action_window.context_domain:
             domain = [
                 'AND', domain,
                 decoder.decode(action_window.context_domain)
             ]
         with Transaction().set_context(context):
             Model.search(domain,
                          order=order,
                          limit=action_window.limit)
             if search_value:
                 Model.search(search_value)
         for action_domain in action_window.act_window_domains:
             if not action_domain.domain:
                 continue
             Model.search(decoder.decode(action_domain.domain))
     if action_window.context_model:
         pool.get(action_window.context_model)
Пример #11
0
    def view_get(self, model=None):
        key = (self.id, model)
        result = self._view_get_cache.get(key)
        if result:
            return result
        if self.inherit:
            if self.model == model:
                return self.inherit.view_get(model=model)
            else:
                arch = self.inherit.arch
                view_id = self.inherit.id
        else:
            arch = self.arch
            view_id = self.id

        views = self.__class__.search([
            'OR',
            [
                ('inherit', '=', view_id),
                ('model', '=', model),
            ],
            [
                ('id', '=', view_id),
                ('inherit', '!=', None),
            ],
        ])
        views.sort(key=lambda v: self._module_index.get(v.module, -1),
                   reverse=True)
        parser = etree.XMLParser(remove_comments=True, resolve_entities=False)
        tree = etree.fromstring(arch, parser=parser)
        decoder = PYSONDecoder({'context': Transaction().context})
        for view in views:
            if view.domain and not decoder.decode(view.domain):
                continue
            if not view.arch or not view.arch.strip():
                continue
            tree_inherit = etree.fromstring(view.arch, parser=parser)
            tree = self.inherit_apply(tree, tree_inherit)
        arch = etree.tostring(tree, encoding='utf-8').decode('utf-8')
        result = {
            'type': self.rng_type,
            'view_id': view_id,
            'arch': arch,
            'field_childs': self.field_childs,
        }
        self._view_get_cache.set(key, result)
        return result
Пример #12
0
    def fields_get(cls, fields_names=None):
        """
        Return the definition of each field on the model.
        """
        definition = {}
        pool = Pool()
        Translation = pool.get('ir.translation')
        FieldAccess = pool.get('ir.model.field.access')
        ModelAccess = pool.get('ir.model.access')

        # Add translation to cache
        language = Transaction().language
        trans_args = []
        for fname, field in cls._fields.items():
            if fields_names and fname not in fields_names:
                continue
            trans_args.extend(field.definition_translations(cls, language))
        Translation.get_sources(trans_args)

        encoder = PYSONEncoder()
        decoder = PYSONDecoder(noeval=True)

        accesses = FieldAccess.get_access([cls.__name__])[cls.__name__]
        for fname, field in cls._fields.items():
            if fields_names and fname not in fields_names:
                continue
            definition[fname] = field.definition(cls, language)
            if not accesses.get(fname, {}).get('write', True):
                definition[fname]['readonly'] = True
                states = decoder.decode(definition[fname]['states'])
                states.pop('readonly', None)
                definition[fname]['states'] = encoder.encode(states)
            for right in ['create', 'delete']:
                definition[fname][right] = accesses.get(fname,
                                                        {}).get(right, True)

        for fname in list(definition.keys()):
            # filter out fields which aren't in the fields_names list
            if fields_names:
                if fname not in fields_names:
                    del definition[fname]
            elif not ModelAccess.check_relation(
                    cls.__name__, fname, mode='read'):
                del definition[fname]
        return definition
Пример #13
0
 def test_ir_action_window(self):
     'Test action windows are correctly defined'
     pool = Pool()
     ModelData = pool.get('ir.model.data')
     ActionWindow = pool.get('ir.action.act_window')
     for model_data in ModelData.search([
         ('module', '=', self.module),
         ('model', '=', 'ir.action.act_window'),
     ]):
         action_window = ActionWindow(model_data.db_id)
         if not action_window.res_model:
             continue
         Model = pool.get(action_window.res_model)
         for active_id, active_ids in [
             (None, []),
             (1, [1]),
             (1, [1, 2]),
         ]:
             decoder = PYSONDecoder({
                 'active_id': active_id,
                 'active_ids': active_ids,
                 'active_model': action_window.res_model,
             })
             domain = decoder.decode(action_window.pyson_domain)
             order = decoder.decode(action_window.pyson_order)
             context = decoder.decode(action_window.pyson_context)
             search_value = decoder.decode(action_window.pyson_search_value)
             if action_window.context_domain:
                 domain = [
                     'AND', domain,
                     decoder.decode(action_window.context_domain)
                 ]
             with Transaction().set_context(context):
                 Model.search(domain,
                              order=order,
                              limit=action_window.limit)
                 if search_value:
                     Model.search(search_value)
             for action_domain in action_window.act_window_domains:
                 if not action_domain.domain:
                     continue
                 Model.search(decoder.decode(action_domain.domain))
         if action_window.context_model:
             pool.get(action_window.context_model)
Пример #14
0
    def fields_get(cls, fields_names=None, level=0):
        """
        Return the definition of each field on the model.
        """
        definition = {}
        pool = Pool()
        Translation = pool.get('ir.translation')
        FieldAccess = pool.get('ir.model.field.access')
        ModelAccess = pool.get('ir.model.access')

        # Add translation to cache
        language = Transaction().language
        trans_args = []
        for fname, field in cls._fields.items():
            if fields_names and fname not in fields_names:
                continue
            trans_args.extend(field.definition_translations(cls, language))
        Translation.get_sources(trans_args)

        encoder = PYSONEncoder()
        decoder = PYSONDecoder(noeval=True)

        accesses = FieldAccess.get_access([cls.__name__])[cls.__name__]
        for fname, field in cls._fields.items():
            if fields_names and fname not in fields_names:
                continue
            definition[fname] = field.definition(cls, language)
            if not accesses.get(fname, {}).get('write', True):
                definition[fname]['readonly'] = True
                states = decoder.decode(definition[fname]['states'])
                states.pop('readonly', None)
                definition[fname]['states'] = encoder.encode(states)
            for right in ['create', 'delete']:
                definition[fname][right] = accesses.get(fname,
                                                        {}).get(right, True)
            if level > 0:
                relation = definition[fname].get('relation')
                if relation:
                    Relation = pool.get(relation)
                    relation_fields = Relation.fields_get(level=level - 1)
                    definition[fname]['relation_fields'] = relation_fields
                    for name, props in relation_fields.items():
                        # Convert selection into list
                        if isinstance(props.get('selection'), str):
                            change_with = props.get('selection_change_with')
                            if change_with:
                                selection = getattr(Relation(),
                                                    props['selection'])()
                            else:
                                selection = getattr(Relation,
                                                    props['selection'])()
                            props['selection'] = selection
                schema = definition[fname].get('schema_model')
                if schema:
                    Schema = pool.get(schema)
                    definition[fname]['relation_fields'] = (
                        Schema.get_relation_fields())

        for fname in list(definition.keys()):
            # filter out fields which aren't in the fields_names list
            if fields_names:
                if fname not in fields_names:
                    del definition[fname]
            elif not ModelAccess.check_relation(
                    cls.__name__, fname, mode='read'):
                del definition[fname]
        return definition
Пример #15
0
    def get(cls, model_name, mode='read'):
        "Return dictionary of non-global and global rules"
        pool = Pool()
        RuleGroup = pool.get('ir.rule.group')
        Model = pool.get('ir.model')
        RuleGroup_Group = pool.get('ir.rule.group-res.group')
        User_Group = pool.get('res.user-res.group')
        rule_table = cls.__table__()
        rule_group = RuleGroup.__table__()
        rule_group_group = RuleGroup_Group.__table__()
        user_group = User_Group.user_group_all_table()
        model = Model.__table__()
        transaction = Transaction()

        assert mode in cls.modes

        model_names = []
        model2field = defaultdict(list)

        def update_model_names(Model, path=None):
            if Model.__name__ in model_names:
                return
            model_names.append(Model.__name__)
            if path:
                model2field[Model.__name__].append(path)
            for field_name in Model.__access__:
                field = getattr(Model, field_name)
                Target = field.get_target()
                if path:
                    target_path = path + '.' + field_name
                else:
                    target_path = field_name
                update_model_names(Target, target_path)
        update_model_names(pool.get(model_name))

        cursor = transaction.connection.cursor()
        user_id = transaction.user
        # root user above constraint
        if user_id == 0:
            return {}, {}
        cursor.execute(*rule_table.join(rule_group,
                condition=rule_group.id == rule_table.rule_group
                ).join(model,
                condition=rule_group.model == model.id
                ).select(rule_table.id,
                where=(model.model.in_(model_names))
                & (getattr(rule_group, 'perm_%s' % mode) == Literal(True))
                & (rule_group.id.in_(
                        rule_group_group.join(
                            user_group,
                            condition=(rule_group_group.group
                                == user_group.group)
                            ).select(rule_group_group.rule_group,
                            where=user_group.user == user_id)
                        )
                    | (rule_group.default_p == Literal(True))
                    | (rule_group.global_p == Literal(True))
                    )))
        ids = [x for x, in cursor]

        # Test if there is no rule_group that have no rule
        cursor.execute(*rule_group.join(model,
                condition=rule_group.model == model.id
                ).select(rule_group.id,
                where=(model.model.in_(model_names))
                & ~rule_group.id.in_(rule_table.select(rule_table.rule_group))
                & rule_group.id.in_(rule_group_group.join(user_group,
                        condition=rule_group_group.group == user_group.group
                        ).select(rule_group_group.rule_group,
                        where=user_group.user == user_id))))
        no_rules = cursor.fetchone()

        clause = defaultdict(lambda: ['OR'])
        clause_global = defaultdict(lambda: ['OR'])
        decoder = PYSONDecoder(cls._get_context())
        # Use root user without context to prevent recursion
        with transaction.set_user(0), transaction.set_context(user=0):
            for rule in cls.browse(ids):
                assert rule.domain, ('Rule domain empty,'
                    'check if migration was done')
                dom = decoder.decode(rule.domain)
                target_model = rule.rule_group.model.model
                if target_model in model2field:
                    target_dom = ['OR']
                    for field in model2field[target_model]:
                        target_dom.append((field, 'where', dom))
                    dom = target_dom
                if rule.rule_group.global_p:
                    clause_global[rule.rule_group].append(dom)
                else:
                    clause[rule.rule_group].append(dom)

            if no_rules:
                group_id = no_rules[0]
                clause[RuleGroup(group_id)] = []

        return clause, clause_global
Пример #16
0
    def get(cls, model_name, mode='read'):
        "Return dictionary of non-global and global rules"
        pool = Pool()
        RuleGroup = pool.get('ir.rule.group')
        Model = pool.get('ir.model')
        RuleGroup_Group = pool.get('ir.rule.group-res.group')
        User_Group = pool.get('res.user-res.group')
        rule_table = cls.__table__()
        rule_group = RuleGroup.__table__()
        rule_group_group = RuleGroup_Group.__table__()
        user_group = User_Group.__table__()
        model = Model.__table__()
        transaction = Transaction()

        assert mode in cls.modes

        cursor = transaction.connection.cursor()
        user_id = transaction.user
        # root user above constraint
        if user_id == 0:
            user_id = transaction.context.get('user')
            if not user_id:
                return {}, {}
        cursor.execute(*rule_table.join(
            rule_group, condition=rule_group.id == rule_table.rule_group
        ).join(model, condition=rule_group.model == model.id).select(
            rule_table.id,
            where=(model.model == model_name)
            & (getattr(rule_group, 'perm_%s' % mode) == Literal(True))
            & (rule_group.id.in_(
                rule_group_group.join(
                    user_group,
                    condition=(rule_group_group.group == user_group.group
                               )).select(rule_group_group.rule_group,
                                         where=user_group.user == user_id))
               | (rule_group.default_p == Literal(True))
               | (rule_group.global_p == Literal(True)))))
        ids = [x for x, in cursor]

        # Test if there is no rule_group that have no rule
        cursor.execute(*rule_group.join(
            model, condition=rule_group.model == model.id).select(
                rule_group.id,
                where=(model.model == model_name)
                & ~rule_group.id.in_(rule_table.select(rule_table.rule_group))
                & rule_group.id.in_(
                    rule_group_group.join(user_group,
                                          condition=rule_group_group.group ==
                                          user_group.group).
                    select(rule_group_group.rule_group,
                           where=user_group.user == user_id))))
        no_rules = cursor.fetchone()

        clause = defaultdict(lambda: ['OR'])
        clause_global = defaultdict(lambda: ['OR'])
        decoder = PYSONDecoder(cls._get_context())
        # Use root user without context to prevent recursion
        with transaction.set_user(0), transaction.set_context(user=0):
            for rule in cls.browse(ids):
                assert rule.domain, ('Rule domain empty,'
                                     'check if migration was done')
                dom = decoder.decode(rule.domain)
                if rule.rule_group.global_p:
                    clause_global[rule.rule_group].append(dom)
                else:
                    clause[rule.rule_group].append(dom)

            if no_rules:
                group_id = no_rules[0]
                clause[RuleGroup(group_id)] = []

        return clause, clause_global