# Copyright 2024 Akretion (http://www.akretion.com). # @author Florian Mounier # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from contextlib import contextmanager from datetime import datetime, timedelta from freezegun import freeze_time from odoo.exceptions import AccessDenied, UserError from .common import CommonTestAuthPartner class TestAuthPartner(CommonTestAuthPartner): @contextmanager def assert_no_new_mail(self): with self.new_mails() as new_mails: yield self.assertFalse(new_mails) def test_default_secret_key(self): self.assertGreaterEqual(len(self.directory.secret_key), 64) def test_login_ok(self): with self.assert_no_new_mail(): auth_partner = self.env["auth.partner"]._login( self.directory, login="partner-auth@example.org", password="Super-secret$1", ) self.assertTrue(auth_partner) def test_login_inactive_partner(self): self.partner.active = False with self.assertRaisesRegex(AccessDenied, "Invalid Login or Password"): self.env["auth.partner"]._login( self.directory, login="partner-auth@example.org", password="Super-secret$1", ) def test_login_no_auth(self): self.auth_partner.unlink() with self.assertRaisesRegex(AccessDenied, "Invalid Login or Password"): self.env["auth.partner"]._login( self.directory, login="partner-auth@example.org", password="Super-secret$1", ) def test_login_wrong_password(self): with self.assertRaisesRegex(AccessDenied, "Invalid Login or Password"): self.env["auth.partner"]._login( self.directory, login="partner-auth@example.org", password="wrong" ) def test_login_mail_not_verified(self): self.directory.force_verified_email = True with self.assertRaisesRegex(AccessDenied, "Email address not validated"): self.env["auth.partner"]._login( self.directory, login="partner-auth@example.org", password="Super-secret$1", ) def test_login_wrong_login(self): with self.assertRaisesRegex(AccessDenied, "Invalid Login or Password"): self.env["auth.partner"]._login( self.directory, login="partner-auth@example.com", password="Super-secret$1", ) def test_login_wrong_directory(self): with self.assertRaisesRegex(AccessDenied, "Invalid Login or Password"): self.env["auth.partner"]._login( self.other_directory, login="partner-auth@example.com", password="Super-secret$1", ) def test_signup(self): with self.new_mails() as new_mails: new_auth_partner = self.env["auth.partner"]._signup( self.directory, name="New Partner", login="new-partner-auth@example.org", password="NewSecret", ) self.assertTrue(new_auth_partner) # Ensure we can't read the password self.assertNotEqual(new_auth_partner.password, "NewSecret") self.assertEqual(len(new_mails), 1) self.assertEqual(new_mails.subject, "Welcome") self.assertIn("Welcome to the site, please", new_mails.body) auth_partner = self.env["auth.partner"]._login( self.directory, login="new-partner-auth@example.org", password="NewSecret" ) self.assertTrue(auth_partner) self.assertEqual(auth_partner, new_auth_partner) def test_signup_wrong_directory(self): new_auth_partner = self.env["auth.partner"]._signup( self.other_directory, name="New Partner", login="new-partner-auth@example.org", password="NewSecret", ) self.assertTrue(new_auth_partner) with self.assertRaisesRegex(AccessDenied, "Invalid Login or Password"): self.env["auth.partner"]._login( self.directory, login="new-partner-auth@example.org", password="NewSecret", ) def test_signup_same_login_other_directory(self): new_auth_partner = self.env["auth.partner"]._signup( self.directory, name="New Partner", login="new-partner-auth@example.org", password="NewSecret", ) self.assertTrue(new_auth_partner) new_auth_partner_2 = self.env["auth.partner"]._signup( self.other_directory, name="New Partner", login="new-partner-auth@example.org", password="NewSecret2", ) self.assertTrue(new_auth_partner_2) self.assertNotEqual(new_auth_partner, new_auth_partner_2) with self.assertRaisesRegex(AccessDenied, "Invalid Login or Password"): self.env["auth.partner"]._login( self.directory, login="new-partner-auth@example.org", password="NewSecret2", ) with self.assertRaisesRegex(AccessDenied, "Invalid Login or Password"): self.env["auth.partner"]._login( self.other_directory, login="new-partner-auth@example.org", password="NewSecret", ) def test_validate_email_ok(self): self.assertFalse(self.auth_partner.mail_verified) token = self.auth_partner._generate_validate_email_token() self.auth_partner._validate_email(self.directory, token) self.assertTrue(self.auth_partner.mail_verified) def test_validate_email_required_login(self): self.directory.force_verified_email = True token = self.auth_partner._generate_validate_email_token() self.auth_partner._validate_email(self.directory, token) with self.assert_no_new_mail(): auth_partner = self.env["auth.partner"]._login( self.directory, login="partner-auth@example.org", password="Super-secret$1", ) self.assertTrue(auth_partner) def test_validate_email_wrong_token(self): self.assertFalse(self.auth_partner.mail_verified) with self.assertRaisesRegex(UserError, "Invalid Token"): self.auth_partner._validate_email(self.directory, "wrong") self.assertFalse(self.auth_partner.mail_verified) def test_validate_email_token(self): with self.new_mails() as new_mails: new_auth_partner = self.env["auth.partner"]._signup( self.directory, name="New Partner", login="new-partner-auth@example.org", password="NewSecret", ) self.assertFalse(new_auth_partner.mail_verified) token = new_mails.body.split("token=")[1].split('">')[0] new_auth_partner._validate_email(self.directory, token) self.assertTrue(new_auth_partner.mail_verified) def test_impersonate_ok(self): action = self.auth_partner.with_user( self.env.ref("base.user_admin") ).impersonate() token = action["url"].split("/")[-1] auth_partner = self.env["auth.partner"]._impersonating(self.directory, token) self.assertEqual(auth_partner, self.auth_partner) def test_impersonate_once(self): action = self.auth_partner.with_user( self.env.ref("base.user_admin") ).impersonate() token = action["url"].split("/")[-1] self.env["auth.partner"]._impersonating(self.directory, token) with self.assertRaisesRegex(UserError, "Invalid Token"): self.env["auth.partner"]._impersonating(self.directory, token) def test_impersonate_wrong_directory(self): action = self.auth_partner.with_user( self.env.ref("base.user_admin") ).impersonate() token = action["url"].split("/")[-1] with self.assertRaisesRegex(UserError, "Invalid Token"): self.env["auth.partner"]._impersonating(self.other_directory, token) def test_impersonate_wrong_user(self): with self.assertRaisesRegex(AccessDenied, "not allowed to impersonate"): self.auth_partner.with_user(self.env.ref("base.default_user")).impersonate() def test_impersonate_not_expired_token(self): self.directory.impersonating_token_duration = 100 action = self.auth_partner.with_user( self.env.ref("base.user_admin") ).impersonate() token = action["url"].split("/")[-1] with freeze_time(datetime.now() + timedelta(hours=1)): self.env["auth.partner"]._impersonating(self.directory, token) def test_impersonate_expired_token(self): self.directory.impersonating_token_duration = 100 action = self.auth_partner.with_user( self.env.ref("base.user_admin") ).impersonate() token = action["url"].split("/")[-1] with ( freeze_time(datetime.now() + timedelta(hours=2)), self.assertRaisesRegex(UserError, "Invalid Token"), ): self.env["auth.partner"]._impersonating(self.directory, token) def test_set_password_ok(self): self.auth_partner._set_password( self.directory, self.auth_partner._generate_set_password_token(), "ResetSecret", ) auth_partner = self.env["auth.partner"]._login( self.directory, login="partner-auth@example.org", password="ResetSecret" ) self.assertTrue(auth_partner) def test_set_password_wrong_token(self): with self.assertRaisesRegex(UserError, "Invalid Token"): self.auth_partner._set_password(self.directory, "wrong", "ResetSecret") def test_set_password_once(self): token = self.auth_partner._generate_set_password_token() self.auth_partner._set_password(self.directory, token, "ResetSecret") with self.assertRaisesRegex(UserError, "Invalid Token"): self.auth_partner._set_password(self.directory, token, "ResetSecret") def test_set_password_not_expired_token(self): self.directory.set_password_token_duration = 100 token = self.auth_partner._generate_set_password_token() with freeze_time(datetime.now() + timedelta(hours=1)): self.auth_partner._set_password(self.directory, token, "ResetSecret") auth_partner = self.env["auth.partner"]._login( self.directory, login="partner-auth@example.org", password="ResetSecret" ) self.assertTrue(auth_partner) def test_set_password_expired_token(self): self.directory.set_password_token_duration = 100 token = self.auth_partner._generate_set_password_token() with ( freeze_time(datetime.now() + timedelta(hours=2)), self.assertRaisesRegex(UserError, "Invalid Token"), ): self.auth_partner._set_password(self.directory, token, "ResetSecret") def test_reset_password_ok(self): with self.new_mails() as new_mails: self.auth_partner._request_reset_password() self.assertEqual(len(new_mails), 1) self.assertEqual(new_mails.subject, "Reset Password") self.assertIn( "Click on the following link to reset your password", new_mails.body ) token = new_mails.body.split("token=")[1].split('">')[0] self.auth_partner._set_password(self.directory, token, "ResetSecret") auth_partner = self.env["auth.partner"]._login( self.directory, login="partner-auth@example.org", password="ResetSecret" ) self.assertTrue(auth_partner) def test_reset_password_wrong_partner(self): with self.new_mails() as new_mails: self.auth_partner._request_reset_password() self.assertEqual(len(new_mails), 1) self.assertEqual(new_mails.subject, "Reset Password") self.assertIn( "Click on the following link to reset your password", new_mails.body ) token = new_mails.body.split("token=")[1].split('">')[0] # This should probably raise instead of reseting the auth_partner password self.other_auth_partner._set_password(self.directory, token, "ResetSecret") with self.assertRaisesRegex(AccessDenied, "Invalid Login or Password"): self.env["auth.partner"]._login( self.directory, login="other-partner-auth@example.org", password="ResetSecret", ) def test_reset_password_once(self): with self.new_mails() as new_mails: self.auth_partner._request_reset_password() self.assertEqual(len(new_mails), 1) self.assertEqual(new_mails.subject, "Reset Password") token = new_mails.body.split("token=")[1].split('">')[0] self.auth_partner._set_password(self.directory, token, "ResetSecret") with self.assertRaisesRegex(UserError, "Invalid Token"): self.auth_partner._set_password(self.directory, token, "ResetSecret2") def test_send_invite_set_password_ok(self): with self.new_mails() as new_mails: self.auth_partner._send_invite() self.assertEqual(len(new_mails), 1) self.assertEqual(new_mails.subject, "Welcome") self.assertIn("your account have been created", new_mails.body) token = new_mails.body.split("token=")[1].split('">')[0] self.auth_partner._set_password(self.directory, token, "ResetSecret") auth_partner = self.env["auth.partner"]._login( self.directory, login="partner-auth@example.org", password="ResetSecret" ) self.assertTrue(auth_partner) def test_send_invite_set_password_once(self): with self.new_mails() as new_mails: self.auth_partner._send_invite() self.assertEqual(len(new_mails), 1) self.assertEqual(new_mails.subject, "Welcome") token = new_mails.body.split("token=")[1].split('">')[0] self.auth_partner._set_password(self.directory, token, "ResetSecret") with self.assertRaisesRegex(UserError, "Invalid Token"): self.auth_partner._set_password(self.directory, token, "ResetSecret2")