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.

97 lines
3.5 KiB

8 years ago
  1. # -*- coding: utf-8 -*-
  2. # Copyright 2014 ACSONE SA/NV (<http://acsone.eu>)
  3. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  4. from openerp import SUPERUSER_ID
  5. from openerp import http
  6. from openerp.http import request
  7. from openerp.addons.web.controllers import main
  8. from openerp.modules.registry import RegistryManager
  9. from ..models.auth_from_http_remote_user import \
  10. AuthFromHttpRemoteUserInstalled
  11. from .. import utils
  12. import random
  13. import logging
  14. import werkzeug
  15. _logger = logging.getLogger(__name__)
  16. class Home(main.Home):
  17. _REMOTE_USER_ATTRIBUTE = 'HTTP_REMOTE_USER'
  18. @http.route('/web', type='http', auth="none")
  19. def web_client(self, s_action=None, **kw):
  20. main.ensure_db()
  21. try:
  22. self._bind_http_remote_user(http.request.session.db)
  23. except http.AuthenticationError:
  24. return werkzeug.exceptions.Unauthorized().get_response()
  25. return super(Home, self).web_client(s_action, **kw)
  26. def _search_user(self, res_users, login, cr):
  27. user_ids = res_users.search(cr, SUPERUSER_ID, [('login', '=', login),
  28. ('active', '=', True)])
  29. assert len(user_ids) < 2
  30. if user_ids:
  31. return user_ids[0]
  32. return None
  33. def _bind_http_remote_user(self, db_name):
  34. try:
  35. registry = RegistryManager.get(db_name)
  36. with registry.cursor() as cr:
  37. if AuthFromHttpRemoteUserInstalled._name not in registry:
  38. # module not installed in database,
  39. # continue usual behavior
  40. return
  41. headers = http.request.httprequest.headers.environ
  42. login = headers.get(self._REMOTE_USER_ATTRIBUTE, None)
  43. if not login:
  44. # no HTTP_REMOTE_USER header,
  45. # continue usual behavior
  46. _logger.debug("Required fields '%s' not found in http"
  47. " headers\n %s",
  48. self._REMOTE_USER_ATTRIBUTE, headers)
  49. return
  50. request_login = request.session.login
  51. if request_login:
  52. if request_login == login:
  53. # already authenticated
  54. return
  55. else:
  56. request.session.logout(keep_db=True)
  57. res_users = registry.get('res.users')
  58. user_id = self._search_user(res_users, login, cr)
  59. if not user_id:
  60. # HTTP_REMOTE_USER login not found in database
  61. request.session.logout(keep_db=True)
  62. raise http.AuthenticationError()
  63. # generate a specific key for authentication
  64. key = randomString(utils.KEY_LENGTH, '0123456789abcdef')
  65. res_users.write(cr, SUPERUSER_ID, [user_id], {'sso_key': key})
  66. request.session.authenticate(db_name, login=login,
  67. password=key, uid=user_id)
  68. except http.AuthenticationError, e:
  69. raise e
  70. except Exception, e:
  71. _logger.error("Error binding Http Remote User session",
  72. exc_info=True)
  73. raise e
  74. randrange = random.SystemRandom().randrange
  75. def randomString(length, chrs):
  76. """Produce a string of length random bytes, chosen from chrs."""
  77. n = len(chrs)
  78. return ''.join([chrs[randrange(n)] for _ in xrange(length)])