from odoo import models, api, exceptions, fields, _ from odoo.http import request from datetime import datetime from time import mktime import hmac from hashlib import sha256 from logging import getLogger _logger = getLogger(__name__) def admin_auth_generate_login(env, user): """ Generates a URL to allow the current user to login as the portal user. :param env: Odoo environment :param user: `res.users` in :return: """ if not env['res.partner'].check_access_rights('write'): return None u = str(user.id) now = datetime.utcnow() fifteen = int(mktime(now.timetuple())) + (15 * 60) e = str(fifteen) o = str(env.uid) config = env['ir.config_parameter'].sudo() key = str(config.search([('key', '=', 'database.secret')], limit=1).value) h = hmac.new(key.encode(), (u + e + o).encode(), sha256) base_url = str(config.search([('key', '=', 'web.base.url')], limit=1).value) _logger.warning('login url for user id: ' + u + ' original user id: ' + o) return base_url + '/auth_admin?u=' + u + '&e=' + e + '&o=' + o + '&h=' + h.hexdigest() def check_admin_auth_login(env, u_user_id, e_expires, o_org_user_id, hash_): """ Checks that the parameters are valid and that the user exists. :param env: Odoo environment :param u_user_id: Desired user id to login as. :param e_expires: Expiration timestamp :param o_org_user_id: Original user id. :param hash_: HMAC generated hash :return: `res.users` """ now = datetime.utcnow() now = int(mktime(now.timetuple())) fifteen = now + (15 * 60) config = env['ir.config_parameter'].sudo() key = str(config.search([('key', '=', 'database.secret')], limit=1).value) myh = hmac.new(key.encode(), str(str(u_user_id) + str(e_expires) + str(o_org_user_id)).encode(), sha256) if not hmac.compare_digest(hash_, myh.hexdigest()): raise exceptions.AccessDenied('Invalid Request') if not (now <= int(e_expires) <= fifteen): raise exceptions.AccessDenied('Expired') user = env['res.users'].sudo().search([('id', '=', int(u_user_id))], limit=1) if not user.id: raise exceptions.AccessDenied('Invalid User') return user class ResUsers(models.Model): _inherit = 'res.users' def admin_auth_generate_login(self): self.ensure_one() login_url = admin_auth_generate_login(self.env, self) if login_url: wizard = self.env['res.users.wizard'].create({ 'force_login_url': login_url, }) return { 'name': _('Generate Login URL'), 'type': 'ir.actions.act_window', 'view_mode': 'form', 'res_model': 'res.users.wizard', 'res_id': wizard.id, 'target': 'new', } return False def _check_credentials(self, password, env): try: return super(ResUsers, self)._check_credentials(password, env) except exceptions.AccessDenied: if request and hasattr(request, 'session') and request.session.get('auth_admin'): _logger.warning('_check_credentials for user id: ' + \ str(request.session.uid) + ' original user id: ' + str(request.session.auth_admin)) else: raise class ResUsersWizard(models.TransientModel): _name = 'res.users.wizard' force_login_url = fields.Char(string='Force Login URL')