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.

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