Skip to content

Instantly share code, notes, and snippets.

@arisnew
Created July 3, 2024 06:41
Show Gist options
  • Select an option

  • Save arisnew/6aa13a53079ad6a55abeb9a45d0687aa to your computer and use it in GitHub Desktop.

Select an option

Save arisnew/6aa13a53079ad6a55abeb9a45d0687aa to your computer and use it in GitHub Desktop.
Debug detail access rule odoo

Jika kita mendapatkan error access right odoo yg mungkin tidak tahu detail kesalahan itu dibaris kode yg mana, kita bisa traceback lebih detail. Kita perlu edit model core nya odoo.

Ref https://www.odoo.com/forum/help-1/how-to-debug-access-permissions-121603

Berikut contoh pesan errornya:

Due to security restrictions, you are not allowed to access 'Sale Order' (sale.order) records.

Records: New (id=NewId_0x7f0cf9b06828)
User: ADMINISTRATOR (id=2)

This restriction is due to the following rules:


Contact your administrator to request access if necessary.

Contoh untuk case read error di atas, kita bs tambahkan traceback sbb:

    # odoo/models.py
    # ...
    
    import traceback
    
    # ...

    def _read(self, fields):
        """ Read the given fields of the records in ``self`` from the database,
            and store them in cache. Access errors are also stored in cache.
            Skip fields that are not stored.

            :param field_names: list of column names of model ``self``; all those
                fields are guaranteed to be read
            :param inherited_field_names: list of column names from parent
                models; some of those fields may not be read
        """
        if not self:
            return
        self.check_access_rights('read')

        # if a read() follows a write(), we must flush updates, as read() will
        # fetch from database and overwrites the cache (`test_update_with_id`)
        self.flush(fields, self)

        field_names = []
        inherited_field_names = []
        for name in fields:
            field = self._fields.get(name)
            if field:
                if field.store:
                    field_names.append(name)
                elif field.base_field.store:
                    inherited_field_names.append(name)
            else:
                _logger.warning("%s.read() with unknown field '%s'", self._name, name)

        # determine the fields that are stored as columns in tables; ignore 'id'
        fields_pre = [
            field
            for field in (self._fields[name] for name in field_names + inherited_field_names)
            if field.name != 'id'
            if field.base_field.store and field.base_field.column_type
            if not (field.inherited and callable(field.base_field.translate))
        ]

        if fields_pre:
            env = self.env
            cr, user, context, su = env.args

            # make a query object for selecting ids, and apply security rules to it
            query = Query(self.env.cr, self._table, self._table_query)
            self._apply_ir_rules(query, 'read')

            # the query may involve several tables: we need fully-qualified names
            def qualify(field):
                col = field.name
                res = self._inherits_join_calc(self._table, field.name, query)
                if field.type == 'binary' and (context.get('bin_size') or context.get('bin_size_' + col)):
                    # PG 9.2 introduces conflicting pg_size_pretty(numeric) -> need ::cast
                    res = 'pg_size_pretty(length(%s)::bigint)' % res
                return '%s as "%s"' % (res, col)

            # selected fields are: 'id' followed by fields_pre
            qual_names = [qualify(name) for name in [self._fields['id']] + fields_pre]

            # determine the actual query to execute (last parameter is added below)
            query.add_where('"%s".id IN %%s' % self._table)
            query_str, params = query.select(*qual_names)

            result = []
            for sub_ids in cr.split_for_in_conditions(self.ids):
                cr.execute(query_str, params + [sub_ids])
                result += cr.fetchall()
        else:
            self.check_access_rule('read')
            result = [(id_,) for id_ in self.ids]

        fetched = self.browse()
        if result:
            cols = zip(*result)
            ids = next(cols)
            fetched = self.browse(ids)

            for field in fields_pre:
                values = next(cols)
                if context.get('lang') and not field.inherited and callable(field.translate):
                    translate = field.get_trans_func(fetched)
                    values = list(values)
                    for index in range(len(ids)):
                        values[index] = translate(ids[index], values[index])

                # store values in cache
                self.env.cache.update(fetched, field, values)

            # determine the fields that must be processed now;
            # for the sake of simplicity, we ignore inherited fields
            for name in field_names:
                field = self._fields[name]
                if not field.column_type:
                    field.read(fetched)
                if field.deprecated:
                    _logger.warning('Field %s is deprecated: %s', field, field.deprecated)

        # possibly raise exception for the records that could not be read
        missing = self - fetched
        if missing:
            extras = fetched - self
            if extras:
                raise AccessError(
                    _("Database fetch misses ids ({}) and has extra ids ({}), may be caused by a type incoherence in a previous request").format(
                        missing._ids, extras._ids,
                    ))
            # mark non-existing records in missing
            forbidden = missing.exists()
            if forbidden:
                # debug by arisnew
                _logger.info('======start here==========')
                for xline in traceback.format_stack():
                    _logger.info(xline.strip())
                _logger.info('======end here==========')
                raise self.env['ir.rule']._make_access_error('read', forbidden)

