From 3d211dae5551516b77ae4ede1183d5b0164d2f95 Mon Sep 17 00:00:00 2001 From: Aungkokolin1997 Date: Thu, 14 Sep 2023 14:47:55 +0630 Subject: [PATCH] [IMP] purchase_security: add is_restricted option --- purchase_security/README.rst | 27 +++++---- purchase_security/models/purchase_order.py | 19 +++++- purchase_security/readme/CONFIGURATION.rst | 2 +- purchase_security/readme/CONTRIBUTORS.rst | 4 ++ purchase_security/readme/DESCRIPTION.rst | 14 ++--- purchase_security/readme/USAGE.rst | 7 ++- purchase_security/security/security.xml | 19 +++++- .../static/description/index.html | 41 +++++++------ purchase_security/tests/test_access_rights.py | 60 +++++++++++++++++-- .../views/purchase_order_views.xml | 31 ++++++++++ 10 files changed, 177 insertions(+), 47 deletions(-) diff --git a/purchase_security/README.rst b/purchase_security/README.rst index 6b6f44cb745..ce4f608e63b 100644 --- a/purchase_security/README.rst +++ b/purchase_security/README.rst @@ -7,7 +7,7 @@ Purchase Order security !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:9e1bbc1a8aa6093aa6f5cffb798552acf8886822317f4ed66d7b5da5684ea62d + !! source digest: sha256:e34914e47157d89425e93f9ef3639e32765ef386fc0c435d9d35a6ce6b7a56dd !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png @@ -28,15 +28,15 @@ Purchase Order security |badge1| |badge2| |badge3| |badge4| |badge5| -This addon creates new groups in Purchase. +This add-on creates two new groups: "User (own orders)" and "User (own or unrestricted orders)" +in Purchases. -Visibility of purchase orders is restricted for users in these groups. -You can only see the purchase order: +Users in the "User (own orders)" group can only see Purchase Orders where they are +the representative, or all of them if they are managers. -- User (own orders): If you are a follower of the partner or there is no user - or you are the partner's user. -- User (team orders): If you are a follower of the partner or there is no user - or you are a user of your purchasing team. +Users in the "User (own or unrestricted orders)" group can only see Purchase Orders where +they are the representative, as well as those where is_restricted is false. If they are managers, +they can see all orders. **Table of contents** @@ -53,10 +53,13 @@ To use this module, you need to: (in the **Other Information** tab), if you are a Purchase User or Manager. If you are a Purchass User (own orders), i'll be automatically assigned, and you won't be able to change it +#. Enable the `is_restricted` option in the purchase order if you want + to prevent other users from viewing your PO. #. Confirm the Purchase Order #. Go back to the **Purchase Orders** view. -#. If you are a Purchase User or a Purchase Manager, you should be - able to see all orders. If not, you'll only see your own orders. +#. If you are a Purchase User or a Purchase Manager, you can see all orders. If you are a Purchase User (own orders), + you'll only see your own orders. If you are a Purchase User (own or unrestricted orders), you'll see + both your own orders and those that are unrestricted. Bug Tracker =========== @@ -88,6 +91,10 @@ Contributors * `Solvos `_: * David Alonso +* `Quartile `__: + + * Rinaldi Firdaus + * Aung Ko Ko Lin Maintainers ~~~~~~~~~~~ diff --git a/purchase_security/models/purchase_order.py b/purchase_security/models/purchase_order.py index 1e4df9c0f29..473cdcb634e 100644 --- a/purchase_security/models/purchase_order.py +++ b/purchase_security/models/purchase_order.py @@ -4,7 +4,8 @@ # Copyright 2024 Tecnativa - Víctor Martínez # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo import api, fields, models +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError class PurchaseOrder(models.Model): @@ -22,6 +23,22 @@ class PurchaseOrder(models.Model): store=True, readonly=False, ) + is_restricted = fields.Boolean( + "Restrict Access", + tracking=True, + help="If selected, this purchase order can only be accessed by the assigned " + "buyer or purchase managers.", + ) + + @api.constrains("is_restricted") + def _check_is_restricted_access(self): + for order in self: + if order.user_id != self.env.user and not self.user_has_groups( + "purchase.group_purchase_manager" + ): + raise ValidationError( + _("You do not have the right to change Restrict Access setting.") + ) def _compute_is_user_id_editable(self): is_user_id_editable = self.env.user.has_group( diff --git a/purchase_security/readme/CONFIGURATION.rst b/purchase_security/readme/CONFIGURATION.rst index 8aa8421bcdf..9d9b533c9c4 100644 --- a/purchase_security/readme/CONFIGURATION.rst +++ b/purchase_security/readme/CONFIGURATION.rst @@ -1,5 +1,5 @@ To use this module you need to add the users whose access you want to restrict -to the "Purchases / User (own orders)" group +to the "Purchases / User (own orders)" group or "Purchases / User (own or unrestricted orders)" You can also assign a Purchase Manager by adding him to the "Purchases / Administrator" group diff --git a/purchase_security/readme/CONTRIBUTORS.rst b/purchase_security/readme/CONTRIBUTORS.rst index eccebd01a91..cba074644ad 100644 --- a/purchase_security/readme/CONTRIBUTORS.rst +++ b/purchase_security/readme/CONTRIBUTORS.rst @@ -7,3 +7,7 @@ * `Solvos `_: * David Alonso +* `Quartile `__: + + * Rinaldi Firdaus + * Aung Ko Ko Lin diff --git a/purchase_security/readme/DESCRIPTION.rst b/purchase_security/readme/DESCRIPTION.rst index ec67d54b8d0..96d282cf5c1 100644 --- a/purchase_security/readme/DESCRIPTION.rst +++ b/purchase_security/readme/DESCRIPTION.rst @@ -1,9 +1,9 @@ -This addon creates new groups in Purchase. +This add-on creates two new groups: "User (own orders)" and "User (own or unrestricted orders)" +in Purchases. -Visibility of purchase orders is restricted for users in these groups. -You can only see the purchase order: +Users in the "User (own orders)" group can only see Purchase Orders where they are +the representative, or all of them if they are managers. -- User (own orders): If you are a follower of the partner or there is no user - or you are the partner's user. -- User (team orders): If you are a follower of the partner or there is no user - or you are a user of your purchasing team. +Users in the "User (own or unrestricted orders)" group can only see Purchase Orders where +they are the representative, as well as those where is_restricted is false. If they are managers, +they can see all orders. diff --git a/purchase_security/readme/USAGE.rst b/purchase_security/readme/USAGE.rst index 62d65e34916..065ccca364c 100644 --- a/purchase_security/readme/USAGE.rst +++ b/purchase_security/readme/USAGE.rst @@ -5,7 +5,10 @@ To use this module, you need to: (in the **Other Information** tab), if you are a Purchase User or Manager. If you are a Purchass User (own orders), i'll be automatically assigned, and you won't be able to change it +#. Enable the `is_restricted` option in the purchase order if you want + to prevent other users from viewing your PO. #. Confirm the Purchase Order #. Go back to the **Purchase Orders** view. -#. If you are a Purchase User or a Purchase Manager, you should be - able to see all orders. If not, you'll only see your own orders. +#. If you are a Purchase User or a Purchase Manager, you can see all orders. If you are a Purchase User (own orders), + you'll only see your own orders. If you are a Purchase User (own or unrestricted orders), you'll see + both your own orders and those that are unrestricted. diff --git a/purchase_security/security/security.xml b/purchase_security/security/security.xml index f8976f42d2f..ebde3048311 100644 --- a/purchase_security/security/security.xml +++ b/purchase_security/security/security.xml @@ -16,11 +16,18 @@ eval="[(4, ref('purchase_security.group_purchase_own_orders'))]" /> + + User (own or unrestricted orders) + + + @@ -31,6 +38,14 @@ [(1, '=', 1)] + + View purchase orders (own or unrestricted) + + ['|','|',('is_restricted','=',False),('user_id','=',user.id),('user_id','=',False)] + + View purchase orders (own responsible) diff --git a/purchase_security/static/description/index.html b/purchase_security/static/description/index.html index 40549c20ee2..74c6e81bf5b 100644 --- a/purchase_security/static/description/index.html +++ b/purchase_security/static/description/index.html @@ -8,11 +8,10 @@ /* :Author: David Goodger (goodger@python.org) -:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $ +:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $ :Copyright: This stylesheet has been placed in the public domain. Default cascading style sheet for the HTML output of Docutils. -Despite the name, some widely supported CSS2 features are used. See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to customize this style sheet. @@ -275,7 +274,7 @@ margin-left: 2em ; margin-right: 2em } -pre.code .ln { color: gray; } /* line numbers */ +pre.code .ln { color: grey; } /* line numbers */ pre.code, code { background-color: #eeeeee } pre.code .comment, code .comment { color: #5C6576 } pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold } @@ -301,7 +300,7 @@ span.pre { white-space: pre } -span.problematic, pre.problematic { +span.problematic { color: red } span.section-subtitle { @@ -367,18 +366,16 @@

