diff --git a/auditlog/__init__.py b/auditlog/__init__.py index da3e36775..69f7babdf 100644 --- a/auditlog/__init__.py +++ b/auditlog/__init__.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# © 2015 ABF OSIELL # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from . import models diff --git a/auditlog/__manifest__.py b/auditlog/__manifest__.py index d3ebecbb8..2b7b9f143 100644 --- a/auditlog/__manifest__.py +++ b/auditlog/__manifest__.py @@ -1,10 +1,9 @@ -# -*- coding: utf-8 -*- # © 2015 ABF OSIELL # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { 'name': "Audit Log", - 'version': "10.0.1.0.0", + 'version': "11.0.1.0.0", 'author': "ABF OSIELL,Odoo Community Association (OCA)", 'license': "AGPL-3", 'website': "http://www.osiell.com", diff --git a/auditlog/data/ir_cron.xml b/auditlog/data/ir_cron.xml index 728b2354b..87c03d0d4 100644 --- a/auditlog/data/ir_cron.xml +++ b/auditlog/data/ir_cron.xml @@ -8,9 +8,9 @@ -1 - auditlog.autovacuum - autovacuum - (180,) + model.autovacuum(180) + code + diff --git a/auditlog/models/__init__.py b/auditlog/models/__init__.py index ce5b89899..d26ec58de 100644 --- a/auditlog/models/__init__.py +++ b/auditlog/models/__init__.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# © 2015 ABF OSIELL # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from . import rule diff --git a/auditlog/models/autovacuum.py b/auditlog/models/autovacuum.py index 216c56ab6..90088bfd4 100644 --- a/auditlog/models/autovacuum.py +++ b/auditlog/models/autovacuum.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2016 ABF OSIELL # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import logging @@ -36,6 +35,6 @@ class AuditlogAutovacuum(models.TransientModel): nb_records = len(records) records.unlink() _logger.info( - u"AUTOVACUUM - %s '%s' records deleted", + "AUTOVACUUM - %s '%s' records deleted", nb_records, data_model) return True diff --git a/auditlog/models/http_request.py b/auditlog/models/http_request.py index 1156925ec..98f45bcbc 100644 --- a/auditlog/models/http_request.py +++ b/auditlog/models/http_request.py @@ -10,20 +10,20 @@ from odoo.http import request class AuditlogHTTPRequest(models.Model): _name = 'auditlog.http.request' - _description = u"Auditlog - HTTP request log" + _description = "Auditlog - HTTP request log" _order = "create_date DESC" display_name = fields.Char( - u"Name", compute="_compute_display_name", store=True) - name = fields.Char(u"Path") - root_url = fields.Char(u"Root URL") + "Name", compute="_compute_display_name", store=True) + name = fields.Char("Path") + root_url = fields.Char("Root URL") user_id = fields.Many2one( - 'res.users', string=u"User") + 'res.users', string="User") http_session_id = fields.Many2one( - 'auditlog.http.session', string=u"Session") - user_context = fields.Char(u"Context") + 'auditlog.http.session', string="Session") + user_context = fields.Char("Context") log_ids = fields.One2many( - 'auditlog.log', 'http_request_id', string=u"Logs") + 'auditlog.log', 'http_request_id', string="Logs") @api.depends('create_date', 'name') def _compute_display_name(self): @@ -31,7 +31,7 @@ class AuditlogHTTPRequest(models.Model): create_date = fields.Datetime.from_string(httprequest.create_date) tz_create_date = fields.Datetime.context_timestamp( httprequest, create_date) - httprequest.display_name = u"%s (%s)" % ( + httprequest.display_name = "%s (%s)" % ( httprequest.name or '?', fields.Datetime.to_string(tz_create_date)) diff --git a/auditlog/models/http_session.py b/auditlog/models/http_session.py index 4a73782eb..0c3b19411 100644 --- a/auditlog/models/http_session.py +++ b/auditlog/models/http_session.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2015 ABF OSIELL # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). @@ -8,16 +7,16 @@ from odoo.http import request class AuditlogtHTTPSession(models.Model): _name = 'auditlog.http.session' - _description = u"Auditlog - HTTP User session log" + _description = "Auditlog - HTTP User session log" _order = "create_date DESC" display_name = fields.Char( - u"Name", compute="_compute_display_name", store=True) - name = fields.Char(u"Session ID", index=True) + "Name", compute="_compute_display_name", store=True) + name = fields.Char("Session ID", index=True) user_id = fields.Many2one( - 'res.users', string=u"User", index=True) + 'res.users', string="User", index=True) http_request_ids = fields.One2many( - 'auditlog.http.request', 'http_session_id', string=u"HTTP Requests") + 'auditlog.http.request', 'http_session_id', string="HTTP Requests") @api.depends('create_date', 'user_id') def _compute_display_name(self): @@ -25,7 +24,7 @@ class AuditlogtHTTPSession(models.Model): create_date = fields.Datetime.from_string(httpsession.create_date) tz_create_date = fields.Datetime.context_timestamp( httpsession, create_date) - httpsession.display_name = u"%s (%s)" % ( + httpsession.display_name = "%s (%s)" % ( httpsession.user_id and httpsession.user_id.name or '?', fields.Datetime.to_string(tz_create_date)) diff --git a/auditlog/models/log.py b/auditlog/models/log.py index 890467a18..3849e87fc 100644 --- a/auditlog/models/log.py +++ b/auditlog/models/log.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2015 ABF OSIELL # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import models, fields @@ -11,22 +10,22 @@ class AuditlogLog(models.Model): name = fields.Char("Resource Name", size=64) model_id = fields.Many2one( - 'ir.model', string=u"Model") - res_id = fields.Integer(u"Resource ID") + 'ir.model', string="Model") + res_id = fields.Integer("Resource ID") user_id = fields.Many2one( - 'res.users', string=u"User") - method = fields.Char(u"Method", size=64) + 'res.users', string="User") + method = fields.Char("Method", size=64) line_ids = fields.One2many( - 'auditlog.log.line', 'log_id', string=u"Fields updated") + 'auditlog.log.line', 'log_id', string="Fields updated") http_session_id = fields.Many2one( - 'auditlog.http.session', string=u"Session") + 'auditlog.http.session', string="Session") http_request_id = fields.Many2one( - 'auditlog.http.request', string=u"HTTP Request") + 'auditlog.http.request', string="HTTP Request") log_type = fields.Selection( - [('full', u"Full log"), - ('fast', u"Fast log"), + [('full', "Full log"), + ('fast', "Fast log"), ], - string=u"Type") + string="Type") class AuditlogLogLine(models.Model): @@ -34,13 +33,13 @@ class AuditlogLogLine(models.Model): _description = "Auditlog - Log details (fields updated)" field_id = fields.Many2one( - 'ir.model.fields', ondelete='cascade', string=u"Field", required=True) + 'ir.model.fields', ondelete='cascade', string="Field", required=True) log_id = fields.Many2one( - 'auditlog.log', string=u"Log", ondelete='cascade', index=True) - old_value = fields.Text(u"Old Value") - new_value = fields.Text(u"New Value") - old_value_text = fields.Text(u"Old value Text") - new_value_text = fields.Text(u"New value Text") - field_name = fields.Char(u"Technical name", related='field_id.name') + 'auditlog.log', string="Log", ondelete='cascade', index=True) + old_value = fields.Text("Old Value") + new_value = fields.Text("New Value") + old_value_text = fields.Text("Old value Text") + new_value_text = fields.Text("New value Text") + field_name = fields.Char("Technical name", related='field_id.name') field_description = fields.Char( - u"Description", related='field_id.field_description') + "Description", related='field_id.field_description') diff --git a/auditlog/models/rule.py b/auditlog/models/rule.py index 4dcdb7877..0545512d9 100644 --- a/auditlog/models/rule.py +++ b/auditlog/models/rule.py @@ -1,8 +1,7 @@ -# -*- coding: utf-8 -*- # © 2015 ABF OSIELL # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import models, fields, api, modules, _, sql_db +from odoo import models, fields, api, modules, _ FIELDS_BLACKLIST = [ 'id', 'create_uid', 'create_date', 'write_uid', 'write_date', @@ -45,42 +44,42 @@ class AuditlogRule(models.Model): _name = 'auditlog.rule' _description = "Auditlog - Rule" - name = fields.Char(u"Name", size=32, required=True) + name = fields.Char("Name", size=32, required=True) model_id = fields.Many2one( - 'ir.model', u"Model", required=True, - help=u"Select model for which you want to generate log.") + 'ir.model', "Model", required=True, + help="Select model for which you want to generate log.") user_ids = fields.Many2many( 'res.users', 'audittail_rules_users', 'user_id', 'rule_id', - string=u"Users", - help=u"if User is not added then it will applicable for all users") + string="Users", + help="if User is not added then it will applicable for all users") log_read = fields.Boolean( - u"Log Reads", - help=(u"Select this if you want to keep track of read/open on any " - u"record of the model of this rule")) + "Log Reads", + help=("Select this if you want to keep track of read/open on any " + "record of the model of this rule")) log_write = fields.Boolean( - u"Log Writes", default=True, - help=(u"Select this if you want to keep track of modification on any " - u"record of the model of this rule")) + "Log Writes", default=True, + help=("Select this if you want to keep track of modification on any " + "record of the model of this rule")) log_unlink = fields.Boolean( - u"Log Deletes", default=True, - help=(u"Select this if you want to keep track of deletion on any " - u"record of the model of this rule")) + "Log Deletes", default=True, + help=("Select this if you want to keep track of deletion on any " + "record of the model of this rule")) log_create = fields.Boolean( - u"Log Creates", default=True, - help=(u"Select this if you want to keep track of creation on any " - u"record of the model of this rule")) + "Log Creates", default=True, + help=("Select this if you want to keep track of creation on any " + "record of the model of this rule")) log_type = fields.Selection( - [('full', u"Full log"), - ('fast', u"Fast log"), + [('full', "Full log"), + ('fast', "Fast log"), ], - string=u"Type", required=True, default='full', - help=(u"Full log: make a diff between the data before and after " - u"the operation (log more info like computed fields which were " - u"updated, but it is slower)\n" - u"Fast log: only log the changes made through the create and " - u"write operations (less information, but it is faster)")) + string="Type", required=True, default='full', + help=("Full log: make a diff between the data before and after " + "the operation (log more info like computed fields which were " + "updated, but it is slower)\n" + "Fast log: only log the changes made through the create and " + "write operations (less information, but it is faster)")) # log_action = fields.Boolean( # "Log Action", # help=("Select this if you want to keep track of actions on the " @@ -91,7 +90,7 @@ class AuditlogRule(models.Model): # "record of the model of this rule")) state = fields.Selection( [('draft', "Draft"), ('subscribed', "Subscribed")], - string=u"State", required=True, default='draft') + string="State", required=True, default='draft') action_id = fields.Many2one( 'ir.actions.act_window', string="Action") @@ -169,16 +168,14 @@ class AuditlogRule(models.Model): delattr(type(model_model), 'auditlog_ruled_%s' % method) updated = True if updated: - modules.registry.RegistryManager.signal_registry_change( - self.env.cr.dbname) + modules.registry.Registry(self.env.cr.dbname).signal_changes() @api.model def create(self, vals): """Update the registry when a new rule is created.""" new_record = super(AuditlogRule, self).create(vals) if new_record._register_hook(): - modules.registry.RegistryManager.signal_registry_change( - self.env.cr.dbname) + modules.registry.Registry(self.env.cr.dbname).signal_changes() return new_record @api.multi @@ -186,8 +183,7 @@ class AuditlogRule(models.Model): """Update the registry when existing rules are updated.""" super(AuditlogRule, self).write(vals) if self._register_hook(): - modules.registry.RegistryManager.signal_registry_change( - self.env.cr.dbname) + modules.registry.Registry(self.env.cr.dbname).signal_changes() return True @api.multi @@ -237,8 +233,8 @@ class AuditlogRule(models.Model): self.ensure_one() log_type = self.log_type - def read(self, *args, **kwargs): - result = read.origin(self, *args, **kwargs) + def read(self, fields=None, load='_classic_read', **kwargs): + result = read.origin(self, fields, load, **kwargs) # Sometimes the result is not a list but a dictionary # Also, we can not modify the current result as it will break calls result2 = result @@ -246,34 +242,18 @@ class AuditlogRule(models.Model): result2 = [result] read_values = dict((d['id'], d) for d in result2) # Old API - if args and isinstance(args[0], sql_db.Cursor): - cr, uid, ids = args[0], args[1], args[2] - if isinstance(ids, (int, long)): - ids = [ids] - # If the call came from auditlog itself, skip logging: - # avoid logs on `read` produced by auditlog during internal - # processing: read data of relevant records, 'ir.model', - # 'ir.model.fields'... (no interest in logging such operations) - if kwargs.get('context', {}).get('auditlog_disabled'): - return result - env = api.Environment(cr, uid, {'auditlog_disabled': True}) - rule_model = env['auditlog.rule'] - rule_model.sudo().create_logs( - env.uid, self._name, ids, - 'read', read_values, None, {'log_type': log_type}) - # New API - else: - # If the call came from auditlog itself, skip logging: - # avoid logs on `read` produced by auditlog during internal - # processing: read data of relevant records, 'ir.model', - # 'ir.model.fields'... (no interest in logging such operations) - if self.env.context.get('auditlog_disabled'): - return result - self = self.with_context(auditlog_disabled=True) - rule_model = self.env['auditlog.rule'] - rule_model.sudo().create_logs( - self.env.uid, self._name, self.ids, - 'read', read_values, None, {'log_type': log_type}) + + # If the call came from auditlog itself, skip logging: + # avoid logs on `read` produced by auditlog during internal + # processing: read data of relevant records, 'ir.model', + # 'ir.model.fields'... (no interest in logging such operations) + if self.env.context.get('auditlog_disabled'): + return result + self = self.with_context(auditlog_disabled=True) + rule_model = self.env['auditlog.rule'] + rule_model.sudo().create_logs( + self.env.uid, self._name, self.ids, + 'read', read_values, None, {'log_type': log_type}) return result return read @@ -307,7 +287,7 @@ class AuditlogRule(models.Model): # afterwards as it could not represent the real state # of the data in the database vals2 = dict(vals) - old_vals2 = dict.fromkeys(vals2.keys(), False) + old_vals2 = dict.fromkeys(list(vals2.keys()), False) old_values = dict((id_, old_vals2) for id_ in self.ids) new_values = dict((id_, vals2) for id_ in self.ids) result = write_fast.origin(self, vals, **kwargs) @@ -382,7 +362,9 @@ class AuditlogRule(models.Model): self._create_log_line_on_create(log, diff.added(), new_values) elif method is 'read': self._create_log_line_on_read( - log, old_values.get(res_id, EMPTY_DICT).keys(), old_values) + log, + list(old_values.get(res_id, EMPTY_DICT).keys()), old_values + ) elif method is 'write': self._create_log_line_on_write( log, diff.changed(), old_values, new_values) @@ -527,49 +509,30 @@ class AuditlogRule(models.Model): to view logs on that model. """ act_window_model = self.env['ir.actions.act_window'] - model_ir_values = self.env['ir.values'] for rule in self: # Create a shortcut to view logs domain = "[('model_id', '=', %s), ('res_id', '=', active_id)]" % ( rule.model_id.id) vals = { - 'name': _(u"View logs"), + 'name': _("View logs"), 'res_model': 'auditlog.log', '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}) - keyword = 'client_action_relate' - value = 'ir.actions.act_window,%s' % act_window.id - model_ir_values.sudo().set_action( - 'View_log_' + rule.model_id.model, - action_slot=keyword, - model=rule.model_id.model, - action=value) - return True @api.multi def unsubscribe(self): """Unsubscribe Auditing Rule on model.""" - act_window_model = self.env['ir.actions.act_window'] - ir_values_model = self.env['ir.values'] # Revert patched methods self._revert_methods() for rule in self: # Remove the shortcut to view logs - act_window = act_window_model.search( - [('name', '=', 'View Log'), - ('res_model', '=', 'auditlog.log'), - ('src_model', '=', rule.model_id.model)]) + act_window = rule.action_id if act_window: - value = 'ir.actions.act_window,%s' % act_window.id act_window.unlink() - ir_value = ir_values_model.search( - [('model', '=', rule.model_id.model), - ('value', '=', value)]) - if ir_value: - ir_value.unlink() self.write({'state': 'draft'}) return True diff --git a/auditlog/tests/__init__.py b/auditlog/tests/__init__.py index 1d57467d8..33f5b4796 100644 --- a/auditlog/tests/__init__.py +++ b/auditlog/tests/__init__.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# © 2015 Therp BV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from . import test_auditlog from . import test_autovacuum diff --git a/auditlog/tests/test_auditlog.py b/auditlog/tests/test_auditlog.py index f4c66dd38..7085b773d 100644 --- a/auditlog/tests/test_auditlog.py +++ b/auditlog/tests/test_auditlog.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2015 Therp BV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo.tests.common import TransactionCase @@ -8,6 +7,9 @@ class TestAuditlog(object): def test_LogCreation(self): """First test, caching some data.""" + + self.groups_rule.subscribe() + auditlog_log = self.env['auditlog.log'] group = self.env['res.groups'].create({ 'name': 'testgroup1', @@ -32,6 +34,9 @@ class TestAuditlog(object): def test_LogCreation2(self): """Second test, using cached data of the first one.""" + + self.groups_rule.subscribe() + auditlog_log = self.env['auditlog.log'] testgroup2 = self.env['res.groups'].create({ 'name': 'testgroup2', @@ -48,6 +53,8 @@ class TestAuditlog(object): of a 'write' log with a deleted resource (so with no text representation). """ + + self.groups_rule.subscribe() auditlog_log = self.env['auditlog.log'] testgroup3 = testgroup3 = self.env['res.groups'].create({ 'name': 'testgroup3', @@ -86,7 +93,6 @@ class TestAuditlogFull(TransactionCase, TestAuditlog): 'log_create': True, 'log_write': True, 'log_unlink': True, - 'state': 'subscribed', 'log_type': 'full', }) @@ -107,7 +113,6 @@ class TestAuditlogFast(TransactionCase, TestAuditlog): 'log_create': True, 'log_write': True, 'log_unlink': True, - 'state': 'subscribed', 'log_type': 'fast', }) diff --git a/auditlog/tests/test_autovacuum.py b/auditlog/tests/test_autovacuum.py index 707cfa80c..4e16f9d88 100644 --- a/auditlog/tests/test_autovacuum.py +++ b/auditlog/tests/test_autovacuum.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # © 2016 ABF OSIELL # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import time