From 0d27c0a830d518bb7205d91ed30bf093b685f531 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Fri, 13 Oct 2017 17:07:01 +0200 Subject: [PATCH] Add module base_user_auth_log --- base_user_auth_log/README.rst | 37 +++++++++ base_user_auth_log/__init__.py | 3 + base_user_auth_log/__openerp__.py | 21 +++++ base_user_auth_log/data/ir_cron.xml | 24 ++++++ base_user_auth_log/models/__init__.py | 4 + base_user_auth_log/models/res_users.py | 42 ++++++++++ .../models/res_users_auth_log.py | 44 ++++++++++ .../security/ir.model.access.csv | 2 + base_user_auth_log/views/res_users.xml | 26 ++++++ .../views/res_users_auth_log.xml | 81 +++++++++++++++++++ 10 files changed, 284 insertions(+) create mode 100644 base_user_auth_log/README.rst create mode 100644 base_user_auth_log/__init__.py create mode 100644 base_user_auth_log/__openerp__.py create mode 100644 base_user_auth_log/data/ir_cron.xml create mode 100644 base_user_auth_log/models/__init__.py create mode 100644 base_user_auth_log/models/res_users.py create mode 100644 base_user_auth_log/models/res_users_auth_log.py create mode 100644 base_user_auth_log/security/ir.model.access.csv create mode 100644 base_user_auth_log/views/res_users.xml create mode 100644 base_user_auth_log/views/res_users_auth_log.xml diff --git a/base_user_auth_log/README.rst b/base_user_auth_log/README.rst new file mode 100644 index 0000000..387f3f4 --- /dev/null +++ b/base_user_auth_log/README.rst @@ -0,0 +1,37 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +======================== +User Authentication Logs +======================== + +This module adds user authentication logs in Odoo. It logs both authentication success and failures. + +Usage +===== + +The authentication logs can be seen: + +* on the users's form view in the *Auth Logs* tab, +* in the menu *Settings > Technical > Security > Authentication Logs*. + +Authentication failure logs are displayed in red. Authentication success logs are displayed in black. + +To have read access to the logs, you need to be part of the *Access Rights* group. + +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. + +Credits +======= + +Contributors +------------ + +* Alexis de Lattre diff --git a/base_user_auth_log/__init__.py b/base_user_auth_log/__init__.py new file mode 100644 index 0000000..cde864b --- /dev/null +++ b/base_user_auth_log/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import models diff --git a/base_user_auth_log/__openerp__.py b/base_user_auth_log/__openerp__.py new file mode 100644 index 0000000..bc79bbd --- /dev/null +++ b/base_user_auth_log/__openerp__.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# © 2017 Akretion (Alexis de Lattre ) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + 'name': 'Users authentification logs', + 'version': '8.0.1.0.0', + 'category': 'Tools', + 'license': 'AGPL-3', + 'summary': 'Adds users authentication logs', + 'author': 'Akretion', + 'website': 'http://www.akretion.com', + 'depends': ['base'], + 'data': [ + 'security/ir.model.access.csv', + 'views/res_users_auth_log.xml', + 'views/res_users.xml', + 'data/ir_cron.xml', + ], + 'installable': True, +} diff --git a/base_user_auth_log/data/ir_cron.xml b/base_user_auth_log/data/ir_cron.xml new file mode 100644 index 0000000..90db7eb --- /dev/null +++ b/base_user_auth_log/data/ir_cron.xml @@ -0,0 +1,24 @@ + + + + + + + + Purge old authentication logs + + + 1 + months + -1 + + + + + + + + diff --git a/base_user_auth_log/models/__init__.py b/base_user_auth_log/models/__init__.py new file mode 100644 index 0000000..ce046fd --- /dev/null +++ b/base_user_auth_log/models/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- + +from . import res_users_auth_log +from . import res_users diff --git a/base_user_auth_log/models/res_users.py b/base_user_auth_log/models/res_users.py new file mode 100644 index 0000000..3878d89 --- /dev/null +++ b/base_user_auth_log/models/res_users.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# © 2017 Akretion (Alexis de Lattre ) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from openerp import models, fields, registry, SUPERUSER_ID +import logging +logger = logging.getLogger(__name__) + + +class ResUsers(models.Model): + _inherit = 'res.users' + + auth_log_ids = fields.One2many( + 'res.users.auth.log', 'user_id', string='Authentication Logs') + + def _login(self, db, login, password): + user_id = super(ResUsers, self)._login(db, login, password) + with registry(db).cursor() as cr: + if user_id: + result = 'success' + else: + user_id = None # To write a null value, psycopg2 wants None + result = 'failure' + cr.execute( + "SELECT id FROM res_users WHERE login=%s", (login, )) + user_select = cr.fetchall() + if user_select: + user_id = user_select[0][0] + + cr.execute(""" + INSERT INTO res_users_auth_log ( + create_uid, + create_date, + date, + login, + result, + user_id + ) VALUES ( + %s, NOW() AT TIME ZONE 'UTC', NOW() AT TIME ZONE 'UTC', + %s, %s, %s)""", (SUPERUSER_ID, login, result, user_id)) + logger.info('Auth log created for login %s type %s', login, result) + return user_id diff --git a/base_user_auth_log/models/res_users_auth_log.py b/base_user_auth_log/models/res_users_auth_log.py new file mode 100644 index 0000000..1bec710 --- /dev/null +++ b/base_user_auth_log/models/res_users_auth_log.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# © 2017 Akretion (Alexis de Lattre ) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from openerp import models, fields, api, _ +from openerp.exceptions import Warning as UserError +from datetime import datetime, timedelta +import logging +logger = logging.getLogger(__name__) + + +class ResUsersAuthLog(models.Model): + _name = 'res.users.auth.log' + _description = 'Users Authentication Logs' + _order = 'date desc' + _rec_name = 'date' + + user_id = fields.Many2one( + 'res.users', string='User', ondelete='cascade', readonly=True) + login = fields.Char(string='Login', readonly=True) + date = fields.Datetime( + string='Authentication Date', required=True, readonly=True) + result = fields.Selection([ + ('success', 'Success'), + ('failure', 'Failure'), + ], string='Result', required=True, readonly=True) + + @api.model + def create(self, vals): + if not self._context.get('authenticate_create'): + raise UserError(_( + "You cannot manually create an authentication log.")) + return super(ResUsersAuthLog, self).create(vals) + + @api.multi + def write(self, vals): + raise UserError(_("You cannot modify an authentication log.")) + + @api.model + def _purge_old_auth_logs(self): + expiry_date = datetime.today() - timedelta(days=365) + self._cr.execute( + "DELETE FROM res_users_auth_log WHERE date <= %s", (expiry_date, )) + logger.info('Auth logs older than %s have been purged', expiry_date) diff --git a/base_user_auth_log/security/ir.model.access.csv b/base_user_auth_log/security/ir.model.access.csv new file mode 100644 index 0000000..26ff768 --- /dev/null +++ b/base_user_auth_log/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_res_users_auth_log,Read access to Access rights group,model_res_users_auth_log,base.group_erp_manager,1,0,0,0 diff --git a/base_user_auth_log/views/res_users.xml b/base_user_auth_log/views/res_users.xml new file mode 100644 index 0000000..c100ad4 --- /dev/null +++ b/base_user_auth_log/views/res_users.xml @@ -0,0 +1,26 @@ + + + + + + + + + auth_logs.res.users.form + res.users + + + + + + + + + + + + + diff --git a/base_user_auth_log/views/res_users_auth_log.xml b/base_user_auth_log/views/res_users_auth_log.xml new file mode 100644 index 0000000..2f75f33 --- /dev/null +++ b/base_user_auth_log/views/res_users_auth_log.xml @@ -0,0 +1,81 @@ + + + + + + + + + res.users.auth.logs.form + res.users.auth.log + +
+ + + + + + +
+
+
+ + + res.users.auth.logs.tree + res.users.auth.log + + + + + + + + + + + + res.users.auth.logs.search + res.users.auth.log + + + + + + + + + + + + + + + + + + res.users.auth.logs.graph + res.users.auth.log + + + + + + + + + + Authentication Logs + res.users.auth.log + tree,form,graph + {'auth_logs_main_view': True} + + + + + +
+