Purchase Order security

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:9e1bbc1a8aa6093aa6f5cffb798552acf8886822317f4ed66d7b5da5684ea62d +!! source digest: sha256:e34914e47157d89425e93f9ef3639e32765ef386fc0c435d9d35a6ce6b7a56dd !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Production/Stable License: AGPL-3 OCA/purchase-workflow Translate me on Weblate Try me on Runboat

-

This addon creates new groups in Purchase.

-

Visibility of purchase orders is restricted for users in these groups. -You can only see the purchase order:

-
    -
  • User (own orders): If you are a follower of the partner or there is no user -or you are the partner’s user.
  • -
  • User (team orders): If you are a follower of the partner or there is no user -or you are a user of your purchasing team.
  • -
+

This add-on creates two new groups: “User (own orders)” and “User (own or unrestricted orders)” +in Purchases.

+

Users in the “User (own orders)” group can only see Purchase Orders where they are +the representative, or all of them if they are managers.

+

Users in the “User (own or unrestricted orders)” group can only see Purchase Orders where +they are the representative, as well as those where is_restricted is false. If they are managers, +they can see all orders.

Table of contents

    @@ -401,10 +398,13 @@

    Usage

    (in the Other Information tab), if you are a Purchase User or Manager. If you are a Purchass User (own orders), i’ll be automatically assigned, and you won’t be able to change it +
  • Enable the is_restricted option in the purchase order if you want +to prevent other users from viewing your PO.
  • Confirm the Purchase Order
  • Go back to the Purchase Orders view.
  • -
  • If you are a Purchase User or a Purchase Manager, you should be -able to see all orders. If not, you’ll only see your own orders.
  • +
  • If you are a Purchase User or a Purchase Manager, you can see all orders. If you are a Purchase User (own orders), +you’ll only see your own orders. If you are a Purchase User (own or unrestricted orders), you’ll see +both your own orders and those that are unrestricted.
