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.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('res.users', 'User', required=True),
  32. 'login_dt': fields.date('Latest connection'),
  33. }
  34. _sql_constraints = [
  35. ('user_id_unique',
  36. 'unique(user_id)',
  37. 'The user can only have one login line!')
  38. ]
  39. # Cron method
  40. def cron_sync_login_date(self, cr, uid, context=None):
  41. # Simple SQL query to update the original login_date column.
  42. try:
  43. cr.execute("UPDATE res_users SET login_date = "
  44. "(SELECT login_dt FROM res_users_login "
  45. "WHERE res_users_login.user_id = res_users.id)")
  46. cr.commit()
  47. except Exception as e:
  48. cr.rollback()
  49. _logger.exception('Could not synchronize login dates: %s', e)
  50. return True
  51. class ResUsers(orm.Model):
  52. _inherit = 'res.users'
  53. # Function to retrieve the login date from the res.users object
  54. # (used in some functions, and the user state)
  55. def _get_login_date(self, cr, uid, ids, name, args, context=None):
  56. res = {}
  57. user_login_obj = self.pool['res.users.login']
  58. for user_id in ids:
  59. login_ids = user_login_obj.search(
  60. cr, uid, [('user_id', '=', user_id)], limit=1,
  61. context=context)
  62. if len(login_ids) == 0:
  63. res[user_id] = False
  64. else:
  65. login = user_login_obj.browse(cr, uid, login_ids[0],
  66. context=context)
  67. res[user_id] = login.login_dt
  68. return res
  69. _columns = {
  70. 'login_date': fields.function(_get_login_date,
  71. string='Latest connection',
  72. type='date', select=1,
  73. readonly=True, store=False,
  74. nodrop=True),
  75. }
  76. # Re-defining the login function in order to use the new table
  77. def _login(self, db, login, password):
  78. if not password:
  79. return False
  80. user_id = False
  81. cr = self.pool.cursor()
  82. try:
  83. # check if user exists
  84. res = self.search(cr, SUPERUSER_ID, [('login', '=', login)])
  85. if res:
  86. user_id = res[0]
  87. try:
  88. # check credentials
  89. self.check_credentials(cr, user_id, password)
  90. except openerp.exceptions.AccessDenied:
  91. _logger.info("Login failed for db:%s login:%s", db, login)
  92. user_id = False
  93. if user_id:
  94. try:
  95. cr.execute("SELECT login_dt "
  96. "FROM res_users_login "
  97. "WHERE user_id=%s "
  98. "FOR UPDATE NOWAIT", (user_id,),
  99. log_exceptions=False)
  100. # create login line if not existing
  101. result = cr.fetchone()
  102. if result:
  103. cr.execute("UPDATE res_users_login "
  104. "SET login_dt = now() "
  105. "AT TIME ZONE 'UTC' "
  106. "WHERE user_id=%s", (user_id,))
  107. else:
  108. cr.execute("INSERT INTO res_users_login "
  109. "(user_id, login_dt) "
  110. "VALUES (%s, now())", (user_id,))
  111. cr.commit()
  112. except psycopg2.OperationalError:
  113. _logger.warning("Failed to update last_login "
  114. "for db:%s login:%s",
  115. db, login, exc_info=True)
  116. cr.rollback()
  117. except Exception as e:
  118. _logger.exception('Login exception: %s', e)
  119. user_id = False
  120. finally:
  121. cr.close()
  122. return user_id