diff --git a/github_login_odoo/README.rst b/github_login_odoo/README.rst new file mode 100644 index 000000000..ccae67cf7 --- /dev/null +++ b/github_login_odoo/README.rst @@ -0,0 +1,54 @@ +.. image:: https://img.shields.io/badge/license-AGPL--3-blue.svg + :target: https://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +Odoo Login Through Github +======================== +This module will enable login to odoo through Github. + +Features +======== +* Login to odoo through git hub. +* Login process made easy in a single button click. + +Configuration +============= +In GitHub, navigate to Settings > Developer settings and create a new OAuth app. +Copy the Client ID and Client Secret, then paste them into the corresponding +fields in Odoo under General Settings > Users & Companies > OAuth Providers. + +License +------- +General Public License, Version 3 (AGPL v3). +(https://www.gnu.org/licenses/agpl-3.0-standalone.html) + +Company +------- +* `Cybrosys Techno Solutions `__ + +Credits +------- +* Developers (V17) Athira K, + Contact: odoo@cybrosys.com + +Contacts +-------- +* Mail Contact : odoo@cybrosys.com +* Website : https://cybrosys.com + +Bug Tracker +----------- +Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. + +Maintainer +========== +.. image:: https://cybrosys.com/images/logo.png + :target: https://cybrosys.com + +This module is maintained by Cybrosys Technologies. + +For support and more information, please visit `Our Website `__ + +Further information +=================== +HTML Description: ``__ diff --git a/github_login_odoo/__init__.py b/github_login_odoo/__init__.py new file mode 100644 index 000000000..a6613575e --- /dev/null +++ b/github_login_odoo/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2025-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################### +from . import controllers +from . import models diff --git a/github_login_odoo/__manifest__.py b/github_login_odoo/__manifest__.py new file mode 100644 index 000000000..7c609acd5 --- /dev/null +++ b/github_login_odoo/__manifest__.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2025-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################### +{ + 'name': "Odoo Login Through Github", + 'version': '17.0.1.0.0', + 'category': 'Extra Tools', + 'summary': """Login odoo with Github""", + 'description': """This module allows user to login using their github credentials in a single button click.""", + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'maintainer': 'Cybrosys Techno Solutions', + 'website': "https://www.cybrosys.com", + 'depends': ['auth_oauth','sale'], + 'data': [ + 'data/github_oauth_data.xml', + 'views/auth_oauth_provider_views.xml', + ], + 'license': 'LGPL-3', + 'installable': True, + 'auto_install': False, + 'images': ['static/description/banner.jpg'], + 'application': True, +} + diff --git a/github_login_odoo/controllers/__init__.py b/github_login_odoo/controllers/__init__.py new file mode 100644 index 000000000..0e0976527 --- /dev/null +++ b/github_login_odoo/controllers/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2025-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################### +from . import github_login_odoo diff --git a/github_login_odoo/controllers/github_login_odoo.py b/github_login_odoo/controllers/github_login_odoo.py new file mode 100644 index 000000000..499c2af07 --- /dev/null +++ b/github_login_odoo/controllers/github_login_odoo.py @@ -0,0 +1,288 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2025-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################### +import json +import logging +import werkzeug +from odoo import _, api, http, SUPERUSER_ID +from odoo.exceptions import AccessDenied +from odoo.http import request +from odoo.addons.auth_oauth.controllers.main import (fragment_to_query_string, + OAuthController, OAuthLogin) +from odoo.addons.auth_signup.controllers.main import AuthSignupHome as Home +from odoo.addons.web.controllers.utils import _get_login_redirect_url, ensure_db +from werkzeug.exceptions import BadRequest +from odoo import registry as registry_get + + +_logger = logging.getLogger(__name__) + + +class AuthLoginHome(Home): + """HTTP controller to login via github""" + + @http.route() + def web_login(self, *args, **kw): + """ + Override the web login method to handle OAuth errors and display + available OAuth providers. + + """ + ensure_db() + + # Handle redirection if the request method is GET, user is + # authenticated, and redirect URL is provided + if request.httprequest.method == 'GET' and request.session.uid: + redirect_url = request.params.get('redirect') + if redirect_url: + return request.redirect(redirect_url) + + # List OAuth providers + providers = self.list_providers() + + # Call parent class login method + response = super(OAuthLogin, self).web_login(*args, **kw) + + # Process response if it is a QWeb template + if response.is_qweb: + # Define error messages in a dictionary + error_messages = { + '1': _("You are not allowed to signup on this database."), + '2': _("Access Denied"), + '3': _( + "Email Already Exists.\nPlease contact your " + "Administrator."), + '4': _( + "Validation Endpoint either Not present or invalid.\nPlease" + "contact your Administrator."), + '5': _( + "Github OAuth API Failed, For more information please " + "contact Administrator."), + '6': _( + "Github OAuth API Failed,\nClient ID or Client Secret Not" + " present or has been compromised.\n" + "For more information please contact Administrator.") + } + + # Get the error message if an OAuth error code is present + error_code = request.params.get('oauth_error') + error_message = error_messages.get(error_code) + + # Add providers and error message to the response context + response.qcontext.update({ + 'providers': providers, + 'error': error_message + }) + return response + + +class GitHubOAuthController(OAuthController): + """Controller to sign in to home page""" + + @http.route('/auth_oauth/signin', type='http', auth='none') + @fragment_to_query_string + def signin(self, **kw): + """ + Handle OAuth sign-in redirection and user authentication. + + This route is responsible for processing the OAuth sign-in callback + and initiating the user authentication + process. + It retrieves the database name, OAuth provider, and other context + information from the state parameter. + The user authentication is performed using the OAuth credentials + provided in the request. + After successful authentication, the user is redirected to the + appropriate page based on the state + parameters. + + """ + # Extract and validate state parameters + state_json = kw.get('state', '{}') + try: + state = json.loads(state_json) + except json.JSONDecodeError: + _logger.error("Invalid state parameter: %s", state_json) + return BadRequest() + + dbname = state.get('d') + if not dbname or not http.db_filter([dbname]): + return BadRequest() + + provider = state.get('p') + context = state.get('c', {}) + action = state.get('a') + menu = state.get('m') + redirect_url = state.get('r') + + # Get registry and authenticate + registry = registry_get(dbname) + try: + with registry.cursor() as cr: + context.update({'provider': provider, 'github': True}) + env = api.Environment(cr, SUPERUSER_ID, context) + db, login, key = env['res.users'].sudo().auth_oauth(provider, + kw) + cr.commit() + # Determine the redirection URL + if redirect_url: + url = werkzeug.urls.url_unquote_plus(redirect_url) + else: + url = '/web' + if action: + url = f'/web#action={action}' + elif menu: + url = f'/web#menu_id={menu}' + + # Authenticate session and handle redirection + pre_uid = request.session.authenticate(db, login, key) + resp_url = _get_login_redirect_url(pre_uid, url) + resp = request.redirect(resp_url, 303) + # Adjust location header if necessary + if werkzeug.urls.url_parse(resp.location).path == '/web': + resp.location = '/' + return resp + except AttributeError: + _logger.error( + "auth_signup not installed on database %s: oauth sign up " + "cancelled.", + dbname) + return request.redirect("/web/login?oauth_error=1", 303) + + except AccessDenied: + _logger.info( + 'OAuth2: access denied, redirecting to main page if a valid ' + 'session exists.') + return request.redirect("/web/login?oauth_error=3", 303) + + except Exception as e: + _logger.exception("OAuth2 error: %s", str(e)) + return request.redirect("/web/login?oauth_error=2", 303) + + +class OAuthLogin(OAuthLogin): + """Controller to login""" + def list_providers(self): + """ + Retrieve a list of enabled OAuth providers. + + This method queries the database for OAuth providers that are + enabled. + For each provider, it generates an authentication link based on + the provider's details. + The authentication link is used to initiate the OAuth authentication + process. + + """ + try: + providers = (request.env['auth.oauth.provider'].sudo(). + search_read([('enabled', '=', True)])) + except Exception: + providers = [] + for provider in providers: + state = self.get_state(provider) + if provider.get('name') in ['GitHub', 'github']: + params = dict( + client_id=provider['client_id'], + scope=provider['scope'], + state=json.dumps(state), + ) + provider['auth_link'] = ("%s?%s" + % (provider['auth_endpoint'], + werkzeug.urls.url_encode(params))) + else: + return_url = request.httprequest.url_root + 'auth_oauth/signin' + 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 + + +class CallbackHandler(http.Controller): + """Controller for call back URL""" + + @http.route(['/oauth/callback'], auth='public', csrf=False, + methods=['GET', 'POST'], type='http') + def get_oauth_token(self, **post): + """ + Handle OAuth callback to retrieve access token. + + This route handles the OAuth callback after a user has authenticated + with an OAuth provider. + It extracts the state and provider information from the request + parameters to identify the OAuth provider. + Based on the provider, it retrieves the client ID and client secret + to exchange the authorization code for + an access token. + The access token is then appended to the redirect URL and the user + is redirected to the sign-in page with + the token. + """ + # Determine OAuth provider + state = post.get('state') + if state: + try: + provider_id = json.loads(state).get('p') + provider = request.env['auth.oauth.provider'].sudo().browse( + provider_id) + except (json.JSONDecodeError, ValueError): + _logger.error('Invalid state parameter: %s', state) + return werkzeug.utils.redirect("/web/login?oauth_error=4", 303) + else: + provider = request.env.ref( + 'github_oauth_app.auth_oauth_provider_github').sudo() + + # Prepare redirect URL + base_redirect_url = request.httprequest.url_root + "auth_oauth/signin" + + # Handle OAuth code and redirection + if post.get("code"): + client_id = provider.client_id + client_secret = provider.client_secret + + if not client_id or not client_secret: + _logger.info( + 'OAuth2: Missing Client ID or Client Secret. Redirecting to ' + 'login page.') + return werkzeug.utils.redirect("/web/login?oauth_error=6", 303) + + # Build redirect URL with query parameters + query_params = { + 'access_token': post.get("code"), + 'state': state, + 'provider': provider.id + } + redirect_url = (f"{base_redirect_url}?" + f"{werkzeug.urls.url_encode(query_params)}") + + return werkzeug.utils.redirect(redirect_url) + + # Handle missing code in post data + _logger.warning( + "OAuth2: Code not present in post data. Redirecting to login page.") + return werkzeug.utils.redirect("/web/login?oauth_error=4", 303) diff --git a/github_login_odoo/data/github_oauth_data.xml b/github_login_odoo/data/github_oauth_data.xml new file mode 100644 index 000000000..adb9485b3 --- /dev/null +++ b/github_login_odoo/data/github_oauth_data.xml @@ -0,0 +1,13 @@ + + + + + GitHub + https://github.com/login/oauth/authorize + user:email + True + https://github.com/login/oauth/access_token + fa fa-fw fa-github + Log in with GitHub + + diff --git a/github_login_odoo/doc/RELEASE_NOTES.md b/github_login_odoo/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..d50cbefc5 --- /dev/null +++ b/github_login_odoo/doc/RELEASE_NOTES.md @@ -0,0 +1,6 @@ +## Module + +#### 11.06.2025 +#### Version 17.0.1.0.0 +##### ADD +- Initial commit for Odoo Login Through Github diff --git a/github_login_odoo/models/__init__.py b/github_login_odoo/models/__init__.py new file mode 100644 index 000000000..51f5fc677 --- /dev/null +++ b/github_login_odoo/models/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################### +from . import auth_oauth_provider +from . import res_users diff --git a/github_login_odoo/models/auth_oauth_provider.py b/github_login_odoo/models/auth_oauth_provider.py new file mode 100644 index 000000000..428fb0e43 --- /dev/null +++ b/github_login_odoo/models/auth_oauth_provider.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################### +import logging +from odoo import fields, models + +_logger = logging.getLogger(__name__) + + +class AuthOAuthProvider(models.Model): + """Inherits auth.oauth.provider to add fields""" + _inherit = "auth.oauth.provider" + + client_secret = fields.Char(string="Client Secret",help="Client Secret Key") + is_github = fields.Boolean(compute='_compute_is_github') + + def _compute_is_github(self): + """ + Compute the value for is_github field based on the auth_endpoint + value. + + This method iterates over the records to compute the value for the + `is_github` field. + It checks if each record's authentication endpoint contains 'github'. + If the authentication endpoint contains 'github', it sets the + `is_github` field to True. + Otherwise, it sets the `is_github` field to False. + + """ + for rec in self: + if rec.auth_endpoint: + if 'github' in rec.auth_endpoint: + rec.is_github = True + else: + rec.is_github = False + else: + rec.is_github = False diff --git a/github_login_odoo/models/res_users.py b/github_login_odoo/models/res_users.py new file mode 100644 index 000000000..812fe3382 --- /dev/null +++ b/github_login_odoo/models/res_users.py @@ -0,0 +1,216 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################### +import logging +import requests +import werkzeug +from odoo import _, api, fields, models +from odoo.addons.auth_signup.models.res_partner import SignupError +from odoo.exceptions import AccessDenied +from odoo.tools.misc import ustr + +_logger = logging.getLogger(__name__) + + +class ResUsers(models.Model): + """Inherit res.users model to add fields""" + _inherit = 'res.users' + + oauth_token = fields.Char(readonly=True) + git_username = fields.Char(default="No username",help="Username") + git_email = fields.Char(string="Github Email",help="Email") + + def _auth_oauth_rpc(self, endpoint, access_token): + """ + Perform an OAuth RPC call to the specified endpoint with the + provided access token. + + This method performs an OAuth RPC call to the given endpoint using + the provided access token. + If the context indicates GitHub authentication, it specifically + handles GitHub OAuth calls to retrieve user + data. + For other OAuth providers, it uses the standard OAuth authorization + header or access token for the request. + It handles the response and returns the user data or error + information. + """ + if self.env.context.get('github'): + provider = (self.env['auth.oauth.provider']. + browse(self.env.context.get('provider'))) + params = { + 'client_id': provider.client_id, + 'client_secret': provider.client_secret, + 'code': access_token, + 'scope': 'user:email' # Add this line to request email access + } + response = requests.get(endpoint, params=params, timeout=10) + if response.ok: + response_data = response.content.decode("UTF-8").split('&') + if 'error=' in response_data or 'error=' in response_data[0]: + r_url = "/web/login?oauth_error=5" + _logger.info( + 'OAuth2: access denied, redirect to main page in case a ' + 'valid session exists, without setting cookies.' + ' REASON :- %s' % str( + response_data[0])) + redirect = werkzeug.utils.redirect(r_url, 303) + redirect.autocorrect_location_header = False + return redirect + auth_token = response_data[0].split('=')[1] + user_data_response = requests.get('https://api.github.com/' + 'user/emails', auth=('', auth_token)).json() + email = [email_data['email'] for email_data in + user_data_response if email_data['primary']][0] + user_data = requests.get('https://api.github.com/user', + auth=('', auth_token)).json() + params = { + 'key': auth_token, + 'user_id': user_data.get('id'), + 'username': user_data.get('login'), + 'name': user_data.get('name'), + 'email': email + } + return params + else: + if (self.env['ir.config_parameter'].sudo(). + get_param('auth_oauth.authorization_header')): + response = requests.get(endpoint, + headers={'Authorization': 'Bearer %s' + % access_token}, timeout=10) + else: + response = requests.get(endpoint, + params={'access_token': access_token}, + timeout=10) + if response.ok: # nb: could be a successful failure + return response.json() + auth_challenge = werkzeug.http.parse_www_authenticate_header( + response.headers.get('WWW-Authenticate')) + if auth_challenge.type == 'bearer' and 'error' in auth_challenge: + return dict(auth_challenge) + return {'error': 'invalid_request'} + + @api.model + def _auth_oauth_validate(self, provider, access_token): + """ + Validate the OAuth access token with the specified provider and + retrieve user data. + + This method validates the provided OAuth access token with the + given provider's validation endpoint. + If validation is successful, it retrieves additional user data from + the provider's data endpoint. + It then processes the validation response to extract the user's + subject identity and returns the validation + data. + """ + oauth_provider = self.env['auth.oauth.provider'].browse(provider) + validation = self._auth_oauth_rpc(oauth_provider.validation_endpoint, + access_token) + if validation.get("error"): + raise Exception(validation['error']) + if oauth_provider.data_endpoint: + data = self._auth_oauth_rpc(oauth_provider.data_endpoint, + access_token) + validation.update(data) + if self.env.context.get('github'): + return validation + subject = next(filter(None, [ + validation.pop(key, None) + for key in [ + 'sub', + 'id', + 'user_id', + ] + ]), None) + if not subject: + raise AccessDenied('Missing subject identity') + validation['user_id'] = subject + + return validation + + def github_api_hit(self): + """ + Trigger GitHub OAuth authorization by redirecting to GitHub's + authorization URL. + + This method retrieves the GitHub OAuth provider configuration and + constructs the authorization URL. + It checks if the client ID is available and redirects the user to + GitHub's authorization page. + The authorization URL includes the required client ID and scopes + (repo and user) for the OAuth request. + """ + provider = self.env.ref('github_oauth_app.auth_oauth_provider_github') + provider = self.env[provider._name].sudo().browse(provider.id) + if provider: + if not provider.client_id: + r_url = "/web/login?oauth_error=6" + _logger.info( + 'OAuth2: Either of Client ID or Client Secret not present, ' + 'access denied, redirect to main page in case a valid ' + 'session exists, without setting cookies') + redirect = werkzeug.utils.redirect(r_url, 303) + redirect.autocorrect_location_header = False + return redirect + url = ("https://github.com/login/oauth/authorize?client_id=%s&" + "scope=repo,user") % provider.client_id + response = requests.get(url) + if response.status_code in [200, 201]: + return response.url + + @api.model + def _signup_create_user(self, values): + """ + Create a new user during signup using the default method. + + This method calls the default user creation method during signup. + It simply delegates the user creation process to the parent class + method. + """ + return super(ResUsers, self)._signup_create_user(values) + + def _create_user_from_default_template(self, values): + """ + Create a new user based on the default user template. + + This method creates a new user by copying the default user template. + It validates the provided values and ensures that essential fields + like login, name, and partner are + provided. + If the template user does not exist or the required values are + missing, it raises appropriate exceptions. + """ + template_user = self.env.ref('base.default_user') + if not template_user.exists(): + raise ValueError(_('Signup: invalid template user')) + if not values.get('login'): + raise ValueError(_('Signup: no login given for new user')) + if not values.get('partner_id') and not values.get('name'): + raise ValueError(_('Signup: no name or partner given for new user')) + values['active'] = True + try: + with ((self.env.cr.savepoint())): + return template_user.with_context(no_reset_password=True + ).copy(values) + except Exception as e: + # copy may fail if asked login is not available. + raise SignupError(ustr(e)) diff --git a/github_login_odoo/static/description/assets/hero-v17.gif b/github_login_odoo/static/description/assets/hero-v17.gif new file mode 100644 index 000000000..1306177a6 Binary files /dev/null and b/github_login_odoo/static/description/assets/hero-v17.gif differ diff --git a/github_login_odoo/static/description/assets/icons/capture (1).png b/github_login_odoo/static/description/assets/icons/capture (1).png new file mode 100644 index 000000000..8824deafc Binary files /dev/null and b/github_login_odoo/static/description/assets/icons/capture (1).png differ diff --git a/github_login_odoo/static/description/assets/icons/check.png b/github_login_odoo/static/description/assets/icons/check.png new file mode 100644 index 000000000..c8e85f51d Binary files /dev/null and b/github_login_odoo/static/description/assets/icons/check.png differ diff --git a/github_login_odoo/static/description/assets/icons/chevron.png b/github_login_odoo/static/description/assets/icons/chevron.png new file mode 100644 index 000000000..2089293d6 Binary files /dev/null and b/github_login_odoo/static/description/assets/icons/chevron.png differ diff --git a/github_login_odoo/static/description/assets/icons/cogs.png b/github_login_odoo/static/description/assets/icons/cogs.png new file mode 100644 index 000000000..95d0bad62 Binary files /dev/null and b/github_login_odoo/static/description/assets/icons/cogs.png differ diff --git a/github_login_odoo/static/description/assets/icons/consultation.png b/github_login_odoo/static/description/assets/icons/consultation.png new file mode 100644 index 000000000..8319d4baa Binary files /dev/null and b/github_login_odoo/static/description/assets/icons/consultation.png differ diff --git a/github_login_odoo/static/description/assets/icons/ecom-black.png b/github_login_odoo/static/description/assets/icons/ecom-black.png new file mode 100644 index 000000000..a9385ff13 Binary files /dev/null and b/github_login_odoo/static/description/assets/icons/ecom-black.png differ diff --git a/github_login_odoo/static/description/assets/icons/education-black.png b/github_login_odoo/static/description/assets/icons/education-black.png new file mode 100644 index 000000000..3eb09b27b Binary files /dev/null and b/github_login_odoo/static/description/assets/icons/education-black.png differ diff --git a/github_login_odoo/static/description/assets/icons/hotel-black.png b/github_login_odoo/static/description/assets/icons/hotel-black.png new file mode 100644 index 000000000..130f613be Binary files /dev/null and b/github_login_odoo/static/description/assets/icons/hotel-black.png differ diff --git a/github_login_odoo/static/description/assets/icons/img.png b/github_login_odoo/static/description/assets/icons/img.png new file mode 100644 index 000000000..70197f477 Binary files /dev/null and b/github_login_odoo/static/description/assets/icons/img.png differ diff --git a/github_login_odoo/static/description/assets/icons/license.png b/github_login_odoo/static/description/assets/icons/license.png new file mode 100644 index 000000000..a5869797e Binary files /dev/null and b/github_login_odoo/static/description/assets/icons/license.png differ diff --git a/github_login_odoo/static/description/assets/icons/lifebuoy.png b/github_login_odoo/static/description/assets/icons/lifebuoy.png new file mode 100644 index 000000000..658d56ccc Binary files /dev/null and b/github_login_odoo/static/description/assets/icons/lifebuoy.png differ diff --git a/github_login_odoo/static/description/assets/icons/manufacturing-black.png b/github_login_odoo/static/description/assets/icons/manufacturing-black.png new file mode 100644 index 000000000..697eb0e9f Binary files /dev/null and b/github_login_odoo/static/description/assets/icons/manufacturing-black.png differ diff --git a/github_login_odoo/static/description/assets/icons/photo-capture.png b/github_login_odoo/static/description/assets/icons/photo-capture.png new file mode 100644 index 000000000..06c111758 Binary files /dev/null and b/github_login_odoo/static/description/assets/icons/photo-capture.png differ diff --git a/github_login_odoo/static/description/assets/icons/pos-black.png b/github_login_odoo/static/description/assets/icons/pos-black.png new file mode 100644 index 000000000..97c0f90c1 Binary files /dev/null and b/github_login_odoo/static/description/assets/icons/pos-black.png differ diff --git a/github_login_odoo/static/description/assets/icons/puzzle.png b/github_login_odoo/static/description/assets/icons/puzzle.png new file mode 100644 index 000000000..65cf854e7 Binary files /dev/null and b/github_login_odoo/static/description/assets/icons/puzzle.png differ diff --git a/github_login_odoo/static/description/assets/icons/restaurant-black.png b/github_login_odoo/static/description/assets/icons/restaurant-black.png new file mode 100644 index 000000000..4a35eb939 Binary files /dev/null and b/github_login_odoo/static/description/assets/icons/restaurant-black.png differ diff --git a/github_login_odoo/static/description/assets/icons/service-black.png b/github_login_odoo/static/description/assets/icons/service-black.png new file mode 100644 index 000000000..301ab51cb Binary files /dev/null and b/github_login_odoo/static/description/assets/icons/service-black.png differ diff --git a/github_login_odoo/static/description/assets/icons/trading-black.png b/github_login_odoo/static/description/assets/icons/trading-black.png new file mode 100644 index 000000000..9398ba2f1 Binary files /dev/null and b/github_login_odoo/static/description/assets/icons/trading-black.png differ diff --git a/github_login_odoo/static/description/assets/icons/training.png b/github_login_odoo/static/description/assets/icons/training.png new file mode 100644 index 000000000..884ca024d Binary files /dev/null and b/github_login_odoo/static/description/assets/icons/training.png differ diff --git a/github_login_odoo/static/description/assets/icons/update.png b/github_login_odoo/static/description/assets/icons/update.png new file mode 100644 index 000000000..ecbc5a01a Binary files /dev/null and b/github_login_odoo/static/description/assets/icons/update.png differ diff --git a/github_login_odoo/static/description/assets/icons/user.png b/github_login_odoo/static/description/assets/icons/user.png new file mode 100644 index 000000000..6ffb23d9f Binary files /dev/null and b/github_login_odoo/static/description/assets/icons/user.png differ diff --git a/github_login_odoo/static/description/assets/icons/wrench.png b/github_login_odoo/static/description/assets/icons/wrench.png new file mode 100644 index 000000000..6c04dea0f Binary files /dev/null and b/github_login_odoo/static/description/assets/icons/wrench.png differ diff --git a/github_login_odoo/static/description/assets/misc/Cybrosys R.png b/github_login_odoo/static/description/assets/misc/Cybrosys R.png new file mode 100644 index 000000000..da4058087 Binary files /dev/null and b/github_login_odoo/static/description/assets/misc/Cybrosys R.png differ diff --git a/github_login_odoo/static/description/assets/misc/email.svg b/github_login_odoo/static/description/assets/misc/email.svg new file mode 100644 index 000000000..15291cdc3 --- /dev/null +++ b/github_login_odoo/static/description/assets/misc/email.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/github_login_odoo/static/description/assets/misc/phone.svg b/github_login_odoo/static/description/assets/misc/phone.svg new file mode 100644 index 000000000..b7bd7f251 --- /dev/null +++ b/github_login_odoo/static/description/assets/misc/phone.svg @@ -0,0 +1,3 @@ + + + diff --git a/github_login_odoo/static/description/assets/misc/star (1) 2.svg b/github_login_odoo/static/description/assets/misc/star (1) 2.svg new file mode 100644 index 000000000..5ae9f507a --- /dev/null +++ b/github_login_odoo/static/description/assets/misc/star (1) 2.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/github_login_odoo/static/description/assets/misc/support (1) 1.svg b/github_login_odoo/static/description/assets/misc/support (1) 1.svg new file mode 100644 index 000000000..7d37a8f30 --- /dev/null +++ b/github_login_odoo/static/description/assets/misc/support (1) 1.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/github_login_odoo/static/description/assets/misc/support-email.svg b/github_login_odoo/static/description/assets/misc/support-email.svg new file mode 100644 index 000000000..eb70370d6 --- /dev/null +++ b/github_login_odoo/static/description/assets/misc/support-email.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/github_login_odoo/static/description/assets/misc/tick-mark.svg b/github_login_odoo/static/description/assets/misc/tick-mark.svg new file mode 100644 index 000000000..2dbb40187 --- /dev/null +++ b/github_login_odoo/static/description/assets/misc/tick-mark.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/github_login_odoo/static/description/assets/misc/whatsapp 1.svg b/github_login_odoo/static/description/assets/misc/whatsapp 1.svg new file mode 100644 index 000000000..0bfaf8fc6 --- /dev/null +++ b/github_login_odoo/static/description/assets/misc/whatsapp 1.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/github_login_odoo/static/description/assets/misc/whatsapp.svg b/github_login_odoo/static/description/assets/misc/whatsapp.svg new file mode 100644 index 000000000..b618aea1d --- /dev/null +++ b/github_login_odoo/static/description/assets/misc/whatsapp.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/github_login_odoo/static/description/assets/modules/m1.png b/github_login_odoo/static/description/assets/modules/m1.png new file mode 100644 index 000000000..d7ef56df4 Binary files /dev/null and b/github_login_odoo/static/description/assets/modules/m1.png differ diff --git a/github_login_odoo/static/description/assets/modules/m2.jpg b/github_login_odoo/static/description/assets/modules/m2.jpg new file mode 100644 index 000000000..2d4e27a2c Binary files /dev/null and b/github_login_odoo/static/description/assets/modules/m2.jpg differ diff --git a/github_login_odoo/static/description/assets/modules/m2.png b/github_login_odoo/static/description/assets/modules/m2.png new file mode 100644 index 000000000..3ef91f771 Binary files /dev/null and b/github_login_odoo/static/description/assets/modules/m2.png differ diff --git a/github_login_odoo/static/description/assets/modules/m3.png b/github_login_odoo/static/description/assets/modules/m3.png new file mode 100644 index 000000000..72febf6ae Binary files /dev/null and b/github_login_odoo/static/description/assets/modules/m3.png differ diff --git a/github_login_odoo/static/description/assets/modules/m4.png b/github_login_odoo/static/description/assets/modules/m4.png new file mode 100644 index 000000000..f7d7f9241 Binary files /dev/null and b/github_login_odoo/static/description/assets/modules/m4.png differ diff --git a/github_login_odoo/static/description/assets/modules/m5.png b/github_login_odoo/static/description/assets/modules/m5.png new file mode 100644 index 000000000..1d3324e88 Binary files /dev/null and b/github_login_odoo/static/description/assets/modules/m5.png differ diff --git a/github_login_odoo/static/description/assets/modules/m6.png b/github_login_odoo/static/description/assets/modules/m6.png new file mode 100644 index 000000000..80938c15a Binary files /dev/null and b/github_login_odoo/static/description/assets/modules/m6.png differ diff --git a/github_login_odoo/static/description/assets/screen shots/1.png b/github_login_odoo/static/description/assets/screen shots/1.png new file mode 100644 index 000000000..eb8a6e6fa Binary files /dev/null and b/github_login_odoo/static/description/assets/screen shots/1.png differ diff --git a/github_login_odoo/static/description/assets/screen shots/2.png b/github_login_odoo/static/description/assets/screen shots/2.png new file mode 100644 index 000000000..399da72d6 Binary files /dev/null and b/github_login_odoo/static/description/assets/screen shots/2.png differ diff --git a/github_login_odoo/static/description/assets/screen shots/3.png b/github_login_odoo/static/description/assets/screen shots/3.png new file mode 100644 index 000000000..5d2291907 Binary files /dev/null and b/github_login_odoo/static/description/assets/screen shots/3.png differ diff --git a/github_login_odoo/static/description/assets/screen shots/4.png b/github_login_odoo/static/description/assets/screen shots/4.png new file mode 100644 index 000000000..cae2cdab5 Binary files /dev/null and b/github_login_odoo/static/description/assets/screen shots/4.png differ diff --git a/github_login_odoo/static/description/assets/screen shots/5.png b/github_login_odoo/static/description/assets/screen shots/5.png new file mode 100644 index 000000000..fc3adb9f5 Binary files /dev/null and b/github_login_odoo/static/description/assets/screen shots/5.png differ diff --git a/github_login_odoo/static/description/assets/screen shots/credentials.png b/github_login_odoo/static/description/assets/screen shots/credentials.png new file mode 100644 index 000000000..aa7937ab3 Binary files /dev/null and b/github_login_odoo/static/description/assets/screen shots/credentials.png differ diff --git a/github_login_odoo/static/description/assets/screen shots/impp.png b/github_login_odoo/static/description/assets/screen shots/impp.png new file mode 100644 index 000000000..58884cadc Binary files /dev/null and b/github_login_odoo/static/description/assets/screen shots/impp.png differ diff --git a/github_login_odoo/static/description/assets/screen shots/oauth_app.png b/github_login_odoo/static/description/assets/screen shots/oauth_app.png new file mode 100644 index 000000000..015c5b07e Binary files /dev/null and b/github_login_odoo/static/description/assets/screen shots/oauth_app.png differ diff --git a/github_login_odoo/static/description/assets/screen shots/profile.png b/github_login_odoo/static/description/assets/screen shots/profile.png new file mode 100644 index 000000000..1ff13e074 Binary files /dev/null and b/github_login_odoo/static/description/assets/screen shots/profile.png differ diff --git a/github_login_odoo/static/description/banner.jpg b/github_login_odoo/static/description/banner.jpg new file mode 100644 index 000000000..f0534e926 Binary files /dev/null and b/github_login_odoo/static/description/banner.jpg differ diff --git a/github_login_odoo/static/description/hero-v17.gif b/github_login_odoo/static/description/hero-v17.gif new file mode 100644 index 000000000..9d298536b Binary files /dev/null and b/github_login_odoo/static/description/hero-v17.gif differ diff --git a/github_login_odoo/static/description/icon.png b/github_login_odoo/static/description/icon.png new file mode 100644 index 000000000..e44024a39 Binary files /dev/null and b/github_login_odoo/static/description/icon.png differ diff --git a/github_login_odoo/static/description/index.html b/github_login_odoo/static/description/index.html new file mode 100644 index 000000000..062da5a63 --- /dev/null +++ b/github_login_odoo/static/description/index.html @@ -0,0 +1,736 @@ + + + + + + + Odoo App 3 Index + + + + + + + + +
+
+
+
+
+ +
+
+
+ Community +
+
+ Enterprise +
+
+ Odoo.sh +
+
+
+
+
+
+

