Raphaël Valyi
8 years ago
committed by
Alexandre Papin
9 changed files with 185 additions and 278 deletions
-
23auth_admin_passkey/__init__.py
-
23auth_admin_passkey/__manifest__.py
-
76auth_admin_passkey/model/res_config.py
-
137auth_admin_passkey/model/res_users.py
-
0auth_admin_passkey/models/__init__.py
-
53auth_admin_passkey/models/res_config.py
-
118auth_admin_passkey/models/res_users.py
-
21auth_admin_passkey/tests/test_auth_admin_passkey.py
-
0auth_admin_passkey/views/res_config_view.xml
@ -1,23 +1,6 @@ |
|||||
# -*- encoding: utf-8 -*- |
|
||||
############################################################################## |
|
||||
# |
|
||||
# Admin Passkey module for OpenERP |
|
||||
|
# -*- coding: utf-8 -*- |
||||
# Copyright (C) 2013-2014 GRAP (http://www.grap.coop) |
# Copyright (C) 2013-2014 GRAP (http://www.grap.coop) |
||||
# @author Sylvain LE GAL (https://twitter.com/legalsylvain) |
# @author Sylvain LE GAL (https://twitter.com/legalsylvain) |
||||
# |
|
||||
# This program is free software: you can redistribute it and/or modify |
|
||||
# it under the terms of the GNU Affero General Public License as |
|
||||
# published by the Free Software Foundation, either version 3 of the |
|
||||
# License, or (at your option) any later version. |
|
||||
# |
|
||||
# This program is distributed in the hope that it will be useful, |
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||
# GNU Affero General Public License for more details. |
|
||||
# |
|
||||
# You should have received a copy of the GNU Affero General Public License |
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
||||
# |
|
||||
############################################################################## |
|
||||
|
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html |
||||
|
|
||||
from . import model |
|
||||
|
from . import models |
@ -1,76 +0,0 @@ |
|||||
# -*- encoding: utf-8 -*- |
|
||||
############################################################################## |
|
||||
# |
|
||||
# Admin Passkey module for OpenERP |
|
||||
# Copyright (C) 2013-2014 GRAP (http://www.grap.coop) |
|
||||
# @author Sylvain LE GAL (https://twitter.com/legalsylvain) |
|
||||
# |
|
||||
# This program is free software: you can redistribute it and/or modify |
|
||||
# it under the terms of the GNU Affero General Public License as |
|
||||
# published by the Free Software Foundation, either version 3 of the |
|
||||
# License, or (at your option) any later version. |
|
||||
# |
|
||||
# This program is distributed in the hope that it will be useful, |
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||
# GNU Affero General Public License for more details. |
|
||||
# |
|
||||
# You should have received a copy of the GNU Affero General Public License |
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
||||
# |
|
||||
############################################################################## |
|
||||
|
|
||||
from openerp.osv import fields |
|
||||
from openerp.osv.orm import TransientModel |
|
||||
from openerp.tools.safe_eval import safe_eval |
|
||||
|
|
||||
|
|
||||
class base_config_settings(TransientModel): |
|
||||
_inherit = 'base.config.settings' |
|
||||
|
|
||||
# Getter / Setter Section |
|
||||
def get_default_auth_admin_passkey_send_to_admin( |
|
||||
self, cr, uid, ids, context=None): |
|
||||
icp = self.pool['ir.config_parameter'] |
|
||||
return { |
|
||||
'auth_admin_passkey_send_to_admin': safe_eval(icp.get_param( |
|
||||
cr, uid, 'auth_admin_passkey.send_to_admin', 'True')), |
|
||||
} |
|
||||
|
|
||||
def set_auth_admin_passkey_send_to_admin(self, cr, uid, ids, context=None): |
|
||||
config = self.browse(cr, uid, ids[0], context=context) |
|
||||
icp = self.pool['ir.config_parameter'] |
|
||||
icp.set_param( |
|
||||
cr, uid, 'auth_admin_passkey.send_to_admin', |
|
||||
repr(config.auth_admin_passkey_send_to_admin)) |
|
||||
|
|
||||
def get_default_auth_admin_passkey_send_to_user( |
|
||||
self, cr, uid, ids, context=None): |
|
||||
icp = self.pool['ir.config_parameter'] |
|
||||
return { |
|
||||
'auth_admin_passkey_send_to_user': safe_eval(icp.get_param( |
|
||||
cr, uid, 'auth_admin_passkey.send_to_user', 'True')), |
|
||||
} |
|
||||
|
|
||||
def set_auth_admin_passkey_send_to_user(self, cr, uid, ids, context=None): |
|
||||
config = self.browse(cr, uid, ids[0], context=context) |
|
||||
icp = self.pool['ir.config_parameter'] |
|
||||
icp.set_param( |
|
||||
cr, uid, 'auth_admin_passkey.send_to_user', |
|
||||
repr(config.auth_admin_passkey_send_to_user)) |
|
||||
|
|
||||
# Columns Section |
|
||||
_columns = { |
|
||||
'auth_admin_passkey_send_to_admin': fields.boolean( |
|
||||
'Send email to admin user.', |
|
||||
help="""When the administrator use his password to login in """ |
|
||||
"""with a different account, OpenERP will send an email """ |
|
||||
"""to the admin user.""", |
|
||||
), |
|
||||
'auth_admin_passkey_send_to_user': fields.boolean( |
|
||||
string='Send email to user.', |
|
||||
help="""When the administrator use his password to login in """ |
|
||||
"""with a different account, OpenERP will send an email """ |
|
||||
"""to the account user.""", |
|
||||
), |
|
||||
} |
|
@ -1,137 +0,0 @@ |
|||||
# -*- encoding: utf-8 -*- |
|
||||
############################################################################## |
|
||||
# |
|
||||
# Admin Passkey module for OpenERP |
|
||||
# Copyright (C) 2013-2014 GRAP (http://www.grap.coop) |
|
||||
# @author Sylvain LE GAL (https://twitter.com/legalsylvain) |
|
||||
# |
|
||||
# This program is free software: you can redistribute it and/or modify |
|
||||
# it under the terms of the GNU Affero General Public License as |
|
||||
# published by the Free Software Foundation, either version 3 of the |
|
||||
# License, or (at your option) any later version. |
|
||||
# |
|
||||
# This program is distributed in the hope that it will be useful, |
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||
# GNU Affero General Public License for more details. |
|
||||
# |
|
||||
# You should have received a copy of the GNU Affero General Public License |
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
||||
# |
|
||||
############################################################################## |
|
||||
|
|
||||
import datetime |
|
||||
|
|
||||
from openerp import SUPERUSER_ID |
|
||||
from openerp import pooler |
|
||||
from openerp import exceptions |
|
||||
from openerp.osv.orm import Model |
|
||||
from openerp.tools.translate import _ |
|
||||
from openerp.tools.safe_eval import safe_eval |
|
||||
|
|
||||
|
|
||||
class res_users(Model): |
|
||||
_inherit = "res.users" |
|
||||
|
|
||||
# Private Function section |
|
||||
def _get_translation(self, cr, lang, text): |
|
||||
context = {'lang': lang} # noqa: _() checks page for locals |
|
||||
return _(text) |
|
||||
|
|
||||
def _send_email_passkey(self, cr, user_id, user_agent_env): |
|
||||
""" Send a email to the admin of the system and / or the user |
|
||||
to inform passkey use.""" |
|
||||
mails = [] |
|
||||
mail_obj = self.pool['mail.mail'] |
|
||||
icp_obj = self.pool['ir.config_parameter'] |
|
||||
admin_user = self.browse(cr, SUPERUSER_ID, SUPERUSER_ID) |
|
||||
login_user = self.browse(cr, SUPERUSER_ID, user_id) |
|
||||
send_to_admin = safe_eval(icp_obj.get_param( |
|
||||
cr, SUPERUSER_ID, 'auth_admin_passkey.send_to_admin', 'True')) |
|
||||
send_to_user = safe_eval(icp_obj.get_param( |
|
||||
cr, SUPERUSER_ID, 'auth_admin_passkey.send_to_user', 'True')) |
|
||||
|
|
||||
if send_to_admin and admin_user.email: |
|
||||
mails.append({'email': admin_user.email, 'lang': admin_user.lang}) |
|
||||
if send_to_user and login_user.email: |
|
||||
mails.append({'email': login_user.email, 'lang': login_user.lang}) |
|
||||
|
|
||||
for mail in mails: |
|
||||
subject = self._get_translation( |
|
||||
cr, mail['lang'], _('Passkey used')) |
|
||||
body = self._get_translation( |
|
||||
cr, mail['lang'], |
|
||||
_("""Admin user used his passkey to login with '%s'.\n\n""" |
|
||||
"""\n\nTechnicals informations belows : \n\n""" |
|
||||
"""- Login date : %s\n\n""")) % ( |
|
||||
login_user.login, |
|
||||
datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")) |
|
||||
for k, v in user_agent_env.iteritems(): |
|
||||
body += ("- %s : %s\n\n") % (k, v) |
|
||||
mail_obj.create( |
|
||||
cr, SUPERUSER_ID, { |
|
||||
'email_to': mail['email'], |
|
||||
'subject': subject, |
|
||||
'body_html': '<pre>%s</pre>' % body}) |
|
||||
|
|
||||
def _send_email_same_password(self, cr, login_user): |
|
||||
""" Send a email to the admin user to inform that another user has the |
|
||||
same password as him.""" |
|
||||
mail_obj = self.pool['mail.mail'] |
|
||||
admin_user = self.browse(cr, SUPERUSER_ID, SUPERUSER_ID) |
|
||||
if admin_user.email: |
|
||||
mail_obj.create(cr, SUPERUSER_ID, { |
|
||||
'email_to': admin_user.email, |
|
||||
'subject': self._get_translation( |
|
||||
cr, admin_user.lang, _('[WARNING] OpenERP Security Risk')), |
|
||||
'body_html': self._get_translation( |
|
||||
cr, admin_user.lang, _( |
|
||||
"""<pre>User with login '%s' has the same """ |
|
||||
"""password as you.</pre>""")) % (login_user), |
|
||||
}) |
|
||||
|
|
||||
# Overload Section |
|
||||
def authenticate(self, db, login, password, user_agent_env): |
|
||||
""" Authenticate the user 'login' is password is ok or if |
|
||||
is admin password. In the second case, send mail to user and admin.""" |
|
||||
user_id = super(res_users, self).authenticate( |
|
||||
db, login, password, user_agent_env) |
|
||||
if user_id and (user_id != SUPERUSER_ID): |
|
||||
same_password = False |
|
||||
cr = pooler.get_db(db).cursor() |
|
||||
try: |
|
||||
# directly use parent 'check_credentials' function |
|
||||
# to really know if credentials are ok |
|
||||
# or if it was admin password |
|
||||
super(res_users, self).check_credentials( |
|
||||
cr, SUPERUSER_ID, password) |
|
||||
try: |
|
||||
# Test now if the user has the same password as admin user |
|
||||
super(res_users, self).check_credentials( |
|
||||
cr, user_id, password) |
|
||||
same_password = True |
|
||||
except exceptions.AccessDenied: |
|
||||
pass |
|
||||
if not same_password: |
|
||||
self._send_email_passkey(cr, user_id, user_agent_env) |
|
||||
else: |
|
||||
self._send_email_same_password(cr, login) |
|
||||
cr.commit() |
|
||||
except exceptions.AccessDenied: |
|
||||
pass |
|
||||
finally: |
|
||||
cr.close() |
|
||||
return user_id |
|
||||
|
|
||||
def check_credentials(self, cr, uid, password): |
|
||||
""" Return now True if credentials are good OR if password is admin |
|
||||
password.""" |
|
||||
if uid != SUPERUSER_ID: |
|
||||
try: |
|
||||
super(res_users, self).check_credentials( |
|
||||
cr, uid, password) |
|
||||
return True |
|
||||
except exceptions.AccessDenied: |
|
||||
return self.check_credentials(cr, SUPERUSER_ID, password) |
|
||||
else: |
|
||||
return super(res_users, self).check_credentials(cr, uid, password) |
|
@ -0,0 +1,53 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Copyright (C) 2013-2014 GRAP (http://www.grap.coop) |
||||
|
# @author Sylvain LE GAL (https://twitter.com/legalsylvain) |
||||
|
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html |
||||
|
|
||||
|
from openerp import api, fields, models |
||||
|
|
||||
|
|
||||
|
class BaseConfigSettings(models.TransientModel): |
||||
|
_inherit = 'base.config.settings' |
||||
|
|
||||
|
# Getter / Setter Section |
||||
|
@api.model |
||||
|
def get_default_auth_admin_passkey_send_to_admin(self, fields): |
||||
|
return { |
||||
|
'auth_admin_passkey_send_to_admin': |
||||
|
self.env["ir.config_parameter"].get_param( |
||||
|
"auth_admin_passkey.send_to_admin") |
||||
|
} |
||||
|
|
||||
|
@api.multi |
||||
|
def set_auth_admin_passkey_send_to_admin(self): |
||||
|
for config in self: |
||||
|
self.env['ir.config_parameter'].set_param( |
||||
|
"auth_admin_passkey.send_to_admin", |
||||
|
config.auth_admin_passkey_send_to_admin or '') |
||||
|
|
||||
|
@api.model |
||||
|
def get_default_auth_admin_passkey_send_to_user(self, fields): |
||||
|
return { |
||||
|
'auth_admin_passkey_send_to_user': |
||||
|
self.env["ir.config_parameter"].get_param( |
||||
|
"auth_admin_passkey.send_to_user") |
||||
|
} |
||||
|
|
||||
|
@api.multi |
||||
|
def set_auth_admin_passkey_send_to_user(self): |
||||
|
for config in self: |
||||
|
self.env['ir.config_parameter'].set_param( |
||||
|
"auth_admin_passkey.send_to_user", |
||||
|
config.auth_admin_passkey_send_to_user or '') |
||||
|
|
||||
|
auth_admin_passkey_send_to_admin = fields.Boolean( |
||||
|
string='Send email to admin user.', |
||||
|
help="""When the administrator use his password to login in """ |
||||
|
"""with a different account, OpenERP will send an email """ |
||||
|
"""to the admin user.""") |
||||
|
|
||||
|
auth_admin_passkey_send_to_user = fields.Boolean( |
||||
|
string='Send email to user.', |
||||
|
help="""When the administrator use his password to login in """ |
||||
|
"""with a different account, OpenERP will send an email """ |
||||
|
"""to the account user.""") |
@ -0,0 +1,118 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Copyright (C) 2013-2014 GRAP (http://www.grap.coop) |
||||
|
# @author Sylvain LE GAL (https://twitter.com/legalsylvain) |
||||
|
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html |
||||
|
|
||||
|
import datetime |
||||
|
|
||||
|
from openerp import _, api, exceptions, models, registry, SUPERUSER_ID |
||||
|
from openerp.tools.safe_eval import safe_eval |
||||
|
|
||||
|
|
||||
|
class ResUsers(models.Model): |
||||
|
_inherit = "res.users" |
||||
|
|
||||
|
def _get_translation(self, lang, text): |
||||
|
context = {'lang': lang} # noqa: _() checks page for locals |
||||
|
return _(text) |
||||
|
|
||||
|
@api.model |
||||
|
def _send_email_passkey(self, user_agent_env): |
||||
|
""" Send a email to the admin of the system and / or the user |
||||
|
to inform passkey use.""" |
||||
|
mails = [] |
||||
|
mail_obj = self.env['mail.mail'] |
||||
|
icp_obj = self.env['ir.config_parameter'] |
||||
|
admin_user = self.sudo().browse(SUPERUSER_ID) |
||||
|
login_user = self.sudo().browse(self.env.uid) |
||||
|
send_to_admin = safe_eval(icp_obj.sudo().get_param( |
||||
|
'auth_admin_passkey.send_to_admin', |
||||
|
'True')) |
||||
|
send_to_user = safe_eval(icp_obj.sudo().get_param( |
||||
|
'auth_admin_passkey.send_to_user', |
||||
|
'True')) |
||||
|
|
||||
|
if send_to_admin and admin_user.email: |
||||
|
mails.append({'email': admin_user.email, 'lang': admin_user.lang}) |
||||
|
if send_to_user and login_user.email: |
||||
|
mails.append({'email': login_user.email, 'lang': login_user.lang}) |
||||
|
for mail in mails: |
||||
|
subject = self._get_translation( |
||||
|
mail['lang'], _('Passkey used')) |
||||
|
body = self._get_translation( |
||||
|
mail['lang'], |
||||
|
_("""Admin user used his passkey to login with '%s'.\n\n""" |
||||
|
"""\n\nTechnicals informations belows : \n\n""" |
||||
|
"""- Login date : %s\n\n""")) % ( |
||||
|
login_user.login, |
||||
|
datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")) |
||||
|
for k, v in user_agent_env.iteritems(): |
||||
|
body += ("- %s : %s\n\n") % (k, v) |
||||
|
mail = mail_obj.sudo().create({ |
||||
|
'email_to': mail['email'], |
||||
|
'subject': subject, |
||||
|
'body_html': '<pre>%s</pre>' % body}) |
||||
|
mail.send(auto_commit=True) |
||||
|
|
||||
|
@api.cr |
||||
|
def _send_email_same_password(self, login_user): |
||||
|
""" Send a email to the admin user to inform that another user has the |
||||
|
same password as him.""" |
||||
|
mail_obj = self.env['mail.mail'] |
||||
|
admin_user = self.sudo().browse(SUPERUSER_ID) |
||||
|
if admin_user.email: |
||||
|
mail = mail_obj.sudo().create({ |
||||
|
'email_to': admin_user.email, |
||||
|
'subject': self._get_translation( |
||||
|
admin_user.lang, _('[WARNING] OpenERP Security Risk')), |
||||
|
'body_html': self._get_translation( |
||||
|
admin_user.lang, _( |
||||
|
"""<pre>User with login '%s' has the same """ |
||||
|
"""password as you.</pre>""")) % (login_user), |
||||
|
}) |
||||
|
mail.send(auto_commit=True) |
||||
|
|
||||
|
# Overload Section |
||||
|
def authenticate(self, db, login, password, user_agent_env): |
||||
|
""" Authenticate the user 'login' is password is ok or if |
||||
|
is admin password. In the second case, send mail to user and admin.""" |
||||
|
user_id = super(ResUsers, self).authenticate( |
||||
|
db, login, password, user_agent_env) |
||||
|
if user_id and (user_id != SUPERUSER_ID): |
||||
|
same_password = False |
||||
|
cr = registry(db).cursor() |
||||
|
try: |
||||
|
# directly use parent 'check_credentials' function |
||||
|
# to really know if credentials are ok |
||||
|
# or if it was admin password |
||||
|
super(ResUsers, self).check_credentials( |
||||
|
cr, SUPERUSER_ID, password) |
||||
|
try: |
||||
|
# Test now if the user has the same password as admin user |
||||
|
super(ResUsers, self).check_credentials( |
||||
|
cr, user_id, password) |
||||
|
same_password = True |
||||
|
except exceptions.AccessDenied: |
||||
|
pass |
||||
|
if not same_password: |
||||
|
self._send_email_passkey(cr, user_id, user_agent_env) |
||||
|
else: |
||||
|
self._send_email_same_password(cr, login) |
||||
|
except exceptions.AccessDenied: |
||||
|
pass |
||||
|
finally: |
||||
|
cr.close() |
||||
|
return user_id |
||||
|
|
||||
|
@api.model |
||||
|
def check_credentials(self, password): |
||||
|
""" Return now True if credentials are good OR if password is admin |
||||
|
password.""" |
||||
|
if self.env.uid != SUPERUSER_ID: |
||||
|
try: |
||||
|
super(ResUsers, self).check_credentials(password) |
||||
|
return True |
||||
|
except exceptions.AccessDenied: |
||||
|
return self.sudo().check_credentials(password) |
||||
|
else: |
||||
|
return super(ResUsers, self).check_credentials(password) |
Write
Preview
Loading…
Cancel
Save
Reference in new issue