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.

135 lines
5.1 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 .. import utils
  27. import random
  28. import logging
  29. import werkzeug
  30. _logger = logging.getLogger(__name__)
  31. class Home(main.Home):
  32. _REQUIRED_ATTRIBUTES = ['HTTP_REMOTE_USER']
  33. _OPTIONAL_ATTRIBUTES = []
  34. @http.route('/web', type='http', auth="none")
  35. def web_client(self, s_action=None, **kw):
  36. main.ensure_db()
  37. if not request.session.uid:
  38. try:
  39. self._bind_http_remote_user(http.request.session.db)
  40. except http.AuthenticationError:
  41. return werkzeug.exceptions.Unauthorized()
  42. return super(Home, self).web_client(s_action, **kw)
  43. def _get_user_id_from_attributes(self, res_users, cr, attrs):
  44. login = attrs.get('HTTP_REMOTE_USER', None)
  45. user_ids = res_users.search(cr, SUPERUSER_ID, [('login', '=', login),
  46. ('active', '=', True)])
  47. assert len(user_ids) < 2
  48. if user_ids:
  49. return user_ids[0]
  50. return None
  51. def _get_attributes_form_header(self):
  52. attrs = {}
  53. all_attrs = self._REQUIRED_ATTRIBUTES + self._OPTIONAL_ATTRIBUTES
  54. headers = http.request.httprequest.headers.environ
  55. for attr in all_attrs:
  56. value = headers.get(attr, None)
  57. if value is not None:
  58. attrs[attr] = value
  59. attrs_found = set(attrs.keys())
  60. attrs_missing = set(all_attrs) - attrs_found
  61. if len(attrs_found) > 0:
  62. _logger.debug("Fields '%s' not found in http headers\n %s",
  63. attrs_missing, headers)
  64. missings = set(self._REQUIRED_ATTRIBUTES) - attrs_found
  65. if len(missings) > 0:
  66. _logger.error("Required fields '%s' not found in http headers\n %s",
  67. missings, headers)
  68. return attrs
  69. def _bind_http_remote_user(self, db_name):
  70. try:
  71. registry = openerp.registry(db_name)
  72. with registry.cursor() as cr:
  73. modules = registry.get('ir.module.module')
  74. domain = ['&',
  75. ('name', '=', 'auth_from_http_remote_user'),
  76. ('state', '=', 'installed')]
  77. installed = modules.search_count(cr, SUPERUSER_ID, domain) == 1
  78. if not installed:
  79. return
  80. config = registry.get('auth_from_http_remote_user.'
  81. 'config.settings')
  82. # get parameters for SSO
  83. default_login_page_disabled = \
  84. config.is_default_login_page_disabled(cr,
  85. SUPERUSER_ID,
  86. None)
  87. # get the user
  88. res_users = registry.get('res.users')
  89. attrs = self._get_attributes_form_header()
  90. user_id = self._get_user_id_from_attributes(res_users,
  91. cr,
  92. attrs)
  93. if user_id is None:
  94. if default_login_page_disabled:
  95. raise http.AuthenticationError()
  96. return
  97. # generate a specific key for authentication
  98. key = randomString(utils.KEY_LENGTH, '0123456789abcdef')
  99. res_users.write(cr, SUPERUSER_ID, [user_id], {'sso_key': key})
  100. login = res_users.browse(cr, SUPERUSER_ID, user_id).login
  101. request.session.authenticate(db_name, login=login,
  102. password=key, uid=user_id)
  103. except http.AuthenticationError, e:
  104. raise e
  105. except Exception, e:
  106. _logger.error("Error binding Http Remote User session",
  107. exc_info=True)
  108. raise e
  109. randrange = random.SystemRandom().randrange
  110. def randomString(length, chrs):
  111. """Produce a string of length random bytes, chosen from chrs."""
  112. n = len(chrs)
  113. return ''.join([chrs[randrange(n)] for _ in xrange(length)])