diff --git a/base_model_restrict_update/models/ir_model_access.py b/base_model_restrict_update/models/ir_model_access.py
index e5da3aa46..8ba3bb5a8 100644
--- a/base_model_restrict_update/models/ir_model_access.py
+++ b/base_model_restrict_update/models/ir_model_access.py
@@ -11,25 +11,56 @@ class IrModelAccess(models.Model):
@api.model
@tools.ormcache_context(
- "self._uid", "model", "mode", "raise_exception", keys=("lang",)
+ "self.env.uid",
+ "self.env.su",
+ "model",
+ "mode",
+ "raise_exception",
+ keys=("lang",),
)
def check(self, model, mode="read", raise_exception=True):
if self.env.su:
return True
res = super().check(model, mode, raise_exception)
- self._cr.execute(
- "SELECT restrict_update FROM ir_model WHERE model = %s", (model,)
- )
- query_res = self._cr.dictfetchone()
- if (
- query_res["restrict_update"]
- and mode != "read"
- and not self.env.user.unrestrict_model_update
- ):
- if raise_exception:
+ if mode != "read" and raise_exception:
+ if self._test_readonly(model) or self._test_restrict_update(model):
raise AccessError(
_("You are only allowed to read this record. (%s - %s)")
% (model, mode)
)
- return False
return res
+
+ @api.model
+ def _test_readonly(self, model):
+ exclude_models = self._readonly_exclude_models()
+ if model not in exclude_models and self.env.user.is_readonly_user:
+ return True
+ return False
+
+ @api.model
+ def _test_restrict_update(self, model):
+ self.env.cr.execute(
+ "SELECT restrict_update FROM ir_model WHERE model = %s", (model,)
+ )
+ query_res = self.env.cr.dictfetchone()
+ if query_res["restrict_update"] and not self.env.user.unrestrict_model_update:
+ return True
+ return False
+
+ @api.model
+ def _readonly_exclude_models(self):
+ """ Models updtate/create by system, and should be excluded from checking """
+ return (
+ self.sudo()
+ .search(
+ [
+ ("group_id", "=", False),
+ "|",
+ ("perm_write", "=", True),
+ "|",
+ ("perm_create", "=", True),
+ ("perm_unlink", "=", True),
+ ]
+ )
+ .mapped("model_id.model")
+ )
diff --git a/base_model_restrict_update/models/res_users.py b/base_model_restrict_update/models/res_users.py
index 0c3ce733d..e3bfc2cb3 100644
--- a/base_model_restrict_update/models/res_users.py
+++ b/base_model_restrict_update/models/res_users.py
@@ -1,7 +1,8 @@
# Copyright 2021 Quartile Limited
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
-from odoo import fields, models
+from odoo import _, api, fields, models
+from odoo.exceptions import UserError
class ResUsers(models.Model):
@@ -11,7 +12,21 @@ class ResUsers(models.Model):
"Unrestrict Model Update",
help="Set to true and the user can update restricted model.",
)
+ is_readonly_user = fields.Boolean(
+ "Ready User",
+ help="Set to true and the user are readonly user on all models",
+ )
+
+ @api.constrains("is_readonly_user")
+ def _check_is_readonly_user(self):
+ for user in self:
+ if self.env.ref("base.group_system") in user.groups_id:
+ raise UserError(_("You cannot set admin user as a readonly user."))
def toggle_unrestrict_model_update(self):
for record in self:
record.unrestrict_model_update = not record.unrestrict_model_update
+
+ def toggle_is_readonly_user(self):
+ for record in self:
+ record.is_readonly_user = not record.is_readonly_user
diff --git a/base_model_restrict_update/readme/CONFIGURE.rst b/base_model_restrict_update/readme/CONFIGURE.rst
index 5ac08602f..850b0ad86 100644
--- a/base_model_restrict_update/readme/CONFIGURE.rst
+++ b/base_model_restrict_update/readme/CONFIGURE.rst
@@ -1,2 +1,3 @@
Enable the "Update Restrict Model" of specific model to restrict update from unpermitted users.
-To set an user as a permitted user to update restricted model(s), click on "Grant Update Permit" in user form.
+To set a user as a permitted user to update restricted model(s), click on "Grant Update Permit" in user form.
+Optionally, to set a user as readonly user to all models, click on "Readonly User" in user form.
diff --git a/base_model_restrict_update/tests/test_base_model_restrict_update.py b/base_model_restrict_update/tests/test_base_model_restrict_update.py
index fa3bfd86c..b098c0881 100644
--- a/base_model_restrict_update/tests/test_base_model_restrict_update.py
+++ b/base_model_restrict_update/tests/test_base_model_restrict_update.py
@@ -33,24 +33,32 @@ class TestBaseModelRestrictUpdate(SavepointCase):
def test_01_create_partner(self):
with self.assertRaises(AccessError):
- self.env["res.partner"].sudo(self.restrict_test_user.id).create(
+ self.env["res.partner"].with_user(self.restrict_test_user.id).create(
{"name": "Test Partner"}
)
- self.env["res.partner"].sudo(self.permit_test_user.id).create(
+ self.env["res.partner"].with_user(self.permit_test_user.id).create(
{"name": "Test Partner"}
)
def test_02_update_partner(self):
with self.assertRaises(AccessError):
- self.test_partner.sudo(self.restrict_test_user.id).update(
+ self.test_partner.with_user(self.restrict_test_user.id).update(
{"name": "Test Partner 2"}
)
- self.test_partner.sudo(self.permit_test_user.id).update(
+ self.test_partner.with_user(self.permit_test_user.id).update(
{"name": "Test Partner 2"}
)
def test_03_unlink_partner(self):
test_partner = self.test_partner.sudo().copy()
with self.assertRaises(AccessError):
- test_partner.sudo(self.restrict_test_user.id).unlink()
- test_partner.sudo(self.permit_test_user.id).unlink()
+ test_partner.with_user(self.restrict_test_user.id).unlink()
+ test_partner.with_user(self.permit_test_user.id).unlink()
+
+ def test_04_readonly_user_update_partner(self):
+ self.permit_test_user.toggle_is_readonly_user()
+ self.assertTrue(self.permit_test_user.is_readonly_user)
+ with self.assertRaises(AccessError):
+ self.test_partner.with_user(self.permit_test_user.id).update(
+ {"name": "Test Partner 2"}
+ )
diff --git a/base_model_restrict_update/views/res_users_views.xml b/base_model_restrict_update/views/res_users_views.xml
index 1d16942ee..aa0f5a1e8 100644
--- a/base_model_restrict_update/views/res_users_views.xml
+++ b/base_model_restrict_update/views/res_users_views.xml
@@ -12,6 +12,7 @@
type="object"
class="oe_stat_button"
icon="fa-pencil"
+ attrs="{'invisible': [('is_readonly_user', '=', True)]}"
>
+