diff --git a/auditlog_security/models/__init__.py b/auditlog_security/models/__init__.py index db0c1ec6291..6a93aed1079 100644 --- a/auditlog_security/models/__init__.py +++ b/auditlog_security/models/__init__.py @@ -1,7 +1,7 @@ -# Copyright 2021-2024 Therp B.V. +# Copyright 2021-2025 Therp B.V. # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from . import auditlog_rule from . import auditlog_line_access_rule -from . import ir_rule +from . import auditlog_log from . import auditlog_log_line diff --git a/auditlog_security/models/auditlog_line_access_rule.py b/auditlog_security/models/auditlog_line_access_rule.py index e7651ff41d2..84013ec950f 100644 --- a/auditlog_security/models/auditlog_line_access_rule.py +++ b/auditlog_security/models/auditlog_line_access_rule.py @@ -1,7 +1,7 @@ # Copyright 2021-2024 Therp B.V. # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo import api, fields, models +from odoo import fields, models class AuditlogLineAccessRule(models.Model): @@ -23,96 +23,3 @@ class AuditlogLineAccessRule(models.Model): "auditlog.rule", "auditlog_access_rule_ids", readonly=True, ondelete="cascade" ) state = fields.Selection(related="auditlog_rule_id.state", readonly=True) - - def needs_rule(self): - self.ensure_one() - return bool(self.group_ids) - - def get_linked_rules(self): - return self.env["ir.rule"].search( - [("auditlog_line_access_rule_id", "in", self.ids)] - ) - - def unlink(self): - to_delete = self.get_linked_rules() - res = super(AuditlogLineAccessRule, self).unlink() - if res: - res = res and to_delete.unlink() - return res - - def add_default_group_if_needed(self): - self.ensure_one() - res = False - if not self.group_ids and self.field_ids: - res = self.with_context(no_iter=True).write( - {"group_ids": [(6, 0, [self.env.ref("base.group_user").id])]} - ) - return res - - @api.model_create_multi - def create(self, vals): - res = super(AuditlogLineAccessRule, self).create(vals) - res.add_default_group_if_needed() - res.regenerate_rules() - return res - - def write(self, vals): - res = super(AuditlogLineAccessRule, self).write(vals) - for this in self: - added = this.add_default_group_if_needed() - if ( - any( - [ - x in vals - for x in ("group_ids", "field_ids", "model_id", "all_fields") - ] - ) - or added - ): - this.regenerate_rules() - - return res - - def remove_rules(self): - for this in self: - this.get_linked_rules().unlink() - - def regenerate_rules(self): - for this in self: - this.remove_rules() - dict_values = this._prepare_rule_values() - for values in dict_values: - self.env["ir.rule"].create(values) - - def _prepare_rule_values(self): - self.ensure_one() - if not self.needs_rule(): - return [] - domain_force = "[" + " ('log_id.model_id' , '=', %s)," % (self.model_id.id) - if self.field_ids: - domain_force = "[('field_id', 'in', %s)]" % (self.field_ids.ids) - model = self.env.ref("auditlog.model_auditlog_log_line") - else: - domain_force = "[('model_id', '=', %s)]" % (self.model_id.id) - model = self.env.ref("auditlog.model_auditlog_log") - auditlog_security_group = self.env.ref( - "auditlog_security.group_can_view_audit_logs" - ) - return [ - { - "name": "auditlog_extended_%s" % self.id, - "model_id": model.id, - "groups": [(6, 0, self.group_ids.ids)], - "perm_read": True, - "domain_force": domain_force, - "auditlog_line_access_rule_id": self.id, - }, - { - "name": "auditlog_extended_%s" % self.id, - "model_id": model.id, - "groups": [(6, 0, [auditlog_security_group.id])], - "perm_read": True, - "domain_force": [(1, "=", 1)], - "auditlog_line_access_rule_id": self.id, - }, - ] diff --git a/auditlog_security/models/auditlog_log.py b/auditlog_security/models/auditlog_log.py new file mode 100644 index 00000000000..ae01442af80 --- /dev/null +++ b/auditlog_security/models/auditlog_log.py @@ -0,0 +1,29 @@ +# Copyright 2025 Therp B.V. +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class AuditlogLog(models.Model): + _inherit = "auditlog.log" + + rule_id = fields.Many2one("auditlog.rule", compute="_compute_rule_id", store=True) + allowed_group_ids = fields.Many2many( + "res.groups", compute="_compute_allowed_group_ids", store=True + ) + + @api.depends("model_id") + def _compute_rule_id(self): + for log in self: + log.rule_id = self.env["auditlog.rule"].search( + [("model_id", "=", log.model_id.id)] + ) + + @api.depends("rule_id") + def _compute_allowed_group_ids(self): + for log in self: + log.allowed_group_ids = ( + self.env["auditlog.line.access.rule"] + .search([("auditlog_rule_id", "=", log.rule_id.id)]) + .group_ids + ) diff --git a/auditlog_security/models/auditlog_log_line.py b/auditlog_security/models/auditlog_log_line.py index 5738b58d0a0..244838e60f5 100644 --- a/auditlog_security/models/auditlog_log_line.py +++ b/auditlog_security/models/auditlog_log_line.py @@ -20,6 +20,9 @@ class AuditlogLogLine(models.Model): "ir.model", compute="_compute_model_id", store=True, index=True ) res_id = fields.Integer(compute="_compute_res_id", store=True, index=True) + allowed_group_ids = fields.Many2many( + "res.groups", compute="_compute_allowed_group_ids", store=True + ) @api.depends("log_id.method") def _compute_method(self): @@ -40,3 +43,25 @@ def _compute_model_id(self): def _compute_res_id(self): for this in self: this.res_id = this.log_id.res_id + + @api.depends( + "field_id", + "log_id.rule_id", + "log_id.rule_id.auditlog_line_access_rule_ids.group_ids", + "log_id.rule_id.auditlog_line_access_rule_ids.field_ids", + ) + def _compute_allowed_group_ids(self): + for line in self: + # Do not give a value to sql model + if line._name == "auditlog.log.line.view": + continue + line.allowed_group_ids = ( + self.env["auditlog.line.access.rule"] + .search( + [ + ("auditlog_rule_id", "=", line.log_id.rule_id.id), + ("field_ids", "in", line.field_id.ids), + ] + ) + .group_ids + ) diff --git a/auditlog_security/models/auditlog_rule.py b/auditlog_security/models/auditlog_rule.py index eceba51f42e..79d322903ba 100644 --- a/auditlog_security/models/auditlog_rule.py +++ b/auditlog_security/models/auditlog_rule.py @@ -118,10 +118,7 @@ def subscribe(self): for rule in self: server_action = rule._create_server_action() server_action.create_action() - res = super(AuditlogRule, self).subscribe() - for rule in self: - rule.auditlog_line_access_rule_ids.regenerate_rules() - # rule now will have "View Log" Action, make that visible only for admin + res = super().subscribe() if res: self.action_id.write( {"groups_id": [(6, 0, [self.env.ref("base.group_system").id])]} @@ -129,8 +126,6 @@ def subscribe(self): return res def unsubscribe(self): - for rule in self: - rule.auditlog_line_access_rule_ids.remove_rules() for rule in self: rule.server_action_id.unlink() - return super(AuditlogRule, self).unsubscribe() + return super().unsubscribe() diff --git a/auditlog_security/models/ir_rule.py b/auditlog_security/models/ir_rule.py deleted file mode 100644 index 8def6cc7115..00000000000 --- a/auditlog_security/models/ir_rule.py +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright 2021-2024 Therp B.V. -# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). - -from odoo import fields, models - - -class IrRule(models.Model): - _inherit = "ir.rule" - - auditlog_line_access_rule_id = fields.Many2one( - "auditlog.line.access.rule", - required=False, - index=True, - ondelete="cascade", - help="Auditlog line access Rule that generated this ir.rule", - ) diff --git a/auditlog_security/security/ir_rule.xml b/auditlog_security/security/ir_rule.xml index dfea064c1c5..d247e7ab499 100644 --- a/auditlog_security/security/ir_rule.xml +++ b/auditlog_security/security/ir_rule.xml @@ -15,4 +15,22 @@ + + Access to auditlog.log + + [('allowed_group_ids', 'in', user.groups_id.ids)] + + + + + Access to auditlog.log.line + + [('allowed_group_ids', 'in', user.groups_id.ids)] + + +