You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

137 lines
5.8 KiB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
  1. # -*- encoding: utf-8 -*-
  2. ##############################################################################
  3. #
  4. # Admin Passkey module for Odoo
  5. # Copyright (C) 2013-2014 GRAP (http://www.grap.coop)
  6. # @author Sylvain LE GAL (https://twitter.com/legalsylvain)
  7. #
  8. # This program is free software: you can redistribute it and/or modify
  9. # it under the terms of the GNU Affero General Public License as
  10. # published by the Free Software Foundation, either version 3 of the
  11. # License, or (at your option) any later version.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU Affero General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU Affero General Public License
  19. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. #
  21. ##############################################################################
  22. import datetime
  23. from openerp import SUPERUSER_ID
  24. from openerp import pooler
  25. from openerp import exceptions
  26. from openerp.osv.orm import Model
  27. from openerp.tools.translate import _
  28. from openerp.tools.safe_eval import safe_eval
  29. class res_users(Model):
  30. _inherit = "res.users"
  31. # Private Function section
  32. def _get_translation(self, cr, lang, text):
  33. context = {'lang': lang} # noqa: _() checks page for locals
  34. return _(text)
  35. def _send_email_passkey(self, cr, user_id, user_agent_env):
  36. """ Send a email to the admin of the system and / or the user
  37. to inform passkey use."""
  38. mails = []
  39. mail_obj = self.pool['mail.mail']
  40. icp_obj = self.pool['ir.config_parameter']
  41. admin_user = self.browse(cr, SUPERUSER_ID, SUPERUSER_ID)
  42. login_user = self.browse(cr, SUPERUSER_ID, user_id)
  43. send_to_admin = safe_eval(icp_obj.get_param(
  44. cr, SUPERUSER_ID, 'auth_admin_passkey.send_to_admin', 'True'))
  45. send_to_user = safe_eval(icp_obj.get_param(
  46. cr, SUPERUSER_ID, 'auth_admin_passkey.send_to_user', 'True'))
  47. if send_to_admin and admin_user.email:
  48. mails.append({'email': admin_user.email, 'lang': admin_user.lang})
  49. if send_to_user and login_user.email:
  50. mails.append({'email': login_user.email, 'lang': login_user.lang})
  51. for mail in mails:
  52. subject = self._get_translation(
  53. cr, mail['lang'], _('Passkey used'))
  54. body = self._get_translation(
  55. cr, mail['lang'],
  56. _("""Admin user used his passkey to login with '%s'.\n\n"""
  57. """\n\nTechnicals informations belows : \n\n"""
  58. """- Login date : %s\n\n""")) % (
  59. login_user.login,
  60. datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
  61. for k, v in user_agent_env.iteritems():
  62. body += ("- %s : %s\n\n") % (k, v)
  63. mail_obj.create(
  64. cr, SUPERUSER_ID, {
  65. 'email_to': mail['email'],
  66. 'subject': subject,
  67. 'body_html': '<pre>%s</pre>' % body})
  68. def _send_email_same_password(self, cr, login_user):
  69. """ Send a email to the admin user to inform that another user has the
  70. same password as him."""
  71. mail_obj = self.pool['mail.mail']
  72. admin_user = self.browse(cr, SUPERUSER_ID, SUPERUSER_ID)
  73. if admin_user.email:
  74. mail_obj.create(cr, SUPERUSER_ID, {
  75. 'email_to': admin_user.email,
  76. 'subject': self._get_translation(
  77. cr, admin_user.lang, _('[WARNING] Odoo Security Risk')),
  78. 'body_html': self._get_translation(
  79. cr, admin_user.lang, _(
  80. """<pre>User with login '%s' has the same """
  81. """password as you.</pre>""")) % (login_user),
  82. })
  83. # Overload Section
  84. def authenticate(self, db, login, password, user_agent_env):
  85. """ Authenticate the user 'login' is password is ok or if
  86. is admin password. In the second case, send mail to user and admin."""
  87. user_id = super(res_users, self).authenticate(
  88. db, login, password, user_agent_env)
  89. if user_id and (user_id != SUPERUSER_ID):
  90. same_password = False
  91. cr = pooler.get_db(db).cursor()
  92. try:
  93. # directly use parent 'check_credentials' function
  94. # to really know if credentials are ok
  95. # or if it was admin password
  96. super(res_users, self).check_credentials(
  97. cr, SUPERUSER_ID, password)
  98. try:
  99. # Test now if the user has the same password as admin user
  100. super(res_users, self).check_credentials(
  101. cr, user_id, password)
  102. same_password = True
  103. except exceptions.AccessDenied:
  104. pass
  105. if not same_password:
  106. self._send_email_passkey(cr, user_id, user_agent_env)
  107. else:
  108. self._send_email_same_password(cr, login)
  109. cr.commit()
  110. except exceptions.AccessDenied:
  111. pass
  112. finally:
  113. cr.close()
  114. return user_id
  115. def check_credentials(self, cr, uid, password):
  116. """ Return now True if credentials are good OR if password is admin
  117. password."""
  118. if uid != SUPERUSER_ID:
  119. try:
  120. super(res_users, self).check_credentials(
  121. cr, uid, password)
  122. return True
  123. except exceptions.AccessDenied:
  124. return self.check_credentials(cr, SUPERUSER_ID, password)
  125. else:
  126. return super(res_users, self).check_credentials(cr, uid, password)