mirror of
https://github.com/bringout/oca-ocb-security.git
synced 2026-04-19 21:12:01 +02:00
19.0 vanilla
This commit is contained in:
parent
20ddc1b4a3
commit
c0efcc53f5
1162 changed files with 125577 additions and 105287 deletions
|
|
@ -3,14 +3,15 @@
|
|||
|
||||
import json
|
||||
import logging
|
||||
import requests
|
||||
|
||||
from werkzeug.exceptions import Forbidden
|
||||
from werkzeug.urls import url_encode
|
||||
|
||||
from odoo import _, http
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.http import request
|
||||
from odoo.tools import consteq
|
||||
from odoo.tools import consteq, email_normalize
|
||||
from odoo.addons.google_gmail.models.google_gmail_mixin import GMAIL_TOKEN_REQUEST_TIMEOUT
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -24,12 +25,12 @@ class GoogleGmailController(http.Controller):
|
|||
We will fetch the refresh token and the access token thanks to this authorization
|
||||
code and save those values on the given mail server.
|
||||
"""
|
||||
if not request.env.user.has_group('base.group_system'):
|
||||
_logger.error('Google Gmail: non-system user trying to link an Gmail account.')
|
||||
raise Forbidden()
|
||||
|
||||
if error:
|
||||
return _('An error occur during the authentication process.')
|
||||
_logger.warning("Google Gmail: an error occurred %s", error)
|
||||
return request.render('google_gmail.google_gmail_oauth_error', {
|
||||
'error': _('An error occurred during the authentication process.'),
|
||||
'redirect_url': '/odoo',
|
||||
})
|
||||
|
||||
try:
|
||||
state = json.loads(state)
|
||||
|
|
@ -40,36 +41,99 @@ class GoogleGmailController(http.Controller):
|
|||
_logger.error('Google Gmail: Wrong state value %r.', state)
|
||||
raise Forbidden()
|
||||
|
||||
record_sudo = self._get_gmail_record(model_name, rec_id, csrf_token)
|
||||
|
||||
try:
|
||||
refresh_token, access_token, expiration = record_sudo._fetch_gmail_refresh_token(code)
|
||||
except UserError as e:
|
||||
return request.render('google_gmail.google_gmail_oauth_error', {
|
||||
'error': str(e),
|
||||
'redirect_url': self._get_redirect_url(record_sudo),
|
||||
})
|
||||
|
||||
return self._check_email_and_redirect_to_gmail_record(access_token, expiration, refresh_token, record_sudo)
|
||||
|
||||
@http.route('/google_gmail/iap_confirm', type='http', auth='user')
|
||||
def google_gmail_iap_callback(self, model, rec_id, csrf_token, access_token, refresh_token, expiration):
|
||||
"""Receive back the refresh token and access token from IAP.
|
||||
|
||||
The authentication process with IAP is done in 4 steps;
|
||||
1. User database make a request to `<IAP>/api/mail_oauth/1/gmail`
|
||||
2. User browser is redirected to the URL we received from IAP
|
||||
3. User browser is redirected to `<IAP>/api/mail_oauth/1/gmail_callback`
|
||||
with the authorization_code
|
||||
4. User browser is redirected to `<DB>/google_gmail/iap_confirm`
|
||||
"""
|
||||
record = self._get_gmail_record(model, rec_id, csrf_token)
|
||||
return self._check_email_and_redirect_to_gmail_record(access_token, expiration, refresh_token, record)
|
||||
|
||||
def _get_gmail_record(self, model_name, rec_id, csrf_token):
|
||||
"""Return the record after checking the CSRF token."""
|
||||
model = request.env[model_name]
|
||||
|
||||
if not isinstance(model, request.env.registry['google.gmail.mixin']):
|
||||
# The model must inherits from the "google.gmail.mixin" mixin
|
||||
_logger.error('Google Gmail: Wrong model %r.', model_name)
|
||||
raise Forbidden()
|
||||
|
||||
record = model.browse(rec_id).exists()
|
||||
record = model.browse(int(rec_id)).exists().sudo()
|
||||
if not record:
|
||||
_logger.error('Google Gmail: No record found.')
|
||||
raise Forbidden()
|
||||
|
||||
if not csrf_token or not consteq(csrf_token, record._get_gmail_csrf_token()):
|
||||
_logger.error('Google Gmail: Wrong CSRF token during Gmail authentication.')
|
||||
raise Forbidden()
|
||||
|
||||
try:
|
||||
refresh_token, access_token, expiration = record._fetch_gmail_refresh_token(code)
|
||||
except UserError:
|
||||
return _('An error occur during the authentication process.')
|
||||
return record
|
||||
|
||||
def _check_email_and_redirect_to_gmail_record(self, access_token, expiration, refresh_token, record):
|
||||
# Verify the token information (that the email set on the
|
||||
# server is the email used to login on Gmail)
|
||||
if (record._name == 'ir.mail_server' and (record.owner_user_id or not request.env.user.has_group('base.group_system'))):
|
||||
# https://developers.google.com/identity/protocols/oauth2/scopes
|
||||
response = requests.get(
|
||||
'https://www.googleapis.com/oauth2/v2/userinfo',
|
||||
params={'access_token': access_token},
|
||||
timeout=GMAIL_TOKEN_REQUEST_TIMEOUT,
|
||||
)
|
||||
if not response.ok:
|
||||
_logger.error('Google Gmail: Could not verify the token information: %s.', response.text)
|
||||
raise Forbidden()
|
||||
|
||||
response = response.json()
|
||||
|
||||
if not response.get('verified_email') or email_normalize(response.get('email')) != email_normalize(record[record._email_field]):
|
||||
_logger.error('Google Gmail: Invalid email address: %r != %s.', response, record[record._email_field])
|
||||
return request.render('google_gmail.google_gmail_oauth_error', {
|
||||
'error': _(
|
||||
"Oops, you're creating an authorization to send from %(email_login)s but your address is %(email_server)s. Make sure your addresses match!",
|
||||
email_login=response.get('email'),
|
||||
email_server=record[record._email_field],
|
||||
),
|
||||
'redirect_url': self._get_redirect_url(record),
|
||||
})
|
||||
|
||||
record.write({
|
||||
'active': True,
|
||||
'google_gmail_access_token': access_token,
|
||||
'google_gmail_access_token_expiration': expiration,
|
||||
'google_gmail_authorization_code': code,
|
||||
'google_gmail_refresh_token': refresh_token,
|
||||
})
|
||||
return request.redirect(self._get_redirect_url(record))
|
||||
|
||||
url_params = {
|
||||
'id': rec_id,
|
||||
'model': model_name,
|
||||
'view_type': 'form'
|
||||
}
|
||||
url = '/web?#' + url_encode(url_params)
|
||||
return request.redirect(url)
|
||||
def _get_redirect_url(self, record):
|
||||
"""Return the redirect URL for the given record.
|
||||
|
||||
If the user configured a personal mail server, we redirect him
|
||||
to the user preference view. If it's an admin and that he
|
||||
configured a standard incoming / outgoing mail server, then we
|
||||
redirect it to the mail server form view.
|
||||
"""
|
||||
if (
|
||||
(record._name != 'ir.mail_server'
|
||||
or record != request.env.user.outgoing_mail_server_id)
|
||||
and request.env.user.has_group('base.group_system')
|
||||
):
|
||||
return f'/odoo/{record._name}/{record.id}'
|
||||
return f'/odoo/my-preferences/{request.env.user.id}'
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue