Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
426 changes: 426 additions & 0 deletions oauth_provider/README.rst

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions oauth_provider/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# -*- coding: utf-8 -*-
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

from . import controllers
from . import models

from .hooks import pre_init_hook, post_load
29 changes: 29 additions & 0 deletions oauth_provider/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
# Copyright 2016 SYLEAM
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

{
'name': 'OAuth Provider',
'summary': 'Allows to use Odoo as an OAuth2 provider',
'version': '10.0.1.0.0',
'category': 'Authentication',
'website': 'http://www.syleam.fr/',
'author': 'SYLEAM, LasLabs, Odoo Community Association (OCA)',
'license': 'LGPL-3',
'installable': True,
'external_dependancies': {
'python': ['oauthlib'],
},
'depends': [
'web',
],
'data': [
'security/oauth_provider_security.xml',
'security/ir.model.access.csv',
'views/oauth_provider_client.xml',
'views/oauth_provider_scope.xml',
'templates/authorization.xml',
],
'pre_init_hook': 'pre_init_hook',
'post_load': 'post_load',
}
8 changes: 8 additions & 0 deletions oauth_provider/controllers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# -*- coding: utf-8 -*-
# Copyright 2016 SYLEAM
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

from . import oauth_mixin

from . import rest_api_controller
from . import oauth_provider_controller
133 changes: 133 additions & 0 deletions oauth_provider/controllers/oauth_mixin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# -*- coding: utf-8 -*-
# Copyright 2016 SYLEAM
# Copyright 2017 LasLabs Inc.
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

import logging

from odoo import http
from odoo.addons.web.controllers.main import ensure_db

from ..exceptions import OauthApiException, OauthInvalidTokenException
from ..http import _json_response


_logger = logging.getLogger(__name__)

try:
import oauthlib
except ImportError:
_logger.debug('Cannot `import oauthlib`.')


class OauthMixin(http.Controller):

def _validate_model(self, model_name, token=None):
""" Validate the access token & return a usable model.

Args:
model_name (str): Name of model to find.
token (OauthProviderToken, optional): Will return the model in
the scope of the token user, if defined.

Returns:
IrModel: Usable model object that matched model_name.

Raises:
OauthApiException: If the model is not found.
"""
ensure_db()
model_obj = http.request.env['ir.model'].search([
('model', '=', model_name),
])
if not model_obj:
raise OauthApiException('Model Not Found')
if token is not None:
model_obj = model_obj.sudo(user=token.user_id)
return model_obj

def _validate_token(self, access_token):
""" Find the access token & return it if valid.

Args:
access_token (str): Access token that should be validated.

Returns:
OAuthProviderToken: Token record, if valid.

Raises:
OauthInvalidTokenException: When the token is invalid or expired.
"""
ensure_db()
token = self._get_access_token(access_token)
if not token:
raise OauthInvalidTokenException()
return token

@classmethod
def _get_access_token(cls, access_token):
""" Verify access token and return record if valid.

Args:
access_token (str): OAuth2 access token to be validated.

Returns:
OauthProviderToken: Valid token record for use.
NoneType: None if no matching token was found in the database.
bool: False if the token was invalid.
"""
token = http.request.env['oauth.provider.token'].search([
('token', '=', access_token),
])
if not token:
return None

oauth2_server = token.client_id.get_oauth2_server()
# Retrieve needed arguments for oauthlib methods
uri, http_method, body, headers = cls._get_request_information()

# Validate request information
valid, oauthlib_request = oauth2_server.verify_request(
uri, http_method=http_method, body=body, headers=headers,
)

if valid:
return token

return False

@staticmethod
def _get_request_information():
""" Retrieve needed arguments for oauthlib methods.

Returns:
tuple: uri, http_method, body, headers
"""
uri = http.request.httprequest.base_url
http_method = http.request.httprequest.method
body = oauthlib.common.urlencode(
http.request.httprequest.values.items(),
)
headers = http.request.httprequest.headers

return uri, http_method, body, headers

@staticmethod
def _json_response(data=None, error=None, headers=None, status=None):
""" Returns a json response to the client.

Args:
result (mixed, optional): User's requested data.
error (dict, optional): Serialized error data (from
`_handle_exception`).
headers (dict, optional): Mapping of headers to apply to the
request. If the `Content-Type` header is not defined,
`application/json` will automatically be added.

Returns:
Response: Werkzeug response object based on the input.
"""
try:
return http.request._json_response(data, error)
except AttributeError:
return _json_response(data, error, headers, status)
Loading