80 lines
3.3 KiB
Python
80 lines
3.3 KiB
Python
# -*- coding: utf-8 -*-
|
|
import re
|
|
|
|
from odoo import http, _
|
|
from odoo.exceptions import AccessDenied
|
|
from odoo.http import request
|
|
from odoo.addons.web.controllers import home as web_home
|
|
|
|
TRUSTED_DEVICE_COOKIE = 'td_id'
|
|
TRUSTED_DEVICE_AGE = 90*86400 # 90 days expiration
|
|
|
|
|
|
class Home(web_home.Home):
|
|
@http.route(
|
|
'/web/login/totp',
|
|
type='http', auth='public', methods=['GET', 'POST'], sitemap=False,
|
|
website=True, multilang=False # website breaks the login layout...
|
|
)
|
|
def web_totp(self, redirect=None, **kwargs):
|
|
if request.session.uid:
|
|
return request.redirect(self._login_redirect(request.session.uid, redirect=redirect))
|
|
|
|
if not request.session.pre_uid:
|
|
return request.redirect('/web/login')
|
|
|
|
error = None
|
|
|
|
user = request.env['res.users'].browse(request.session.pre_uid)
|
|
if user and request.httprequest.method == 'GET':
|
|
cookies = request.httprequest.cookies
|
|
key = cookies.get(TRUSTED_DEVICE_COOKIE)
|
|
if key:
|
|
user_match = request.env['auth_totp.device']._check_credentials_for_uid(
|
|
scope="browser", key=key, uid=user.id)
|
|
if user_match:
|
|
request.session.finalize(request.env)
|
|
return request.redirect(self._login_redirect(request.session.uid, redirect=redirect))
|
|
|
|
elif user and request.httprequest.method == 'POST' and kwargs.get('totp_token'):
|
|
try:
|
|
with user._assert_can_auth(user=user.id):
|
|
user._totp_check(int(re.sub(r'\s', '', kwargs['totp_token'])))
|
|
except AccessDenied as e:
|
|
error = str(e)
|
|
except ValueError:
|
|
error = _("Invalid authentication code format.")
|
|
else:
|
|
request.session.finalize(request.env)
|
|
request.update_env(user=request.session.uid)
|
|
request.update_context(**request.session.context)
|
|
response = request.redirect(self._login_redirect(request.session.uid, redirect=redirect))
|
|
if kwargs.get('remember'):
|
|
name = _("%(browser)s on %(platform)s",
|
|
browser=request.httprequest.user_agent.browser.capitalize(),
|
|
platform=request.httprequest.user_agent.platform.capitalize(),
|
|
)
|
|
|
|
if request.geoip.city.name:
|
|
name += f" ({request.geoip.city.name}, {request.geoip.country_name})"
|
|
|
|
key = request.env['auth_totp.device']._generate("browser", name)
|
|
response.set_cookie(
|
|
key=TRUSTED_DEVICE_COOKIE,
|
|
value=key,
|
|
max_age=TRUSTED_DEVICE_AGE,
|
|
httponly=True,
|
|
samesite='Lax'
|
|
)
|
|
# Crapy workaround for unupdatable Odoo Mobile App iOS (Thanks Apple :@)
|
|
request.session.touch()
|
|
return response
|
|
|
|
# Crapy workaround for unupdatable Odoo Mobile App iOS (Thanks Apple :@)
|
|
request.session.touch()
|
|
return request.render('auth_totp.auth_totp_form', {
|
|
'user': user,
|
|
'error': error,
|
|
'redirect': redirect,
|
|
})
|