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.

110 lines
4.0 KiB

  1. # -*- coding: utf-8 -*-
  2. ##############################################################################
  3. #
  4. # Author: Laurent Mignon
  5. # Copyright 2014 'ACSONE SA/NV'
  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. from openerp import SUPERUSER_ID
  22. import openerp
  23. from openerp import http
  24. from openerp.http import request
  25. from openerp.addons.web.controllers import main
  26. from openerp.addons.auth_from_http_remote_user.model import \
  27. AuthFromHttpRemoteUserInstalled
  28. from .. import utils
  29. import random
  30. import logging
  31. import werkzeug
  32. _logger = logging.getLogger(__name__)
  33. class Home(main.Home):
  34. _REMOTE_USER_ATTRIBUTE = 'HTTP_REMOTE_USER'
  35. @http.route('/web', type='http', auth="none")
  36. def web_client(self, s_action=None, **kw):
  37. main.ensure_db()
  38. try:
  39. self._bind_http_remote_user(http.request.session.db)
  40. except http.AuthenticationError:
  41. return werkzeug.exceptions.Unauthorized().get_response()
  42. return super(Home, self).web_client(s_action, **kw)
  43. def _search_user(self, res_users, login, cr):
  44. user_ids = res_users.search(cr, SUPERUSER_ID, [('login', '=', login),
  45. ('active', '=', True)])
  46. assert len(user_ids) < 2
  47. if user_ids:
  48. return user_ids[0]
  49. return None
  50. def _bind_http_remote_user(self, db_name):
  51. try:
  52. registry = openerp.registry(db_name)
  53. with registry.cursor() as cr:
  54. if AuthFromHttpRemoteUserInstalled._name not in registry:
  55. # module not installed in database,
  56. # continue usual behavior
  57. return
  58. headers = http.request.httprequest.headers.environ
  59. login = headers.get(self._REMOTE_USER_ATTRIBUTE, None)
  60. if not login:
  61. # no HTTP_REMOTE_USER header,
  62. # continue usual behavior
  63. return
  64. request_login = request.session.login
  65. if request_login:
  66. if request_login == login:
  67. # already authenticated
  68. return
  69. else:
  70. request.session.logout(keep_db=True)
  71. res_users = registry.get('res.users')
  72. user_id = self._search_user(res_users, login, cr)
  73. if not user_id:
  74. # HTTP_REMOTE_USER login not found in database
  75. request.session.logout(keep_db=True)
  76. raise http.AuthenticationError()
  77. # generate a specific key for authentication
  78. key = randomString(utils.KEY_LENGTH, '0123456789abcdef')
  79. res_users.write(cr, SUPERUSER_ID, [user_id], {'sso_key': key})
  80. request.session.authenticate(db_name, login=login,
  81. password=key, uid=user_id)
  82. except http.AuthenticationError, e:
  83. raise e
  84. except Exception, e:
  85. _logger.error("Error binding Http Remote User session",
  86. exc_info=True)
  87. raise e
  88. randrange = random.SystemRandom().randrange
  89. def randomString(length, chrs):
  90. """Produce a string of length random bytes, chosen from chrs."""
  91. n = len(chrs)
  92. return ''.join([chrs[randrange(n)] for _ in xrange(length)])