diff --git a/auth_oidc_portal/README.rst b/auth_oidc_portal/README.rst new file mode 100644 index 0000000000..a8aba25d77 --- /dev/null +++ b/auth_oidc_portal/README.rst @@ -0,0 +1,35 @@ +**This file is going to be generated by oca-gen-addon-readme.** + +*Manual changes will be overwritten.* + +Please provide content in the ``readme`` directory: + +* **DESCRIPTION.rst** (required) +* INSTALL.rst (optional) +* CONFIGURE.rst (optional) +* **USAGE.rst** (optional, highly recommended) +* DEVELOP.rst (optional) +* ROADMAP.rst (optional) +* HISTORY.rst (optional, recommended) +* **CONTRIBUTORS.rst** (optional, highly recommended) +* CREDITS.rst (optional) + +Content of this README will also be drawn from the addon manifest, +from keys such as name, authors, maintainers, development_status, +and license. + +A good, one sentence summary in the manifest is also highly recommended. + + +Automatic changelog generation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +`HISTORY.rst` can be auto generated using `towncrier `_. + +Just put towncrier compatible changelog fragments into `readme/newsfragments` +and the changelog file will be automatically generated and updated when a new fragment is added. + +Please refer to `towncrier` documentation to know more. + +NOTE: the changelog will be automatically generated when using `/ocabot merge $option`. +If you need to run it manually, refer to `OCA/maintainer-tools README `_. \ No newline at end of file diff --git a/auth_oidc_portal/__init__.py b/auth_oidc_portal/__init__.py new file mode 100644 index 0000000000..14cd1b0579 --- /dev/null +++ b/auth_oidc_portal/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import wizard diff --git a/auth_oidc_portal/__manifest__.py b/auth_oidc_portal/__manifest__.py new file mode 100644 index 0000000000..e52735f0a9 --- /dev/null +++ b/auth_oidc_portal/__manifest__.py @@ -0,0 +1,19 @@ +# Copyright 2023 glueckkanja AG (https://www.glueckkanja.com) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{ + "name": "Authentication OpenID Connect on Portal", + "summary": "Allow portal users to login through OpenID Connect Provider", + "version": "16.0.1.0.0", + "author": ("CRogos (glueckkanja AG), Odoo Community Association (OCA)"), + "license": "AGPL-3", + "maintainers": ["CRogos"], + "category": "hr", + "website": "https://github.com/OCA/server-auth", + "depends": ["auth_oauth", "portal"], + "data": [ + "wizard/portal_wizard_views.xml", + ], + "auto_install": False, + "installable": True, +} diff --git a/auth_oidc_portal/readme/DESCRIPTION.rst b/auth_oidc_portal/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..bc983123ff --- /dev/null +++ b/auth_oidc_portal/readme/DESCRIPTION.rst @@ -0,0 +1,3 @@ +Select a OAuth provider for a portal user. The email address is also used as oauth_id and the first active OAuth provider is selected as default when creating a new portal user. + +.. image:: ..static/description/oauth-portal-user.png diff --git a/auth_oidc_portal/static/description/oauth-portal-user.png b/auth_oidc_portal/static/description/oauth-portal-user.png new file mode 100644 index 0000000000..c78b275c36 Binary files /dev/null and b/auth_oidc_portal/static/description/oauth-portal-user.png differ diff --git a/auth_oidc_portal/tests/__init__.py b/auth_oidc_portal/tests/__init__.py new file mode 100644 index 0000000000..c121601f09 --- /dev/null +++ b/auth_oidc_portal/tests/__init__.py @@ -0,0 +1 @@ +from . import test_portal_wizard diff --git a/auth_oidc_portal/tests/test_portal_wizard.py b/auth_oidc_portal/tests/test_portal_wizard.py new file mode 100644 index 0000000000..e407199485 --- /dev/null +++ b/auth_oidc_portal/tests/test_portal_wizard.py @@ -0,0 +1,39 @@ +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo.tests.common import TransactionCase, users + + +class TestPortalWizard(TransactionCase): + def setUp(self): + super(TestPortalWizard, self).setUp() + + self.partner = self.env["res.partner"].create( + { + "name": "Testing Partner", + "email": "testing_partner@example.com", + } + ) + + @users("admin") + def test_portal_wizard_partner(self): + portal_wizard = ( + self.env["portal.wizard"] + .with_context(active_ids=[self.partner.id]) + .create({}) + ) + + self.assertEqual(len(portal_wizard.user_ids), 1) + + portal_user = portal_wizard.user_ids + portal_user.email = "first_email@example.com" + + oauth_provider_id = self.env["auth.oauth.provider"].search( + [("enabled", "=", True)], limit=1 + ) + self.assertEqual(oauth_provider_id, portal_user.oauth_provider_id) + + portal_user.action_grant_access() + new_user = portal_user.user_id + + self.assertEqual(new_user.oauth_uid, "first_email@example.com") + self.assertEqual(new_user.oauth_provider_id, oauth_provider_id) diff --git a/auth_oidc_portal/wizard/__init__.py b/auth_oidc_portal/wizard/__init__.py new file mode 100644 index 0000000000..b8900201d3 --- /dev/null +++ b/auth_oidc_portal/wizard/__init__.py @@ -0,0 +1,3 @@ +# See LICENSE file for full copyright and licensing details. + +from . import portal_wizard diff --git a/auth_oidc_portal/wizard/portal_wizard.py b/auth_oidc_portal/wizard/portal_wizard.py new file mode 100644 index 0000000000..5e5540e0ec --- /dev/null +++ b/auth_oidc_portal/wizard/portal_wizard.py @@ -0,0 +1,29 @@ +from odoo import fields, models +from odoo.tools import email_normalize + + +class PortalWizardUser(models.TransientModel): + # A model to configure users in the portal wizard. + + _inherit = "portal.wizard.user" + + def _get_default_provider(self): + return self.env["auth.oauth.provider"].search([("enabled", "=", True)], limit=1) + + oauth_provider_id = fields.Many2one( + "auth.oauth.provider", + string="OAuth Provider", + default=_get_default_provider, + domain=[("enabled", "=", True)], + ) + + def _create_user(self): + # create a new user for wizard_user.partner_id + # :returns record of res.users + + user = super(PortalWizardUser, self)._create_user() + if self.oauth_provider_id: + user.oauth_uid = email_normalize(self.email) + user.oauth_provider_id = self.oauth_provider_id + + return user diff --git a/auth_oidc_portal/wizard/portal_wizard_views.xml b/auth_oidc_portal/wizard/portal_wizard_views.xml new file mode 100644 index 0000000000..4000d49eff --- /dev/null +++ b/auth_oidc_portal/wizard/portal_wizard_views.xml @@ -0,0 +1,14 @@ + + + + + Grant oidc portal access + portal.wizard + + + + + + + + diff --git a/password_security/tests/test_signup.py b/password_security/tests/test_signup.py index b600f4cd12..bd3829852f 100644 --- a/password_security/tests/test_signup.py +++ b/password_security/tests/test_signup.py @@ -60,9 +60,7 @@ def test_02_signup_user_success(self): response = self.signup("jackoneill", "!asdQWE12345_3") # Ensure we were logged in - self.assertEqual( - response.request.path_url, "/web/login_successful?account_created=True" - ) + self.assertNotEqual(response.request.path_url, "/web/signup") self.assertEqual(response.status_code, 200) def test_03_create_user_signup(self): diff --git a/setup/auth_oidc_portal/odoo/addons/auth_oidc_portal b/setup/auth_oidc_portal/odoo/addons/auth_oidc_portal new file mode 120000 index 0000000000..62a7117dc8 --- /dev/null +++ b/setup/auth_oidc_portal/odoo/addons/auth_oidc_portal @@ -0,0 +1 @@ +../../../../auth_oidc_portal \ No newline at end of file diff --git a/setup/auth_oidc_portal/setup.py b/setup/auth_oidc_portal/setup.py new file mode 100644 index 0000000000..28c57bb640 --- /dev/null +++ b/setup/auth_oidc_portal/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)