Skip to content

Seguridad de Modelos

Además de administrar manualmente el acceso mediante un código personalizado, Odoo proporciona dos mecanismos principales para administrar o restringir el acceso a los datos. Ambos mecanismos están vinculados a usuarios específicos a través de grupos: un usuario pertenece a cualquier número de grupos y los mecanismos de seguridad están asociados a grupos, aplicando así mecanismos de seguridad a los usuarios.

Los permisos de acceso se definen como registros del modelo ir.model.access. Cada derecho de acceso está asociado a un modelo, un grupo (o ningún grupo para acceso global) y un conjunto de permisos: crear, leer, escribir y desvincular. Dichos permisos de acceso generalmente se definen en un archivo CSV llamado ir.model.access.csv de la siguiente forma:

id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
access_test_model,access_test_model,model_test_model,base.group_user,1,0,0,0
  • id, es un identificador externo.

  • name, es el nombre del modelo ir.model.access.

  • model_id / id, se refiere al modelo al que se aplica el permiso de acceso. La forma estándar de referirse al modelo es model_<model_name>, donde <model_name > es el _name del modelo con el . reemplazado por _

  • group_id / id, se refiere al grupo al que se aplica el permiso de acceso.

  • perm_read, perm_write, perm_create, perm_unlink: permisos de lectura, escritura, creación y desvinculación.

Las reglas de registro son condiciones que deben cumplirse para que se permita una operación. Estas se evalúan registro por registro, siguiendo los permisos de acceso.

Además son predeterminadas: si los permisos de acceso otorgan acceso y no se aplica ninguna regla a la operación y el modelo para el usuario, se otorga el acceso.

A diferencia de los permisos de acceso se definen en el modelo ir.rule y cuentan con el campo domain_force para aplicar un dominio a las operaciones.

<record model="ir.rule" id="record_restricted_test_model_rule">
<field name="name">Restricted Record to Test Model</field>
<field name="model_id" ref="model_test_model"/>
<field name="global" eval="True"/>
<field name="domain_force">
[('company_id', 'in', company_ids)]
</field>
</record>
  • Las reglas globales se cruzan, si se aplican dos reglas globales, entonces ambas deben cumplirse para que se otorgue el acceso, esto significa que agregar reglas globales siempre restringe aún más el acceso.

  • Las reglas de grupo se unifican, si se aplican dos reglas de grupo, entonces se puede satisfacer cualquiera de las dos para que se otorgue el acceso. Esto significa que agregar reglas de grupo puede expandir el acceso, pero no más allá de los límites definidos por las reglas globales.

Los conjuntos de reglas globales y grupales se cruzan, lo que significa que la primera regla grupal que se agregue a un conjunto de reglas global determinado restringirá el acceso.

Cuando el campo company_id se hace obligatorio en un modelo, una buena práctica es establecer una empresa predeterminada. Facilita el flujo de configuración para el usuario o incluso garantiza su validez cuando la empresa está oculta a la vista. De hecho, la empresa suele estar oculta si el usuario no tiene acceso a varias empresas (es decir, cuando el usuario no tiene la base del grupo.group_multi_company).

from odoo import api, fields, models
class Record(models.Model):
_name = 'record.restricted'
_check_company_auto = True
company_id = fields.Many2one(
'res.company', required=True, default=lambda self: self.env.company
)
other_record_id = fields.Many2one('other.record', check_company=True)

Como se indicó anteriormente, la empresa generalmente está oculta a la vista si el usuario no tiene acceso a varias empresas. Esto se evalúa con la base grupal.grupo_multi_empresa.

<record model="ir.ui.view" id="record_form_view">
<field name="name">record.restricted.form</field>
<field name="model">record.restricted</field>
<field name="arch" type="xml">
<form>
<sheet>
<group>
<group>
<field name="company_id" groups="base.group_multi_company"/>
<field name="other_record_id"/>
</group>
</group>
</sheet>
</form>
</field>
</record>

Al trabajar con registros compartidos entre empresas o restringidos a una sola empresa, debemos tener cuidado de que un usuario no tenga acceso a registros pertenecientes a otras empresas. Esto se logra con reglas de seguridad basadas en company_ids, que contienen las empresas actuales del usuario (las empresas que el usuario verificó en el widget multiempresa).

<!-- Shareable Records -->
<record model="ir.rule" id="record_shared_company_rule">
<field name="name">Shared Record: multi-company</field>
<field name="model_id" ref="model_record_shared"/>
<field name="global" eval="True"/>
<field name="domain_force">
['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]
</field>
</record>
<!-- Company-restricted Records -->
<record model="ir.rule" id="record_restricted_company_rule">
<field name="name">Restricted Record: multi-company</field>
<field name="model_id" ref="model_record_restricted"/>
<field name="global" eval="True"/>
<field name="domain_force">
[('company_id', 'in', company_ids)]
</field>
</record>