diff --git a/base_tier_validation/security/ir.model.access.csv b/base_tier_validation/security/ir.model.access.csv index 82c76c65b..ed5b411ed 100644 --- a/base_tier_validation/security/ir.model.access.csv +++ b/base_tier_validation/security/ir.model.access.csv @@ -1,8 +1,4 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_tier_review_group_public,access_tier_review_group_public,model_tier_review,base.group_public,1,0,0,0 -access_tier_definition_group_public,access_tier_definition_group_public,model_tier_definition,base.group_public,1,0,0,0 -access_tier_review_group_portal,access_tier_review_group_portal,model_tier_review,base.group_portal,1,0,0,0 -access_tier_definition_group_portal,access_tier_definition_group_portal,model_tier_definition,base.group_portal,1,0,0,0 access_tier_review,access.tier.review,model_tier_review,base.group_user,1,1,1,1 access_tier_definition_all,tier.definition.all,model_tier_definition,base.group_user,1,0,0,0 access_tier_definition_settings,tier.definition.settings,model_tier_definition,base.group_erp_manager,1,1,1,1 diff --git a/base_tier_validation/tests/__init__.py b/base_tier_validation/tests/__init__.py index 9859e84ca..e4a78140e 100644 --- a/base_tier_validation/tests/__init__.py +++ b/base_tier_validation/tests/__init__.py @@ -2,3 +2,4 @@ from . import test_tier_validation from . import test_tier_validation_reminder +from . import test_tier_validation_access diff --git a/base_tier_validation/tests/test_tier_validation_access.py b/base_tier_validation/tests/test_tier_validation_access.py new file mode 100644 index 000000000..f1e59062c --- /dev/null +++ b/base_tier_validation/tests/test_tier_validation_access.py @@ -0,0 +1,18 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from odoo.exceptions import AccessError +from odoo.tests import new_test_user, tagged + +from .common import CommonTierValidation + + +@tagged("post_install", "-at_install") +class TierValidationAccess(CommonTierValidation): + def test_portal_and_public_cannot_read_reviews(self): + self.test_record.with_user(self.test_user_2).request_validation() + self.assertTrue(self.test_record.review_ids) + portal = new_test_user(self.env, login="tv_portal", groups="base.group_portal") + public = self.env.ref("base.public_user") + for user in (portal, public): + for model in ("tier.review", "tier.definition"): + with self.assertRaises(AccessError): + self.env[model].with_user(user).search([]) diff --git a/purchase_tier_validation/tests/__init__.py b/purchase_tier_validation/tests/__init__.py index f39596410..bb3410c31 100644 --- a/purchase_tier_validation/tests/__init__.py +++ b/purchase_tier_validation/tests/__init__.py @@ -1,3 +1,4 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from . import test_tier_validation +from . import test_portal diff --git a/purchase_tier_validation/tests/test_portal.py b/purchase_tier_validation/tests/test_portal.py new file mode 100644 index 000000000..0b11101c9 --- /dev/null +++ b/purchase_tier_validation/tests/test_portal.py @@ -0,0 +1,55 @@ +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). +from odoo import Command +from odoo.tests import tagged +from odoo.tests.common import new_test_user + +from odoo.addons.base.tests.common import HttpCaseWithUserPortal + + +@tagged("post_install", "-at_install") +class TestPurchaseTierValidationPortal(HttpCaseWithUserPortal): + @classmethod + def setUpClass(cls): + super().setUpClass() + reviewer = new_test_user( + cls.env, login="portal_test_reviewer", groups="purchase.group_purchase_user" + ) + cls.env["tier.definition"].create( + { + "model_id": cls.env.ref("purchase.model_purchase_order").id, + "review_type": "individual", + "reviewer_id": reviewer.id, + } + ) + product = cls.env["product.product"].create({"name": "Product for test"}) + cls.order = cls.env["purchase.order"].create( + { + "partner_id": cls.partner_portal.id, + "order_line": [ + Command.create({"product_id": product.id, "price_unit": 10.0}) + ], + } + ) + cls.order.write({"state": "sent"}) + cls.order.request_validation() + + def test_portal_user_cannot_read_reviews(self): + self.assertTrue(self.order.review_ids) + portal_env = self.env(user=self.user_portal) + for model in ("tier.review", "tier.definition"): + self.assertFalse(portal_env[model].has_access("read")) + + def test_portal_vendor_views_order_under_validation(self): + self.authenticate(self.user_portal.login, self.user_portal.login) + for url in ( + f"/my/purchase/{self.order.id}", + f"/my/purchase/{self.order.id}?report_type=pdf", + ): + response = self.url_open(url) + self.assertEqual(response.status_code, 200) + + def test_public_views_order_under_validation(self): + token = self.order._portal_ensure_token() + response = self.url_open(f"/my/purchase/{self.order.id}?access_token={token}") + self.assertEqual(response.status_code, 200) + self.assertIn(self.order.name, response.text) diff --git a/sale_tier_validation/tests/__init__.py b/sale_tier_validation/tests/__init__.py index e1a50db59..ea33e6152 100644 --- a/sale_tier_validation/tests/__init__.py +++ b/sale_tier_validation/tests/__init__.py @@ -1,2 +1,3 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from . import test_tier_validation +from . import test_portal diff --git a/sale_tier_validation/tests/test_portal.py b/sale_tier_validation/tests/test_portal.py new file mode 100644 index 000000000..24d22baa5 --- /dev/null +++ b/sale_tier_validation/tests/test_portal.py @@ -0,0 +1,93 @@ +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). +from odoo import Command +from odoo.tests import tagged +from odoo.tests.common import new_test_user + +from odoo.addons.base.tests.common import HttpCaseWithUserPortal + +SIGNATURE = "R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" + + +@tagged("post_install", "-at_install") +class TestSaleTierValidationPortal(HttpCaseWithUserPortal): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.reviewer = new_test_user( + cls.env, + login="portal_test_reviewer", + groups="sales_team.group_sale_salesman_all_leads", + ) + so_model = cls.env.ref("sale.model_sale_order") + cls.env["tier.definition"].create( + { + "model_id": so_model.id, + "review_type": "individual", + "reviewer_id": cls.reviewer.id, + } + ) + # Without it, signing is refused while the quotation is not confirmed + cls.env["tier.validation.exception"].create( + { + "model_id": so_model.id, + "field_ids": [ + Command.set( + so_model.field_id.filtered( + lambda f: f.name in ("signature", "signed_by", "signed_on") + ).ids + ) + ], + } + ) + product = cls.env["product.product"].create( + {"name": "Product for test", "list_price": 100.0} + ) + cls.order = cls.env["sale.order"].create( + { + "partner_id": cls.partner_portal.id, + "require_signature": True, + "require_payment": False, + "order_line": [Command.create({"product_id": product.id})], + } + ) + cls.order.action_quotation_sent() + cls.order.request_validation() + + def test_portal_user_cannot_read_reviews(self): + self.assertTrue(self.order.review_ids) + portal_env = self.env(user=self.user_portal) + for model in ("tier.review", "tier.definition"): + self.assertFalse(portal_env[model].has_access("read")) + + def test_portal_flow_with_reviews(self): + self.authenticate(self.user_portal.login, self.user_portal.login) + response = self.url_open(f"/my/orders/{self.order.id}") + self.assertEqual(response.status_code, 200) + self.assertIn(self.order.name, response.text) + self.make_jsonrpc_request( + "/mail/message/post", + { + "thread_model": "sale.order", + "thread_id": self.order.id, + "post_data": {"body": "Any news on the approval?"}, + }, + ) + self.order.with_user(self.reviewer).validate_tier() + self.assertEqual(self.order.validation_status, "validated") + self.make_jsonrpc_request( + f"/my/orders/{self.order.id}/accept", + {"name": "Joel Willis", "signature": SIGNATURE}, + ) + self.assertEqual(self.order.state, "sale") + + def test_public_flow_with_reviews(self): + token = self.order._portal_ensure_token() + response = self.url_open(f"/my/orders/{self.order.id}?access_token={token}") + self.assertEqual(response.status_code, 200) + self.assertIn(self.order.name, response.text) + self.order.with_user(self.reviewer).validate_tier() + self.make_jsonrpc_request( + f"/my/orders/{self.order.id}/accept?access_token={token}", + {"name": "Joel Willis", "signature": SIGNATURE}, + ) + self.assertEqual(self.order.state, "sale")