@@ -437,14 +437,17 @@

Contributors

  • David Alonso <david.alonso@solvos.es>
  • +
  • Quartile:
      +
    • Rinaldi Firdaus
    • +
    • Aung Ko Ko Lin
    • +
    +
  • Maintainers

    This module is maintained by the OCA.

    - -Odoo Community Association - +Odoo Community Association

    OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use.

    diff --git a/purchase_security/tests/test_access_rights.py b/purchase_security/tests/test_access_rights.py index 3d0cee899f5..b967915468d 100644 --- a/purchase_security/tests/test_access_rights.py +++ b/purchase_security/tests/test_access_rights.py @@ -26,6 +26,8 @@ def setUpClass(cls): cls.team1 = cls.env["purchase.team"].create({"name": "Team1"}) cls.team2 = cls.env["purchase.team"].create({"name": "Team2"}) # Users + users = cls.env["res.users"].with_context(no_reset_password=True) + purchase_restricted_group = "group_purchase_restricted_orders" # User in group_purchase_own_orders cls.user_group_purchase_own_orders = new_test_user( cls.env, @@ -55,6 +57,25 @@ def setUpClass(cls): login="group_purchase_team_3_orders", groups="purchase_security.group_purchase_group_orders", ) + # User in group_purchase_restricted_orders + cls.user_group_purchase_restricted_orders = users.create( + { + "name": "group_purchase_restricted_orders", + "login": "group_purchase_restricted_orders", + "email": "group_purchase_restricted_orders@example.com", + "groups_id": [ + ( + 6, + 0, + [ + cls.env.ref( + "purchase_security.%s" % purchase_restricted_group + ).id + ], + ) + ], + } + ) # Purchase order user cls.user_po_user = new_test_user( cls.env, login="po_user", groups="purchase.group_purchase_user" @@ -93,6 +114,17 @@ def setUpClass(cls): "partner_id": cls.partner_po.id, "team_id": cls.team2.id, }, + { + "name": "po_security_5", + "user_id": cls.user_group_purchase_own_orders.id, + "partner_id": cls.partner_po.id, + "is_restricted": True, + }, + { + "name": "po_security_6", + "user_id": cls.user_group_purchase_restricted_orders.id, + "partner_id": cls.partner_po.id, + }, ) ) @@ -153,7 +185,7 @@ def test_access_user_user_group_purchase_own_orders(self): .with_user(self.user_group_purchase_own_orders) .search([]) ), - 2, + 3, ) self.assertFalse( self.orders.filtered( @@ -163,6 +195,24 @@ def test_access_user_user_group_purchase_own_orders(self): .is_user_id_editable ) + def test_access_user_group_purchase_restricted_orders(self): + # User in group should have access to it's own PO + # and unrestricted orders + self.assertEqual( + len( + self.env["purchase.order"] + .with_user(self.user_group_purchase_restricted_orders) + .search([("name", "like", "po_security")]) + .ids + ), + 5, + ) + self.assertTrue( + self.orders.with_user(self.user_group_purchase_restricted_orders)[ + 0 + ].is_user_id_editable + ) + def test_access_user_po_user(self): # Normal PO user should have access to all of them # because he is not in group @@ -172,7 +222,7 @@ def test_access_user_po_user(self): .with_user(self.user_po_user) .search([("name", "like", "po_security")]) ), - 4, + 6, ) self.assertTrue(self.orders.with_user(self.user_po_user)[0].is_user_id_editable) @@ -184,7 +234,7 @@ def test_access_user_po_manager(self): .with_user(self.user_po_manager) .search([("name", "like", "po_security")]) ), - 4, + 6, ) self.assertTrue( self.orders.with_user(self.user_po_manager)[1].is_user_id_editable @@ -207,7 +257,7 @@ def test_access_user_user_group_purchase_group_orders_1(self): .with_user(self.user_group_team_1) .search([("name", "like", "po_security")]) ), - 4, + 6, ) def test_access_user_user_group_purchase_group_orders_2(self): @@ -220,7 +270,7 @@ def test_access_user_user_group_purchase_group_orders_2(self): .with_user(self.user_group_team_2) .search([("name", "like", "po_security")]) ), - 3, + 5, ) def test_access_user_user_group_purchase_group_orders_3(self): diff --git a/purchase_security/views/purchase_order_views.xml b/purchase_security/views/purchase_order_views.xml index 9558a7f4f5d..0d487d49003 100644 --- a/purchase_security/views/purchase_order_views.xml +++ b/purchase_security/views/purchase_order_views.xml @@ -5,6 +5,9 @@ purchase.order + + + @@ -28,4 +31,32 @@ + + purchase.order.tree + purchase.order + + + + + + + + + purchase.order.inherit.purchase.order.tree + purchase.order + + + + + + +