diff --git a/addons/auth_totp/models/res_users.py b/addons/auth_totp/models/res_users.py index 7ed28beddd3..bb703e3ee77 100644 --- a/addons/auth_totp/models/res_users.py +++ b/addons/auth_totp/models/res_users.py @@ -21,7 +21,7 @@ _logger = logging.getLogger(__name__) class Users(models.Model): _inherit = 'res.users' - totp_secret = fields.Char(copy=False, groups=".") # no access + totp_secret = fields.Char(copy=False, groups=fields.NO_ACCESS) totp_enabled = fields.Boolean(string="TOTP enabled", compute='_compute_totp_enabled') def __init__(self, pool, cr): diff --git a/odoo/addons/base/models/res_users.py b/odoo/addons/base/models/res_users.py index 11d0f0980ae..33a84f53292 100644 --- a/odoo/addons/base/models/res_users.py +++ b/odoo/addons/base/models/res_users.py @@ -1475,7 +1475,7 @@ class CheckIdentity(models.TransientModel): _name = 'res.users.identitycheck' _description = "Password Check Wizard" - request = fields.Char(readonly=True, groups='.') # no access + request = fields.Char(readonly=True, groups=fields.NO_ACCESS) password = fields.Char() def run_check(self): diff --git a/odoo/addons/test_access_rights/models.py b/odoo/addons/test_access_rights/models.py index 52eee53979a..ed435324208 100644 --- a/odoo/addons/test_access_rights/models.py +++ b/odoo/addons/test_access_rights/models.py @@ -15,6 +15,7 @@ class SomeObj(models.Model): default=5 ) forbidden2 = fields.Integer(groups='test_access_rights.test_group') + forbidden3 = fields.Integer(groups=fields.NO_ACCESS) class Container(models.Model): _name = 'test_access_right.container' @@ -65,4 +66,4 @@ class ResPartner(models.Model): def _get_company_currency(self): for partner in self: - partner.currency_id = partner.sudo().company_id.currency_id \ No newline at end of file + partner.currency_id = partner.sudo().company_id.currency_id diff --git a/odoo/addons/test_access_rights/tests/test_feedback.py b/odoo/addons/test_access_rights/tests/test_feedback.py index 0e0afbe5b50..f9a8f3b5e1b 100644 --- a/odoo/addons/test_access_rights/tests/test_feedback.py +++ b/odoo/addons/test_access_rights/tests/test_feedback.py @@ -390,6 +390,20 @@ Fields: % self.user.id ) + with self.assertRaises(AccessError) as ctx: + _ = self.record.forbidden3 + + self.assertEqual( + ctx.exception.args[0], + """The requested operation can not be completed due to security restrictions. + +Document type: Object For Test Access Right (test_access_right.some_obj) +Operation: read +User: %s +Fields: +- forbidden3 (always forbidden)""" % self.user.id + ) + def test_write(self): self.env.ref('base.group_no_one').write( {'users': [(4, self.user.id)]}) diff --git a/odoo/fields.py b/odoo/fields.py index 4695eb2c43d..f1c2942cc29 100644 --- a/odoo/fields.py +++ b/odoo/fields.py @@ -29,6 +29,9 @@ from odoo.exceptions import CacheMiss DATE_LENGTH = len(date.today().strftime(DATE_FORMAT)) DATETIME_LENGTH = len(datetime.now().strftime(DATETIME_FORMAT)) +# hacky-ish way to prevent access to a field through the ORM (except for sudo mode) +NO_ACCESS='.' + IR_MODELS = ( 'ir.model', 'ir.model.data', 'ir.model.fields', 'ir.model.fields.selection', 'ir.model.relation', 'ir.model.constraint', 'ir.module.module', diff --git a/odoo/models.py b/odoo/models.py index ba9cb15b6c4..a3b221433f7 100644 --- a/odoo/models.py +++ b/odoo/models.py @@ -2888,6 +2888,9 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})): }) def format_groups(field): + if field.groups == '.': + return _("always forbidden") + anyof = self.env['res.groups'] noneof = self.env['res.groups'] for g in field.groups.split(','):