diff --git a/auditlog_security/README.rst b/auditlog_security/README.rst new file mode 100644 index 00000000000..438dfbd137a --- /dev/null +++ b/auditlog_security/README.rst @@ -0,0 +1,95 @@ +========================== +Audit Log User Permissions +========================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--tools-lightgray.png?logo=github + :target: https://github.com/OCA/server-tools/tree/11.0/auditlog_security + :alt: OCA/server-tools +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/server-tools-11-0/server-tools-11-0-auditlog_security + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/149/11.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows extends auditlog, allowing specific log lines to be viewed only +by users belonging to specific views, while all other lines are allowed only to +administrator. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +Go to `Settings / Technical / Audit / Rules` to subscribe rules. A rule defines +which operations to log for a given data model. +The rule is now extended with a new field permission_ids, that tells us wich groups will +be allowed to read the lines produced by this rule. +If permission_ids is left empty, the default will be: +"auditlog lines visible only by user in Settings group, which is the default +for the auditlog module" + + +Then, check logs in the `Settings / Technical / Audit / Logs` menu. You can +group them by user sessions, date, data model , HTTP requests. + +Known issues / Roadmap +====================== + + + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Therp B.V. + +Contributors +~~~~~~~~~~~~ + +* Giovanni Francesco Capalbo + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/server-tools `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/auditlog_security/__init__.py b/auditlog_security/__init__.py new file mode 100644 index 00000000000..31660d6a965 --- /dev/null +++ b/auditlog_security/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from . import models diff --git a/auditlog_security/__manifest__.py b/auditlog_security/__manifest__.py new file mode 100644 index 00000000000..782da1100cc --- /dev/null +++ b/auditlog_security/__manifest__.py @@ -0,0 +1,23 @@ +# Copyright 2021 Therp B.V. +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +{ + "name": "Audit Log User Permissions", + "version": "11.0.1.0.0", + "author": "Therp B.V.,Odoo Community Association (OCA)", + "license": "AGPL-3", + "website": "https://github.com/OCA/server-tools/", + "category": "Tools", + "description": """Allow regular users to view Audit log lines + via the form view of the relevant model""", + "depends": [ + "auditlog", + "contacts", + ], + "data": [ + "views/auditlog_view.xml", + "security/ir.model.access.csv", + ], + "application": True, + "installable": True, +} diff --git a/auditlog_security/models/__init__.py b/auditlog_security/models/__init__.py new file mode 100644 index 00000000000..4c1c462d621 --- /dev/null +++ b/auditlog_security/models/__init__.py @@ -0,0 +1,6 @@ +# 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_autovacuum diff --git a/auditlog_security/models/auditlog_autovacuum.py b/auditlog_security/models/auditlog_autovacuum.py new file mode 100644 index 00000000000..7b4b0bc3a19 --- /dev/null +++ b/auditlog_security/models/auditlog_autovacuum.py @@ -0,0 +1,14 @@ +# Copyright 2021 Therp B.V. +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import models, api + + +class AuditlogAutovacuum(models.TransientModel): + _inherit = "auditlog.autovacuum" + + @api.model + def autovacuum(self, days): + return super( + AuditlogAutovacuum, self.with_context(auditlog_write=True) + ).autovacuum(days=days) diff --git a/auditlog_security/models/auditlog_line_access_rule.py b/auditlog_security/models/auditlog_line_access_rule.py new file mode 100644 index 00000000000..aedb39009f0 --- /dev/null +++ b/auditlog_security/models/auditlog_line_access_rule.py @@ -0,0 +1,115 @@ +# Copyright 2021 Therp B.V. +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import exceptions, models, fields, api, modules, _ +from odoo.addons.auditlog.models.rule import FIELDS_BLACKLIST + + +class AuditlogLineAccessRule(models.Model): + _name = "auditlog.line.access.rule" + + name = fields.Char() + + field_ids = fields.Many2many("ir.model.fields") + group_ids = fields.Many2many( + "res.groups", + help="""Groups that will be allowed to see the logged fields, if left empty + default will be all users with a login""", + ) + model_id = fields.Many2one( + "ir.model", related="auditlog_rule_id.model_id", readonly=True + ) + auditlog_rule_id = fields.Many2one( + "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 with context key so that deletion will not be forbidden + return self.env["ir.rule"].search( + [("auditlog_line_access_rule_id", "in", self.ids)] + ) + + def get_field_ids_domain(self): + """note this solution will work only with a hardcoded design of models, + because on initialization , self.model_id.id still is not defined. + for now, to keep generality we put the filtering in the view.""" + return [ + ("model_id", "=", self.env.ref("base.model_res_partner").id), + ("name", "not in", FIELDS_BLACKLIST), + ] + + def unlink(self): + to_delete = self.get_linked_rules() + res = super(AuditlogLineAccessRule, self).unlink() + if res: + res = res and to_delete.with_context(auditlog_write=True).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 + def create(self, vals): + res = super(AuditlogLineAccessRule, self).create(vals) + res.add_default_group_if_needed() + if res.needs_rule(): + res.generate_rules() + return res + + @api.multi + 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 + ): + if this.needs_rule(): + this.generate_rules() + else: + this.get_linked_rules().with_context(auditlog_write=True).unlink() + return res + + def generate_rules(self): + old_rule = self.env["ir.rule"].search( + [("auditlog_line_access_rule_id", "=", self.id)], limit=1 + ) + values = self._prepare_rule_values() + if old_rule: + old_rule.with_context(auditlog_write=True).write(values) + else: + self.with_context(auditlog_write=True).env["ir.rule"].create(values) + + def _prepare_rule_values(self): + domain_force = "[" + " ('aulditlog_rule_id.log_id.model_id' , '=', %s)," % ( + self.model_id.id + ) + if self.field_ids: + domain_force += "('field_id', 'in', %s)" % (self.field_ids.ids) + domain_force += "]" + return { + "name": "auditlog_extended_%s" % self.id, + "model_id": self.env.ref("auditlog.model_auditlog_log_line").id, + "groups": [(6, 0, self.group_ids.ids)], + "perm_read": True, + "domain_force": domain_force, + "auditlog_line_access_rule_id": self.id, + } diff --git a/auditlog_security/models/auditlog_rule.py b/auditlog_security/models/auditlog_rule.py new file mode 100644 index 00000000000..4ca5a924395 --- /dev/null +++ b/auditlog_security/models/auditlog_rule.py @@ -0,0 +1,46 @@ +# Copyright 2021 Therp B.V. +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import exceptions, models, fields, api, modules, _ +from odoo.addons.auditlog.models.rule import FIELDS_BLACKLIST + + +class AuditlogRule(models.Model): + _inherit = "auditlog.rule" + + auditlog_line_access_rule_ids = fields.One2many( + "auditlog.line.access.rule", "auditlog_rule_id", ondelete="cascade" + ) + + @api.onchange("model_id") + def onchange_model_id(self): + # if model changes we must wipe out all field ids + self.auditlog_line_access_rule_ids.unlink() + + @api.multi + def unlink(self): + lines = self.mapped("auditlog_line_access_rule_ids") + res = super(AuditlogRule, self).unlink() + if res: + lines.unlink() + return res + + @api.multi + def subscribe(self): + super(AuditlogRule, self).subscribe() + act_window_model = self.env["ir.actions.act_window"] + for rule in self: + domain = ( + "[('log_id.model_id', '=', %s), ('log_id.res_id', '=', active_id)]" + % (rule.model_id.id) + ) + vals = { + "name": _("View log lines"), + "res_model": "auditlog.log.line", + "src_model": rule.model_id.model, + "binding_model_id": rule.model_id.id, + "domain": domain, + } + act_window = act_window_model.sudo().create(vals) + rule.write({"state": "subscribed", "action_id": act_window.id}) + return True diff --git a/auditlog_security/models/ir_rule.py b/auditlog_security/models/ir_rule.py new file mode 100644 index 00000000000..dfb1c822fae --- /dev/null +++ b/auditlog_security/models/ir_rule.py @@ -0,0 +1,52 @@ +# Copyright 2021 Therp B.V. +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import exceptions, models, fields, api, _ + + +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", + ) + + @api.model + def create(self, values): + if values.get("model_id") == self.env.ref( + "auditlog.model_auditlog_log_line" + ).id and not self.env.context.get("auditlog_write"): + raise exceptions.ValidationError( + _( + """ + Auditlog line rules are automatically generated from the + auditlog interface, please use that to create""" + ) + ) + return super(IrRule, self).create(values) + + @api.multi + def write(self, vals): + if "auditlog_id" in vals and not self.env.context.get("auditlog_write"): + raise exceptions.ValidationError( + _("""Cannot change auditlog_line_access_rule""") + ) + return super(IrRule, self).write(vals) + + @api.multi + def unlink(self): + auditlog_write = self.env.context.get("auditlog_write") + for this in self: + if this.auditlog_line_access_rule_id and not auditlog_write: + raise exceptions.ValidationError( + _( + """ + Auditlog line rules are automatically generated from the + auditlog interface, please use that to delete""" + ) + ) + return super(IrRule, self).unlink() diff --git a/auditlog_security/readme/CONTRIBUTORS.rst b/auditlog_security/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000000..addcc3f4a2b --- /dev/null +++ b/auditlog_security/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Giovanni Francesco Capalbo diff --git a/auditlog_security/readme/CREDITS.rst b/auditlog_security/readme/CREDITS.rst new file mode 100644 index 00000000000..e69de29bb2d diff --git a/auditlog_security/readme/DESCRIPTION.rst b/auditlog_security/readme/DESCRIPTION.rst new file mode 100644 index 00000000000..2d056774e16 --- /dev/null +++ b/auditlog_security/readme/DESCRIPTION.rst @@ -0,0 +1,3 @@ +This module allows extends auditlog, allowing specific log lines to be viewed only +by users belonging to specific views, while all other lines are allowed only to +administrator. diff --git a/auditlog_security/readme/ROADMAP.rst b/auditlog_security/readme/ROADMAP.rst new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/auditlog_security/readme/ROADMAP.rst @@ -0,0 +1 @@ + diff --git a/auditlog_security/readme/USAGE.rst b/auditlog_security/readme/USAGE.rst new file mode 100644 index 00000000000..f4cfaeca2cf --- /dev/null +++ b/auditlog_security/readme/USAGE.rst @@ -0,0 +1,11 @@ +Go to `Settings / Technical / Audit / Rules` to subscribe rules. A rule defines +which operations to log for a given data model. +The rule is now extended with a new field permission_ids, that tells us wich groups will +be allowed to read the lines produced by this rule. +If permission_ids is left empty, the default will be: +"auditlog lines visible only by user in Settings group, which is the default +for the auditlog module" + + +Then, check logs in the `Settings / Technical / Audit / Logs` menu. You can +group them by user sessions, date, data model , HTTP requests. diff --git a/auditlog_security/security/ir.model.access.csv b/auditlog_security/security/ir.model.access.csv new file mode 100644 index 00000000000..f5314c702a3 --- /dev/null +++ b/auditlog_security/security/ir.model.access.csv @@ -0,0 +1,4 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_auditlog_log_line_user,auditlog_log_line_user,model_auditlog_log_line,base.group_user,1,0,0,0 +access_auditlog_log_user,auditlog_log_user,model_auditlog_log,base.group_user,1,0,0,0 +access_auditlog_line_access_rule_admin,auditlog_line_access_rule_admin,model_auditlog_line_access_rule,base.group_system,1,1,1,1 diff --git a/auditlog_security/static/description/index.html b/auditlog_security/static/description/index.html new file mode 100644 index 00000000000..03f14d1e6be --- /dev/null +++ b/auditlog_security/static/description/index.html @@ -0,0 +1,438 @@ + + + + + + +Audit Log User Permissions + + + +
+

