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.

138 lines
5.2 KiB

10 years ago
  1. # -*- coding: utf-8 -*-
  2. ##############################################################################
  3. #
  4. # Author: Matthieu Dietrich
  5. # Copyright 2015 Camptocamp SA
  6. #
  7. # This program is free software: you can redistribute it and/or modify
  8. # it under the terms of the GNU Affero General Public License as
  9. # published by the Free Software Foundation, either version 3 of the
  10. # License, or (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU Affero General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU Affero General Public License
  18. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. #
  20. ##############################################################################
  21. import logging
  22. import psycopg2
  23. import openerp.exceptions
  24. from openerp import SUPERUSER_ID
  25. from openerp.osv import orm, fields
  26. _logger = logging.getLogger(__name__)
  27. # New class to store the login date
  28. class ResUsersLogin(orm.Model):
  29. _name = 'res.users.login'
  30. _columns = {
  31. 'user_id': fields.many2one(
  32. 'res.users', 'User', required=True, ondelete="cascade"),
  33. 'login_dt': fields.date('Latest connection'),
  34. }
  35. _sql_constraints = [
  36. ('user_id_unique',
  37. 'unique(user_id)',
  38. 'The user can only have one login line!')
  39. ]
  40. # Cron method
  41. def cron_sync_login_date(self, cr, uid, context=None):
  42. # Simple SQL query to update the original login_date column.
  43. try:
  44. cr.execute("UPDATE res_users SET login_date = "
  45. "(SELECT login_dt FROM res_users_login "
  46. "WHERE res_users_login.user_id = res_users.id)")
  47. cr.commit()
  48. except Exception as e:
  49. cr.rollback()
  50. _logger.exception('Could not synchronize login dates: %s', e)
  51. return True
  52. class ResUsers(orm.Model):
  53. _inherit = 'res.users'
  54. # Function to retrieve the login date from the res.users object
  55. # (used in some functions, and the user state)
  56. def _get_login_date(self, cr, uid, ids, name, args, context=None):
  57. res = {}
  58. user_login_obj = self.pool['res.users.login']
  59. for user_id in ids:
  60. login_ids = user_login_obj.search(
  61. cr, uid, [('user_id', '=', user_id)], limit=1,
  62. context=context)
  63. if len(login_ids) == 0:
  64. res[user_id] = False
  65. else:
  66. login = user_login_obj.browse(cr, uid, login_ids[0],
  67. context=context)
  68. res[user_id] = login.login_dt
  69. return res
  70. _columns = {
  71. 'login_date': fields.function(_get_login_date,
  72. string='Latest connection',
  73. type='date', select=1,
  74. readonly=True, store=False,
  75. nodrop=True),
  76. }
  77. # Re-defining the login function in order to use the new table
  78. def _login(self, db, login, password):
  79. if not password:
  80. return False
  81. user_id = False
  82. cr = self.pool.cursor()
  83. try:
  84. # check if user exists
  85. res = self.search(cr, SUPERUSER_ID, [('login', '=', login)])
  86. if res:
  87. user_id = res[0]
  88. try:
  89. # check credentials
  90. self.check_credentials(cr, user_id, password)
  91. except openerp.exceptions.AccessDenied:
  92. _logger.info("Login failed for db:%s login:%s", db, login)
  93. user_id = False
  94. if user_id:
  95. try:
  96. cr.execute("SELECT login_dt "
  97. "FROM res_users_login "
  98. "WHERE user_id=%s "
  99. "FOR UPDATE NOWAIT", (user_id,),
  100. log_exceptions=False)
  101. # create login line if not existing
  102. result = cr.fetchone()
  103. if result:
  104. cr.execute("UPDATE res_users_login "
  105. "SET login_dt = now() "
  106. "AT TIME ZONE 'UTC' "
  107. "WHERE user_id=%s", (user_id,))
  108. else:
  109. cr.execute("INSERT INTO res_users_login "
  110. "(user_id, login_dt) "
  111. "VALUES (%s, now())", (user_id,))
  112. cr.commit()
  113. except psycopg2.OperationalError:
  114. _logger.warning("Failed to update last_login "
  115. "for db:%s login:%s",
  116. db, login, exc_info=True)
  117. cr.rollback()
  118. except Exception as e:
  119. _logger.exception('Login exception: %s', e)
  120. user_id = False
  121. finally:
  122. cr.close()
  123. return user_id