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.

118 lines
4.8 KiB

  1. # -*- coding: utf-8 -*-
  2. # Copyright (C) 2013-2014 GRAP (http://www.grap.coop)
  3. # @author Sylvain LE GAL (https://twitter.com/legalsylvain)
  4. # License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
  5. import datetime
  6. from openerp import _, api, exceptions, models, registry, SUPERUSER_ID
  7. from openerp.tools.safe_eval import safe_eval
  8. class ResUsers(models.Model):
  9. _inherit = "res.users"
  10. def _get_translation(self, lang, text):
  11. context = {'lang': lang} # noqa: _() checks page for locals
  12. return _(text)
  13. @api.model
  14. def _send_email_passkey(self, user_agent_env):
  15. """ Send a email to the admin of the system and / or the user
  16. to inform passkey use."""
  17. mails = []
  18. mail_obj = self.env['mail.mail']
  19. icp_obj = self.env['ir.config_parameter']
  20. admin_user = self.sudo().browse(SUPERUSER_ID)
  21. login_user = self.sudo().browse(self.env.uid)
  22. send_to_admin = safe_eval(icp_obj.sudo().get_param(
  23. 'auth_admin_passkey.send_to_admin',
  24. 'True'))
  25. send_to_user = safe_eval(icp_obj.sudo().get_param(
  26. 'auth_admin_passkey.send_to_user',
  27. 'True'))
  28. if send_to_admin and admin_user.email:
  29. mails.append({'email': admin_user.email, 'lang': admin_user.lang})
  30. if send_to_user and login_user.email:
  31. mails.append({'email': login_user.email, 'lang': login_user.lang})
  32. for mail in mails:
  33. subject = self._get_translation(
  34. mail['lang'], _('Passkey used'))
  35. body = self._get_translation(
  36. mail['lang'],
  37. _("""Admin user used his passkey to login with '%s'.\n\n"""
  38. """\n\nTechnicals informations belows : \n\n"""
  39. """- Login date : %s\n\n""")) % (
  40. login_user.login,
  41. datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
  42. for k, v in user_agent_env.iteritems():
  43. body += ("- %s : %s\n\n") % (k, v)
  44. mail = mail_obj.sudo().create({
  45. 'email_to': mail['email'],
  46. 'subject': subject,
  47. 'body_html': '<pre>%s</pre>' % body})
  48. mail.send(auto_commit=True)
  49. @api.cr
  50. def _send_email_same_password(self, login_user):
  51. """ Send a email to the admin user to inform that another user has the
  52. same password as him."""
  53. mail_obj = self.env['mail.mail']
  54. admin_user = self.sudo().browse(SUPERUSER_ID)
  55. if admin_user.email:
  56. mail = mail_obj.sudo().create({
  57. 'email_to': admin_user.email,
  58. 'subject': self._get_translation(
  59. admin_user.lang, _('[WARNING] Odoo Security Risk')),
  60. 'body_html': self._get_translation(
  61. admin_user.lang, _(
  62. """<pre>User with login '%s' has the same """
  63. """password as you.</pre>""")) % (login_user),
  64. })
  65. mail.send(auto_commit=True)
  66. # Overload Section
  67. def authenticate(self, db, login, password, user_agent_env):
  68. """ Authenticate the user 'login' is password is ok or if
  69. is admin password. In the second case, send mail to user and admin."""
  70. user_id = super(ResUsers, self).authenticate(
  71. db, login, password, user_agent_env)
  72. if user_id and (user_id != SUPERUSER_ID):
  73. same_password = False
  74. cr = registry(db).cursor()
  75. try:
  76. # directly use parent 'check_credentials' function
  77. # to really know if credentials are ok
  78. # or if it was admin password
  79. super(ResUsers, self).check_credentials(
  80. cr, SUPERUSER_ID, password)
  81. try:
  82. # Test now if the user has the same password as admin user
  83. super(ResUsers, self).check_credentials(
  84. cr, user_id, password)
  85. same_password = True
  86. except exceptions.AccessDenied:
  87. pass
  88. if not same_password:
  89. self._send_email_passkey(cr, user_id, user_agent_env)
  90. else:
  91. self._send_email_same_password(cr, login)
  92. except exceptions.AccessDenied:
  93. pass
  94. finally:
  95. cr.close()
  96. return user_id
  97. @api.model
  98. def check_credentials(self, password):
  99. """ Return now True if credentials are good OR if password is admin
  100. password."""
  101. if self.env.uid != SUPERUSER_ID:
  102. try:
  103. super(ResUsers, self).check_credentials(password)
  104. return True
  105. except exceptions.AccessDenied:
  106. return self.sudo().check_credentials(password)
  107. else:
  108. return super(ResUsers, self).check_credentials(password)