Audit Log User Permissions

+ + +

Beta License: AGPL-3 OCA/server-tools Translate me on Weblate Try me on Runbot

+

This module allows extends auditlog, allowing specific log lines to be viewed only +by users belonging to specific views, while all other lines are allowed only to +administrator.

+

Table of contents

+ +
+

Usage

+

Go to Settings / Technical / Audit / Rules to subscribe rules. A rule defines +which operations to log for a given data model. +The rule is now extended with a new field permission_ids, that tells us wich groups will +be allowed to read the lines produced by this rule. +If permission_ids is left empty, the default will be: +“auditlog lines visible only by user in Settings group, which is the default +for the auditlog module”

+

Then, check logs in the Settings / Technical / Audit / Logs menu. You can +group them by user sessions, date, data model , HTTP requests.

+
+ +
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Therp B.V.
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/server-tools project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/auditlog_security/views/auditlog_view.xml b/auditlog_security/views/auditlog_view.xml new file mode 100644 index 00000000000..6d34b52e66d --- /dev/null +++ b/auditlog_security/views/auditlog_view.xml @@ -0,0 +1,120 @@ + + + + + auditlog.log.line.form + auditlog.log.line + +
+ + + + + + + + + +
+
+
+ + + + auditlog.log.line.tree + auditlog.log.line + + + + + + + + + + + + + + + + + auditlog rule form extension + auditlog.rule + + + + + +

+ Add fields here to make any changes to them (audit log lines) + visible to members of the selected groups. +

+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+
+ + + auditlog rule tree extension + auditlog.rule + + + + + + + + + + + + + + +
diff --git a/maintainer-tools b/maintainer-tools new file mode 160000 index 00000000000..7d8a9f9ad73 --- /dev/null +++ b/maintainer-tools @@ -0,0 +1 @@ +Subproject commit 7d8a9f9ad73db0976fb03cbee43d953bc29b89e9