From 95e9afa1f36849fbb544dad0ab71abd2d53bf8b3 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Mon, 21 Jan 2019 16:52:12 +0530 Subject: [PATCH] feat: Clear user permissions button (#6767) * Add button to delete user permissions in bulk * Show no records deleted the delete count is 0 * Return this from show of dialog to make it chainable * Add test for clear user permissions function * Fix test * Format code * Reset the user * Remove rollback from test * Move clear user permission button to menu * fix: Translations --- .../user_permission/user_permission.py | 12 ++++- .../user_permission/user_permission_list.js | 52 +++++++++++++++++++ frappe/public/js/frappe/ui/dialog.js | 1 + frappe/tests/test_permissions.py | 34 +++++++++++- 4 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 frappe/core/doctype/user_permission/user_permission_list.js diff --git a/frappe/core/doctype/user_permission/user_permission.py b/frappe/core/doctype/user_permission/user_permission.py index 0fd2efa757..43dff47745 100644 --- a/frappe/core/doctype/user_permission/user_permission.py +++ b/frappe/core/doctype/user_permission/user_permission.py @@ -96,7 +96,7 @@ def get_applicable_for_doctype_list(doctype, txt, searchfield, start, page_len, linked_doctypes = get_linked_doctypes(doctype, True).keys() linked_doctypes = list(linked_doctypes) linked_doctypes += [doctype] - + if txt: linked_doctypes = [d for d in linked_doctypes if txt in d.lower()] @@ -111,3 +111,13 @@ def get_applicable_for_doctype_list(doctype, txt, searchfield, start, page_len, def get_permitted_documents(doctype): return [d.get('doc') for d in get_user_permissions().get(doctype, []) \ if d.get('doc')] + +@frappe.whitelist() +def clear_user_permissions(user, for_doctype): + frappe.only_for('System Manager') + + total = frappe.db.count('User Permission', filters = dict(user=user, allow=for_doctype)) + if total: + frappe.db.sql('DELETE FROM `tabUser Permission` WHERE user=%s AND allow=%s', (user, for_doctype)) + frappe.clear_cache() + return total diff --git a/frappe/core/doctype/user_permission/user_permission_list.js b/frappe/core/doctype/user_permission/user_permission_list.js new file mode 100644 index 0000000000..39a4648334 --- /dev/null +++ b/frappe/core/doctype/user_permission/user_permission_list.js @@ -0,0 +1,52 @@ +frappe.listview_settings['User Permission'] = { + onload: function(list_view) { + list_view.page.add_menu_item(__("Clear User Permissions"), () => { + const dialog = new frappe.ui.Dialog({ + title: __('Clear User Permissions'), + fields: [ + { + 'fieldname': 'user', + 'label': __('For User'), + 'fieldtype': 'Link', + 'options': 'User', + 'reqd': 1 + }, + { + 'fieldname': 'for_doctype', + 'label': __('For Document Type'), + 'fieldtype': 'Link', + 'options': 'DocType', + 'reqd': 1 + }, + ], + primary_action: (data) => { + // mandatory not filled + if (!data) return; + + frappe.confirm(__('Are you sure?'), () => { + frappe + .xcall('frappe.core.doctype.user_permission.user_permission.clear_user_permissions', data) + .then(data => { + dialog.hide(); + let message = ''; + if (data === 0) { + message = __('No records deleted'); + } else { + message = __('{0} records deleted', [data]); + } + frappe.show_alert({ + message, + indicator: 'green' + }); + list_view.refresh(); + }); + }); + + }, + primary_action_label: __('Clear') + }); + + dialog.show(); + }); + } +}; diff --git a/frappe/public/js/frappe/ui/dialog.js b/frappe/public/js/frappe/ui/dialog.js index cd76db91d4..cfbd765497 100644 --- a/frappe/public/js/frappe/ui/dialog.js +++ b/frappe/public/js/frappe/ui/dialog.js @@ -153,6 +153,7 @@ frappe.ui.Dialog = class Dialog extends frappe.ui.FieldGroup { this.$wrapper.modal("show"); this.primary_action_fulfilled = false; this.is_visible = true; + return this; } hide() { this.$wrapper.modal("hide"); diff --git a/frappe/tests/test_permissions.py b/frappe/tests/test_permissions.py index 9924e92eda..13106697c5 100644 --- a/frappe/tests/test_permissions.py +++ b/frappe/tests/test_permissions.py @@ -14,6 +14,7 @@ from frappe.permissions import (add_user_permission, remove_user_permission, get_valid_perms) from frappe.core.page.permission_manager.permission_manager import update, reset from frappe.test_runner import make_test_records_for_doctype +from frappe.core.doctype.user_permission.user_permission import clear_user_permissions test_dependencies = ['Blogger', 'Blog Post', "User", "Contact", "Salutation"] @@ -427,4 +428,35 @@ class TestPermissions(unittest.TestCase): self.assertTrue(doc.has_permission("delete")) # delete the created doc - frappe.delete_doc('Blog Post', '-test-blog-post-title') \ No newline at end of file + frappe.delete_doc('Blog Post', '-test-blog-post-title') + + def test_clear_user_permissions(self): + current_user = frappe.session.user + frappe.set_user('Administrator') + clear_user_permissions_for_doctype('Blog Category', 'test2@example.com') + clear_user_permissions_for_doctype('Blog Post', 'test2@example.com') + + add_user_permission('Blog Post', '-test-blog-post-1', 'test2@example.com') + add_user_permission('Blog Post', '-test-blog-post-2', 'test2@example.com') + add_user_permission("Blog Category", '_Test Blog Category 1', 'test2@example.com') + + deleted_user_permission_count = clear_user_permissions('test2@example.com', 'Blog Post') + + self.assertEqual(deleted_user_permission_count, 2) + + blog_post_user_permission_count = frappe.db.count('User Permission', filters={ + 'user': 'test2@example.com', + 'allow': 'Blog Post' + }) + + self.assertEqual(blog_post_user_permission_count, 0) + + blog_category_user_permission_count = frappe.db.count('User Permission', filters={ + 'user': 'test2@example.com', + 'allow': 'Blog Category' + }) + + self.assertEqual(blog_category_user_permission_count, 1) + + # reset the user + frappe.set_user(current_user)