Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions auditlog_security/models/__init__.py
Original file line number Diff line number Diff line change
@@ -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
95 changes: 1 addition & 94 deletions auditlog_security/models/auditlog_line_access_rule.py
Original file line number Diff line number Diff line change
@@ -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):
Expand All @@ -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,
},
]
29 changes: 29 additions & 0 deletions auditlog_security/models/auditlog_log.py
Original file line number Diff line number Diff line change
@@ -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
)
25 changes: 25 additions & 0 deletions auditlog_security/models/auditlog_log_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -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
)
9 changes: 2 additions & 7 deletions auditlog_security/models/auditlog_rule.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,19 +118,14 @@ 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])]}
)
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()
16 changes: 0 additions & 16 deletions auditlog_security/models/ir_rule.py

This file was deleted.

18 changes: 18 additions & 0 deletions auditlog_security/security/ir_rule.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,22 @@
<field name="perm_unlink" eval="False" />
</record>

<record id="auditlog_log_rule" model="ir.rule">
<field name="name">Access to auditlog.log</field>
<field name="model_id" ref="auditlog.model_auditlog_log" />
<field
name="domain_force"
>[('allowed_group_ids', 'in', user.groups_id.ids)]</field>
<field name="perm_read" eval="False" />
</record>

<record id="auditlog_log_line_rule" model="ir.rule">
<field name="name">Access to auditlog.log.line</field>
<field name="model_id" ref="auditlog.model_auditlog_log_line" />
<field
name="domain_force"
>[('allowed_group_ids', 'in', user.groups_id.ids)]</field>
<field name="perm_read" eval="False" />
</record>

</odoo>
Loading