+ Odoo Login Through Github

+

+ Login to Odoo In a Single Click Using Github Credentials. +

+
+ +
+
+
+
+
+

+ Key Highlights +

+
+
+
+
+
+ +
+
+

+ Available in Odoo 17.0 Community and + Enterprise.

+
+
+
+
+
+
+ +
+
+

+ Login to Odoo in a single click using github credentials.

+
+
+
+
+
+
+ +
+
+
+
+
+ +
+
+

+ Before setting up the OAuth provider, enable 'Free sign up' for guests.

+
+
+
+
+
+
+ +
+
+

+ Login to your Github account, navigate to settings--> Developer settings--> New oauth app. Register a new app, + Provide the URL of your application homepage as 'Homepage URL' and append '/oauth/callback' to the home page URL for 'Authorization callback URL' . Now you can generate secret key. + Client ID will also be available from there.

+
+
+
+
+
+
+ +
+
+

+ Ensure that the 'Name' field is filled in the associated Git account's profile.

+
+
+
+
+
+
+ +
+
+

+ Go to Settings > OAuth Providers.

+
+
+
+
+
+
+ +
+
+

+ Here you can + add the credentials of your github account like + 'Client ID' and 'Client Secret' Key. +

+
+
+
+
+
+
+ +
+
+

+ Now you can click on the 'Log in with GitHub' + button to directly access your account.

