summaryrefslogtreecommitdiff
path: root/addons/auth_oauth/controllers
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
commit3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch)
treea44932296ef4a9b71d5f010906253d8c53727726 /addons/auth_oauth/controllers
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/auth_oauth/controllers')
-rw-r--r--addons/auth_oauth/controllers/__init__.py4
-rw-r--r--addons/auth_oauth/controllers/main.py195
2 files changed, 199 insertions, 0 deletions
diff --git a/addons/auth_oauth/controllers/__init__.py b/addons/auth_oauth/controllers/__init__.py
new file mode 100644
index 00000000..5d4b25db
--- /dev/null
+++ b/addons/auth_oauth/controllers/__init__.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from . import main
diff --git a/addons/auth_oauth/controllers/main.py b/addons/auth_oauth/controllers/main.py
new file mode 100644
index 00000000..3d1a6b53
--- /dev/null
+++ b/addons/auth_oauth/controllers/main.py
@@ -0,0 +1,195 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+import functools
+import logging
+
+import json
+
+import werkzeug.urls
+import werkzeug.utils
+from werkzeug.exceptions import BadRequest
+
+from odoo import api, http, SUPERUSER_ID, _
+from odoo.exceptions import AccessDenied
+from odoo.http import request
+from odoo import registry as registry_get
+
+from odoo.addons.auth_signup.controllers.main import AuthSignupHome as Home
+from odoo.addons.web.controllers.main import db_monodb, ensure_db, set_cookie_and_redirect, login_and_redirect
+
+
+_logger = logging.getLogger(__name__)
+
+
+#----------------------------------------------------------
+# helpers
+#----------------------------------------------------------
+def fragment_to_query_string(func):
+ @functools.wraps(func)
+ def wrapper(self, *a, **kw):
+ kw.pop('debug', False)
+ if not kw:
+ return """<html><head><script>
+ var l = window.location;
+ var q = l.hash.substring(1);
+ var r = l.pathname + l.search;
+ if(q.length !== 0) {
+ var s = l.search ? (l.search === '?' ? '' : '&') : '?';
+ r = l.pathname + l.search + s + q;
+ }
+ if (r == l.pathname) {
+ r = '/';
+ }
+ window.location = r;
+ </script></head><body></body></html>"""
+ return func(self, *a, **kw)
+ return wrapper
+
+
+#----------------------------------------------------------
+# Controller
+#----------------------------------------------------------
+class OAuthLogin(Home):
+ def list_providers(self):
+ try:
+ providers = request.env['auth.oauth.provider'].sudo().search_read([('enabled', '=', True)])
+ except Exception:
+ providers = []
+ for provider in providers:
+ return_url = request.httprequest.url_root + 'auth_oauth/signin'
+ state = self.get_state(provider)
+ params = dict(
+ response_type='token',
+ client_id=provider['client_id'],
+ redirect_uri=return_url,
+ scope=provider['scope'],
+ state=json.dumps(state),
+ )
+ provider['auth_link'] = "%s?%s" % (provider['auth_endpoint'], werkzeug.urls.url_encode(params))
+ return providers
+
+ def get_state(self, provider):
+ redirect = request.params.get('redirect') or 'web'
+ if not redirect.startswith(('//', 'http://', 'https://')):
+ redirect = '%s%s' % (request.httprequest.url_root, redirect[1:] if redirect[0] == '/' else redirect)
+ state = dict(
+ d=request.session.db,
+ p=provider['id'],
+ r=werkzeug.urls.url_quote_plus(redirect),
+ )
+ token = request.params.get('token')
+ if token:
+ state['t'] = token
+ return state
+
+ @http.route()
+ def web_login(self, *args, **kw):
+ ensure_db()
+ if request.httprequest.method == 'GET' and request.session.uid and request.params.get('redirect'):
+ # Redirect if already logged in and redirect param is present
+ return http.redirect_with_hash(request.params.get('redirect'))
+ providers = self.list_providers()
+
+ response = super(OAuthLogin, self).web_login(*args, **kw)
+ if response.is_qweb:
+ error = request.params.get('oauth_error')
+ if error == '1':
+ error = _("Sign up is not allowed on this database.")
+ elif error == '2':
+ error = _("Access Denied")
+ elif error == '3':
+ error = _("You do not have access to this database or your invitation has expired. Please ask for an invitation and be sure to follow the link in your invitation email.")
+ else:
+ error = None
+
+ response.qcontext['providers'] = providers
+ if error:
+ response.qcontext['error'] = error
+
+ return response
+
+ def get_auth_signup_qcontext(self):
+ result = super(OAuthLogin, self).get_auth_signup_qcontext()
+ result["providers"] = self.list_providers()
+ return result
+
+
+class OAuthController(http.Controller):
+
+ @http.route('/auth_oauth/signin', type='http', auth='none')
+ @fragment_to_query_string
+ def signin(self, **kw):
+ state = json.loads(kw['state'])
+ dbname = state['d']
+ if not http.db_filter([dbname]):
+ return BadRequest()
+ provider = state['p']
+ context = state.get('c', {})
+ registry = registry_get(dbname)
+ with registry.cursor() as cr:
+ try:
+ env = api.Environment(cr, SUPERUSER_ID, context)
+ credentials = env['res.users'].sudo().auth_oauth(provider, kw)
+ cr.commit()
+ action = state.get('a')
+ menu = state.get('m')
+ redirect = werkzeug.urls.url_unquote_plus(state['r']) if state.get('r') else False
+ url = '/web'
+ if redirect:
+ url = redirect
+ elif action:
+ url = '/web#action=%s' % action
+ elif menu:
+ url = '/web#menu_id=%s' % menu
+ resp = login_and_redirect(*credentials, redirect_url=url)
+ # Since /web is hardcoded, verify user has right to land on it
+ if werkzeug.urls.url_parse(resp.location).path == '/web' and not request.env.user.has_group('base.group_user'):
+ resp.location = '/'
+ return resp
+ except AttributeError:
+ # auth_signup is not installed
+ _logger.error("auth_signup not installed on database %s: oauth sign up cancelled." % (dbname,))
+ url = "/web/login?oauth_error=1"
+ except AccessDenied:
+ # oauth credentials not valid, user could be on a temporary session
+ _logger.info('OAuth2: access denied, redirect to main page in case a valid session exists, without setting cookies')
+ url = "/web/login?oauth_error=3"
+ redirect = werkzeug.utils.redirect(url, 303)
+ redirect.autocorrect_location_header = False
+ return redirect
+ except Exception as e:
+ # signup error
+ _logger.exception("OAuth2: %s" % str(e))
+ url = "/web/login?oauth_error=2"
+
+ return set_cookie_and_redirect(url)
+
+ @http.route('/auth_oauth/oea', type='http', auth='none')
+ def oea(self, **kw):
+ """login user via Odoo Account provider"""
+ dbname = kw.pop('db', None)
+ if not dbname:
+ dbname = db_monodb()
+ if not dbname:
+ return BadRequest()
+ if not http.db_filter([dbname]):
+ return BadRequest()
+
+ registry = registry_get(dbname)
+ with registry.cursor() as cr:
+ try:
+ env = api.Environment(cr, SUPERUSER_ID, {})
+ provider = env.ref('auth_oauth.provider_openerp')
+ except ValueError:
+ return set_cookie_and_redirect('/web?db=%s' % dbname)
+ assert provider._name == 'auth.oauth.provider'
+
+ state = {
+ 'd': dbname,
+ 'p': provider.id,
+ 'c': {'no_user_creation': True},
+ }
+
+ kw['state'] = json.dumps(state)
+ return self.signin(**kw)