Jika kita cek log:

// ...
web_1  | 2024-07-03 06:20:01,507 1 INFO DBODOOCKWI odoo.models: File "/usr/lib/python3/dist-packages/odoo/fields.py", line 1157, in recompute
web_1  |     self.compute_value(record) 
web_1  | 2024-07-03 06:20:01,507 1 INFO DBODOOCKWI odoo.models: File "/usr/lib/python3/dist-packages/odoo/fields.py", line 1177, in compute_value
web_1  |     records._compute_field_value(self) 
web_1  | 2024-07-03 06:20:01,508 1 INFO DBODOOCKWI odoo.models: File "/usr/lib/python3/dist-packages/odoo/addons/sale/models/sale.py", line 516, in _compute_field_value
web_1  |     super()._compute_field_value(field) 
web_1  | 2024-07-03 06:20:01,508 1 INFO DBODOOCKWI odoo.models: File "/usr/lib/python3/dist-packages/odoo/addons/mail/models/mail_thread.py", line 410, in _compute_field_value
web_1  |     return super()._compute_field_value(field) 
web_1  | 2024-07-03 06:20:01,508 1 INFO DBODOOCKWI odoo.models: File "/usr/lib/python3/dist-packages/odoo/models.py", line 4074, in _compute_field_value
web_1  |     getattr(self, field.compute)() 
web_1  | 2024-07-03 06:20:01,508 1 INFO DBODOOCKWI odoo.models: File "/mnt/extra-addons/ckwi-addons/jidoka_sale/models/sale.py", line 90, in _get_document_type
web_1  |     self.write({'document_type': 'marketing_quotation'}) 
web_1  | 2024-07-03 06:20:01,508 1 INFO DBODOOCKWI odoo.models: File "/mnt/extra-addons/ckwi-addons/auditlog/models/rule.py", line 395, in write_full
web_1  |     .read(fields_list) 
web_1  | 2024-07-03 06:20:01,508 1 INFO DBODOOCKWI odoo.models: File "/usr/lib/python3/dist-packages/odoo/models.py", line 3023, in read
web_1  |     self._read(stored_fields) 
web_1  | 2024-07-03 06:20:01,508 1 INFO DBODOOCKWI odoo.models: File "/usr/lib/python3/dist-packages/odoo/models.py", line 3187, in _read
web_1  |     for xline in traceback.format_stack(): 
web_1  | 2024-07-03 06:20:01,508 1 INFO DBODOOCKWI odoo.addons.base.models.ir_rule: Access Denied by record rules for operation: read on record ids: [], uid: 2, model: sale.order 
web_1  | 2024-07-03 06:20:01,512 1 WARNING DBODOOCKWI odoo.http: Due to security restrictions, you are not allowed to access 'Sale Order' (sale.order) records.
web_1  | 
web_1  | Records: New (id=NewId_0x7f0cf9b06828)
web_1  | User: ADMINISTRATOR (id=2)
web_1  | 
web_1  | This restriction is due to the following rules:
web_1  | 
web_1  | 
web_1  | Contact your administrator to request access if necessary. 
// ...

Kita dapat mengetahui eksekusi yg bermasalah dimana, misal contoh di atas pada method _get_document_type.

Semoga bermanfaat.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment