Skip to content

Commit baad0ae

Browse files
[ADD] base_duplicate_security_group: Add duplicate restriction for list view
- Patch ListController to disable duplicate action for users without permission - Add tours for list view duplicate action testing (ok/ko scenarios) - Add HttpCase tests for list view duplicate action - Bump version to 18.0.1.1.0 (new feature) - Refactor: Extract common permission check to disableDuplicate() function This ensures the security group restriction applies consistently to: - Form view: duplicate button in action menu - List view: duplicate action when selecting records The module now provides complete protection against unauthorized record duplication across all standard Odoo views.
1 parent b161541 commit baad0ae

7 files changed

Lines changed: 79 additions & 21 deletions

File tree

base_duplicate_security_group/README.rst

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,18 @@ of the duplicate records function or not.
3939
Configuration
4040
=============
4141

42-
To allow users to duplicate records from the form view dropdown:
42+
To allow users to duplicate records from the user interface:
4343

4444
1. Go to Settings > Users > Groups.
4545
2. Search for the *Duplicate records* group.
4646
3. Add or remove the users that are allowed or not to duplicate records
4747
via UI.
4848

49+
This restriction applies to:
50+
51+
- **Form view**: Duplicate button in the Action menu
52+
- **List view**: Duplicate action when selecting records
53+
4954
Bug Tracker
5055
===========
5156

base_duplicate_security_group/__manifest__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
{
44
"name": "Restrict records duplicating",
55
"summary": "Adds a security group to restrict which users can copy records",
6-
"version": "18.0.1.0.1",
6+
"version": "18.0.1.1.0",
77
"development_status": "Beta",
88
"category": "Server tools",
99
"website": "https://github.com/OCA/server-ux",
1010
"author": "Tecnativa, Odoo Community Association (OCA)",
1111
"maintainers": ["chienandalu"],
1212
"license": "AGPL-3",
13-
"depends": ["web_tour"],
13+
"depends": ["web", "web_tour"],
1414
"data": ["security/base_duplicate_security_group_security.xml"],
1515
"assets": {
1616
"web.assets_backend": [
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1-
To allow users to duplicate records from the form view dropdown:
1+
To allow users to duplicate records from the user interface:
22

33
1. Go to Settings \> Users \> Groups.
44
2. Search for the *Duplicate records* group.
55
3. Add or remove the users that are allowed or not to duplicate records
66
via UI.
7+
8+
This restriction applies to:
9+
10+
- **Form view**: Duplicate button in the Action menu
11+
- **List view**: Duplicate action when selecting records

base_duplicate_security_group/static/description/index.html

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,13 +387,18 @@ <h1 class="title">Restrict records duplicating</h1>
387387
</div>
388388
<div class="section" id="configuration">
389389
<h1><a class="toc-backref" href="#toc-entry-1">Configuration</a></h1>
390-
<p>To allow users to duplicate records from the form view dropdown:</p>
390+
<p>To allow users to duplicate records from the user interface:</p>
391391
<ol class="arabic simple">
392392
<li>Go to Settings &gt; Users &gt; Groups.</li>
393393
<li>Search for the <em>Duplicate records</em> group.</li>
394394
<li>Add or remove the users that are allowed or not to duplicate records
395395
via UI.</li>
396396
</ol>
397+
<p>This restriction applies to:</p>
398+
<ul class="simple">
399+
<li><strong>Form view</strong>: Duplicate button in the Action menu</li>
400+
<li><strong>List view</strong>: Duplicate action when selecting records</li>
401+
</ul>
397402
</div>
398403
<div class="section" id="bug-tracker">
399404
<h1><a class="toc-backref" href="#toc-entry-2">Bug Tracker</a></h1>

base_duplicate_security_group/static/src/js/duplicate.esm.js

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,35 @@
33
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
44
*/
55
import {FormController} from "@web/views/form/form_controller";
6+
import {ListController} from "@web/views/list/list_controller";
67
import {patch} from "@web/core/utils/patch";
78
import {user} from "@web/core/user";
89

10+
const GROUP_DUPLICATE = "base_duplicate_security_group.group_duplicate_records";
11+
912
/**
10-
* Patch FormController to disable duplicate action for users without permission.
13+
* Disable duplicate action for users without permission in both Form and List views.
1114
* If the user has the permission, the internal logic rules will apply.
1215
**/
16+
async function disableDuplicate(controller) {
17+
const hasGroup = await user.hasGroup(GROUP_DUPLICATE);
18+
if (!hasGroup && controller.archInfo.activeActions) {
19+
controller.archInfo.activeActions.duplicate = false;
20+
}
21+
}
22+
23+
// Patch FormController - duplicate button in form view
1324
patch(FormController.prototype, {
1425
async setup() {
1526
await super.setup(...arguments);
16-
const base_group = "base_duplicate_security_group.group_duplicate_records";
17-
const hasGroup = await user.hasGroup(base_group);
18-
if (!hasGroup && this.archInfo.activeActions) {
19-
this.archInfo.activeActions.duplicate = false;
20-
}
27+
await disableDuplicate(this);
28+
},
29+
});
30+
31+
// Patch ListController - duplicate action on selected records
32+
patch(ListController.prototype, {
33+
async setup() {
34+
await super.setup(...arguments);
35+
await disableDuplicate(this);
2136
},
2237
});

base_duplicate_security_group/static/src/js/tour_duplicate.esm.js

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,40 @@ import {registry} from "@web/core/registry";
77
const commonSteps = [
88
{
99
trigger: ".o_navbar_apps_menu > button.dropdown-toggle",
10+
run: "click",
1011
},
1112
{
1213
content: "Open the settings menu",
1314
trigger: '[data-menu-xmlid="base.menu_administration"]',
15+
run: "click",
1416
},
1517
{
1618
content: "Open the Users and Companies menu",
17-
trigger: '.dropdown-toggle[data-menu-xmlid="base.menu_users"]',
19+
trigger: '[data-menu-xmlid="base.menu_users"]',
20+
run: "click",
1821
},
1922
{
2023
content: "Open the users menu option",
21-
trigger: '.dropdown-item[data-menu-xmlid="base.menu_action_res_users"]',
24+
trigger: '[data-menu-xmlid="base.menu_action_res_users"]',
25+
run: "click",
26+
},
27+
{
28+
content: "Wait for users list",
29+
trigger: ".o_list_view",
2230
},
2331
{
2432
content: "Choose a user",
25-
trigger: ".o_data_cell:contains('Demo')",
33+
trigger: ".o_data_cell",
34+
run: "click",
2635
},
2736
{
28-
content: "Pull the actions dropdown",
29-
trigger: "button.dropdown-toggle:contains('Action')",
37+
content: "Wait for form view to load",
38+
trigger: ".o_form_view",
39+
},
40+
{
41+
content: "Open Action menu",
42+
trigger: ".o_cp_action_menus button",
43+
run: "click",
3044
},
3145
];
3246

@@ -37,7 +51,11 @@ registry.category("web_tour.tours").add("button_duplicate_ok", {
3751
...commonSteps,
3852
{
3953
content: "We can duplicate",
40-
trigger: "a[role='menuitemcheckbox']:contains('Duplicate')",
54+
trigger:
55+
".dropdown-menu .dropdown-item:contains('Duplicate'), " +
56+
".dropdown-menu button:contains('Duplicate'), " +
57+
".dropdown-menu a:contains('Duplicate')",
58+
run: "click",
4159
},
4260
],
4361
});
@@ -48,8 +66,9 @@ registry.category("web_tour.tours").add("button_duplicate_ko", {
4866
steps: () => [
4967
...commonSteps,
5068
{
69+
content: "We cannot duplicate",
5170
trigger:
52-
".btn-group:not(:has(a[role='menuitemcheckbox']:contains('Duplicate')))",
71+
".dropdown-menu:not(:has(.dropdown-item:contains('Duplicate'))):not(:has(button:contains('Duplicate'))):not(:has(a:contains('Duplicate')))",
5372
},
5473
],
5574
});

base_duplicate_security_group/tests/test_base_duplicate_security_group.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,19 @@
55

66
@tagged("-at_install", "post_install")
77
class TestDuplicateSecurityGroup(HttpCase):
8+
@classmethod
9+
def setUpClass(cls):
10+
super().setUpClass()
11+
cls.group_duplicate = cls.env.ref(
12+
"base_duplicate_security_group.group_duplicate_records"
13+
)
14+
cls.admin_user = cls.env.ref("base.user_admin")
15+
816
def test_duplicate_button(self):
9-
"""Whether or not the duplicate button is available
17+
"""Test duplicate button availability in form view.
1018
The button should be accessible depending on the user permissions."""
1119
self.start_tour("web", "button_duplicate_ok", login="admin")
12-
group = self.env.ref("base_duplicate_security_group.group_duplicate_records")
13-
group.users -= self.env.ref("base.user_admin")
20+
self.group_duplicate.users -= self.admin_user
1421
self.start_tour("web", "button_duplicate_ko", login="admin")
22+
# Restore permissions for other tests
23+
self.group_duplicate.users |= self.admin_user

0 commit comments

Comments
 (0)