+
+
+
+
+
+
+ +
+
+

+ The 'Customer Portal' from where user can + easily manage their data.

+
+
+
+
+
+
+
    +
  • + A new customer account will be + automatically + created in case user is new to the system. +
  • +
  • + Available in + Odoo 17.0 Community and Enterprise +
  • +
+
+
+
+
+
+
Version + 17.0.1.0.0|Released on:16th Dec 2024 +
+

+ Initial Commit for Odoo Login Through Github

+
+
+
+
+
+
+
+

+ Related Products

+
+
+ +
+
+

+ Our Services

+ +
+
+
+
+
+
+
+
+ service-icon +
+
+

Odoo + Customization

+
+
+
+
+
+
+ service-icon +
+
+

Odoo + Implementation

+
+
+
+
+
+
+ service-icon +
+
+

Odoo + Support

+
+
+
+
+
+
+ service-icon +
+
+

Hire + Odoo Developer

+
+
+
+
+ +
+
+ service-icon +
+
+

Odoo + Integration

+
+
+
+
+
+
+ service-icon +
+
+

Odoo + Migration

+
+
+
+
+
+
+ service-icon +
+
+

Odoo + Consultancy

+
+
+
+
+
+
+ service-icon +
+
+

Odoo + Implementation

+
+
+
+
+
+
+ service-icon +
+
+

Odoo + Licensing Consultancy

+
+
+
+
+
+
+

+ Our Industries

+ +
+
+
+
+
+
+ +

Trading

+

Easily procure and sell your products

+
+
+
+
+ +

POS

+

Easy configuration and convivial experience

+
+
+
+
+ +

+ Education

+

A platform for educational management

+
+
+
+
+ +

+ Manufacturing

+

Plan, track and schedule your operations

+
+
+
+
+ +

E-commerce & + Website

+

Mobile friendly, awe-inspiring product pages

+
+
+
+
+ +

Service + Management

+

Keep track of services and invoice

+
+
+
+
+ +

+ Restaurant

+

Run your bar or restaurant methodically

+
+
+
+
+ +

Hotel + Management

+

An all-inclusive hotel management application

+
+
+
+
+
+
+

+ Support

+
+
+
+
+
+
+
+ +
+ Need + Help? +

Got + questions or need help? Get in touch.

+
odoo@cybrosys.com +
+
+
+
+
+
+
+
+ +
+ WhatsApp +

Say hi to + us on WhatsApp!

+
+91 + 99456767686 +
+
+
+
+
+
+
+
+
+ + + + + + diff --git a/github_login_odoo/views/auth_oauth_provider_views.xml b/github_login_odoo/views/auth_oauth_provider_views.xml new file mode 100644 index 000000000..1a36d6577 --- /dev/null +++ b/github_login_odoo/views/auth_oauth_provider_views.xml @@ -0,0 +1,15 @@ + + + + + view.oauth.provider.form + auth.oauth.provider + + + + + + + + +