From 3db3da9fe9945f996770b82e6dd43e29d954917b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Mart=C3=ADnez?= Date: Wed, 12 Jun 2024 12:19:57 +0200 Subject: [PATCH] [FIX] dms_field: Avoid auto-generate multiple access groups + Refactoring Now the process will be as follows: - The auto-generated access group will be created. - The user will be defined in explicit_user_ids of the group created in the previous step. In the directory created (from the corresponding record) the auto-generated group (for the user to have access) + the access groups that the template had will be used. --- dms_field/README.rst | 2 +- dms_field/__manifest__.py | 1 + dms_field/i18n/dms_field.pot | 47 ++++++++++---- dms_field/i18n/es.po | 2 +- dms_field/i18n/fr.po | 2 +- dms_field/i18n/it.po | 2 +- dms_field/models/dms_access_group.py | 23 ++++++- dms_field/models/dms_field_mixin.py | 25 ++++++++ dms_field/models/dms_field_template.py | 72 ++++++++++++---------- dms_field/static/description/index.html | 2 +- dms_field/tests/test_dms_field.py | 28 +++++++-- dms_field/views/dms_access_group_views.xml | 23 +++++++ 12 files changed, 172 insertions(+), 57 deletions(-) create mode 100644 dms_field/views/dms_access_group_views.xml diff --git a/dms_field/README.rst b/dms_field/README.rst index 0b19ab07e..aaeeba59d 100644 --- a/dms_field/README.rst +++ b/dms_field/README.rst @@ -7,7 +7,7 @@ DMS Field !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:ed7854681f73bbc617938529c1da77fcf81cba2bf46a8ae9387d8f20b360a53b + !! source digest: sha256:32b5522bce9f7a8e1a758183d74db8c1775e5b42d9ceef41a55724d1a4e62681 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png diff --git a/dms_field/__manifest__.py b/dms_field/__manifest__.py index 75947d518..f1a40a814 100644 --- a/dms_field/__manifest__.py +++ b/dms_field/__manifest__.py @@ -11,6 +11,7 @@ "website": "https://github.com/OCA/dms", "depends": ["dms"], "data": [ + "views/dms_access_group_views.xml", "views/dms_directory.xml", "views/dms_field_template_views.xml", "views/dms_storage.xml", diff --git a/dms_field/i18n/dms_field.pot b/dms_field/i18n/dms_field.pot index 4b78efaae..0f87c106e 100644 --- a/dms_field/i18n/dms_field.pot +++ b/dms_field/i18n/dms_field.pot @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 16.0+e\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-04-16 11:00+0000\n" -"PO-Revision-Date: 2024-04-16 11:00+0000\n" +"POT-Creation-Date: 2024-06-13 06:26+0000\n" +"PO-Revision-Date: 2024-06-13 06:26+0000\n" "Last-Translator: \n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -59,7 +59,7 @@ msgstr "" #. odoo-python #: code:addons/dms_field/models/dms_field_template.py:0 #, python-format -msgid "Autogenerate group from %(model)s (%(name)s) #%(id)s" +msgid "Autogenerated group from %(model)s (%(name)s) #%(id)s" msgstr "" #. module: dms_field @@ -161,6 +161,9 @@ msgstr "" #: model:ir.model.fields,field_description:dms_field.field_dms_tag__dms_directory_ids #: model:ir.model.fields,field_description:dms_field.field_fetchmail_server__dms_directory_ids #: model:ir.model.fields,field_description:dms_field.field_format_address_mixin__dms_directory_ids +#: model:ir.model.fields,field_description:dms_field.field_iap_account__dms_directory_ids +#: model:ir.model.fields,field_description:dms_field.field_iap_autocomplete_api__dms_directory_ids +#: model:ir.model.fields,field_description:dms_field.field_iap_enrich_api__dms_directory_ids #: model:ir.model.fields,field_description:dms_field.field_image_mixin__dms_directory_ids #: model:ir.model.fields,field_description:dms_field.field_ir_actions_act_url__dms_directory_ids #: model:ir.model.fields,field_description:dms_field.field_ir_actions_act_window__dms_directory_ids @@ -309,6 +312,19 @@ msgstr "" #: model:ir.model.fields,field_description:dms_field.field_res_users_settings__dms_directory_ids #: model:ir.model.fields,field_description:dms_field.field_res_users_settings_volumes__dms_directory_ids #: model:ir.model.fields,field_description:dms_field.field_reset_view_arch_wizard__dms_directory_ids +#: model:ir.model.fields,field_description:dms_field.field_sms_api__dms_directory_ids +#: model:ir.model.fields,field_description:dms_field.field_sms_cancel__dms_directory_ids +#: model:ir.model.fields,field_description:dms_field.field_sms_composer__dms_directory_ids +#: model:ir.model.fields,field_description:dms_field.field_sms_resend__dms_directory_ids +#: model:ir.model.fields,field_description:dms_field.field_sms_resend_recipient__dms_directory_ids +#: model:ir.model.fields,field_description:dms_field.field_sms_sms__dms_directory_ids +#: model:ir.model.fields,field_description:dms_field.field_sms_template__dms_directory_ids +#: model:ir.model.fields,field_description:dms_field.field_sms_template_preview__dms_directory_ids +#: model:ir.model.fields,field_description:dms_field.field_snailmail_confirm__dms_directory_ids +#: model:ir.model.fields,field_description:dms_field.field_snailmail_letter__dms_directory_ids +#: model:ir.model.fields,field_description:dms_field.field_snailmail_letter_cancel__dms_directory_ids +#: model:ir.model.fields,field_description:dms_field.field_snailmail_letter_format_error__dms_directory_ids +#: model:ir.model.fields,field_description:dms_field.field_snailmail_letter_missing_required_fields__dms_directory_ids #: model:ir.model.fields,field_description:dms_field.field_web_editor_assets__dms_directory_ids #: model:ir.model.fields,field_description:dms_field.field_web_editor_converter_test_sub__dms_directory_ids #: model:ir.model.fields,field_description:dms_field.field_web_tour_tour__dms_directory_ids @@ -324,8 +340,14 @@ msgid "DMS Tree" msgstr "" #. module: dms_field -#. odoo-javascript -#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0 +#: model:ir.model.fields,field_description:dms_field.field_dms_access_group__dms_field_ref +msgid "DMS field reference" +msgstr "" + +#. module: dms_field +#. openerp-web +#: code:addons/dms_field/static/src/js/base/dms_tree_renderer.js:0 +#: code:addons/dms_field/static/src/xml/controls.xml:0 #, python-format msgid "Delete" msgstr "" @@ -477,8 +499,13 @@ msgid "Paste" msgstr "" #. module: dms_field -#. odoo-javascript -#: code:addons/dms_field/static/src/views/dms_list/dms_list_renderer.esm.js:0 +#: model:ir.model,name:dms_field.model_dms_access_group +msgid "Record Access Groups" +msgstr "" + +#. module: dms_field +#. openerp-web +#: code:addons/dms_field/static/src/xml/controls.xml:0 #, python-format msgid "Preview" msgstr "" @@ -533,14 +560,12 @@ msgid "There is already a linked directory created." msgstr "" #. module: dms_field -#. odoo-python -#: code:addons/dms_field/models/dms_field_template.py:0 +#: code:addons/dms_field/models/dms_access_group.py:0 #, python-format -msgid "There is already a template created for this model." +msgid "There is already an access group created for this record." msgstr "" #. module: dms_field -#. odoo-python #: code:addons/dms_field/models/dms_field_template.py:0 #, python-format msgid "There is no template linked to this model" diff --git a/dms_field/i18n/es.po b/dms_field/i18n/es.po index d923916c7..7eff4a61c 100644 --- a/dms_field/i18n/es.po +++ b/dms_field/i18n/es.po @@ -61,7 +61,7 @@ msgstr "Se ha producido un error durante la carga" #. odoo-python #: code:addons/dms_field/models/dms_field_template.py:0 #, python-format -msgid "Autogenerate group from %(model)s (%(name)s) #%(id)s" +msgid "Autogenerated group from %(model)s (%(name)s) #%(id)s" msgstr "Grupo autogenerado desde %(model)s (%(name)s) #%(id)s" #. module: dms_field diff --git a/dms_field/i18n/fr.po b/dms_field/i18n/fr.po index 311e07e0e..19af867a7 100644 --- a/dms_field/i18n/fr.po +++ b/dms_field/i18n/fr.po @@ -50,7 +50,7 @@ msgstr "" #. module: dms_field #: code:addons/dms_field/models/dms_field_template.py:0 #, python-format -msgid "Autogenerate group from %(model)s (%(name)s)" +msgid "Autogenerated group from %(model)s (%(name)s) #%(id)s" msgstr "" #. module: dms_field diff --git a/dms_field/i18n/it.po b/dms_field/i18n/it.po index e072b9c36..754c9ed33 100644 --- a/dms_field/i18n/it.po +++ b/dms_field/i18n/it.po @@ -52,7 +52,7 @@ msgstr "Aggiungi file: " #. module: dms_field #: code:addons/dms_field/models/dms_field_template.py:0 #, python-format -msgid "Autogenerate group from %(model)s (%(name)s)" +msgid "Autogenerated group from %(model)s (%(name)s) #%(id)s" msgstr "" #. module: dms_field diff --git a/dms_field/models/dms_access_group.py b/dms_field/models/dms_access_group.py index 1f6bf77bd..0ba63a20f 100644 --- a/dms_field/models/dms_access_group.py +++ b/dms_field/models/dms_access_group.py @@ -1,15 +1,16 @@ # Copyright 2024 Tecnativa - Víctor Martínez # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -from odoo import api, fields, models +from odoo import _, api, fields, models +from odoo.exceptions import UserError class DmsAccessGroups(models.Model): _inherit = "dms.access.group" - model_ref = fields.Reference( + dms_field_ref = fields.Reference( selection="_selection_reference_value", - string="Default value", + string="DMS field reference", ) @api.model @@ -20,3 +21,19 @@ def _selection_reference_value(self): .search([("transient", "=", False)], order="name asc") ) return [(model.model, model.name) for model in models] + + def _get_item_from_dms_field_ref(self, record): + return self.env["dms.access.group"].search( + [("dms_field_ref", "=", "%s,%s" % (record._name, record.id))] + ) + + @api.constrains("dms_field_ref") + def _check_dms_field_ref(self): + for item in self.filtered("dms_field_ref"): + dms_field_ref = "%s,%s" % (item.dms_field_ref._name, item.dms_field_ref.id) + if self.search( + [("dms_field_ref", "=", dms_field_ref), ("id", "!=", item.id)] + ): + raise UserError( + _("There is already an access group created for this record.") + ) diff --git a/dms_field/models/dms_field_mixin.py b/dms_field/models/dms_field_mixin.py index 0da9d456e..588d54817 100644 --- a/dms_field/models/dms_field_mixin.py +++ b/dms_field/models/dms_field_mixin.py @@ -40,3 +40,28 @@ def create(self, vals_list): for item in result: template.with_context(res_id=item.id).create_dms_directory() return result + + def write(self, vals): + """When modifying a record that has linked directories and changing the + user_id field it is necessary to update the auto-generated access group + (name and explicit_user_ids). + """ + res = super().write(vals) + for item in self.filtered("dms_directory_ids"): + if "user_id" in vals: + template = self.env["dms.field.template"]._get_template_from_model( + item._name + ) + if template: + template._get_autogenerated_group(item) + return res + + def unlink(self): + """When deleting a record, we also delete the linked directories and the + auto-generated access group. + """ + for record in self.filtered("dms_directory_ids"): + group = self.env["dms.access.group"]._get_item_from_dms_field_ref(record) + record.sudo().dms_directory_ids.unlink() + group.sudo().unlink() + return super().unlink() diff --git a/dms_field/models/dms_field_template.py b/dms_field/models/dms_field_template.py index 8a94bd01b..d32294db8 100644 --- a/dms_field/models/dms_field_template.py +++ b/dms_field/models/dms_field_template.py @@ -104,37 +104,43 @@ def _copy_files_from_directory(self, directory, new_directory): for file in directory.file_ids: file.copy({"directory_id": new_directory.id}) - def _set_groups_from_directory(self, directory, record): - """Set groups of directory, if there are already linked groups we use those - to avoid constraint name error.""" - group_model = groups = self.env["dms.access.group"] - groups_ref = group_model.search( - [("model_ref", "=", "%s,%s" % (record._name, record.id))] - ) - if groups_ref: - return groups_ref - for group in directory.group_ids: - group_name = _("Autogenerate group from %(model)s (%(name)s) #%(id)s") % { - "model": record._description, - "name": record.display_name, - "id": record.id, - } - new_group = group.copy( - { - "name": group_name, - "directory_ids": False, - "model_ref": "%s,%s" % (record._name, record.id), - } - ) - # Apply sudo() because the user may not have permissions to access - # ir.model.fields. - user_field = self.sudo().user_field_id - if user_field: - user = record[user_field.name] - if user: - new_group.write({"explicit_user_ids": [(4, user.id)]}) - groups += new_group - return groups + def _prepare_autogenerated_group(self, record): + group_name = _("Autogenerated group from %(model)s (%(name)s) #%(id)s") % { + "model": record._description, + "name": record.display_name, + "id": record.id, + } + vals = { + "name": group_name, + # We need to set all the permissions so that the user can manage their + # documents (directories and files) + "perm_create": True, + "perm_write": True, + "perm_unlink": True, + "dms_field_ref": "%s,%s" % (record._name, record.id), + "explicit_user_ids": [(5, 0)], + } + # Apply sudo() because the user may not have permissions to access + # ir.model.fields. + user_field = self.sudo().user_field_id + if user_field: + user = record[user_field.name] + if user: + vals["explicit_user_ids"] += [(4, user.id)] + return vals + + def _get_autogenerated_group(self, record): + """Get the existing auto-generated group or create a new one. + The permissions of the auto-generated group should be changed + to make sure you have the correct data. + """ + group_model = self.env["dms.access.group"] + group_ref = group_model._get_item_from_dms_field_ref(record) + if group_ref: + group_ref.write(self._prepare_autogenerated_group(record)) + return group_ref + # Create the autogenerated group linked to the record + return group_model.create(self._prepare_autogenerated_group(record)) def _create_child_directories(self, parent, directory): # Create child directories (all leves) + files @@ -151,7 +157,9 @@ def _create_child_directories(self, parent, directory): self._create_child_directories(child, child_directory) def _prepare_directory_vals(self, directory, record): - groups = self._set_groups_from_directory(directory, record) + # Groups of the new directory will be those of the template + auto-generate + groups = directory.group_ids + groups += self._get_autogenerated_group(record) directory_name = self.env["mail.render.mixin"]._render_template( self.directory_format_name, record._name, diff --git a/dms_field/static/description/index.html b/dms_field/static/description/index.html index e4bfc53ba..604715b7d 100644 --- a/dms_field/static/description/index.html +++ b/dms_field/static/description/index.html @@ -367,7 +367,7 @@

DMS Field

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:ed7854681f73bbc617938529c1da77fcf81cba2bf46a8ae9387d8f20b360a53b +!! source digest: sha256:32b5522bce9f7a8e1a758183d74db8c1775e5b42d9ceef41a55724d1a4e62681 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Beta License: LGPL-3 OCA/dms Translate me on Weblate Try me on Runboat

This addon creates a new kind of view and allows to define a folder diff --git a/dms_field/tests/test_dms_field.py b/dms_field/tests/test_dms_field.py index 6d626613f..6d44efef2 100644 --- a/dms_field/tests/test_dms_field.py +++ b/dms_field/tests/test_dms_field.py @@ -3,8 +3,9 @@ # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). from odoo import fields -from odoo.exceptions import ValidationError +from odoo.exceptions import UserError, ValidationError from odoo.tests import TransactionCase, new_test_user +from odoo.tools import mute_logger class TestDmsField(TransactionCase): @@ -100,12 +101,23 @@ def test_js_tree(self): ) ) + def test_dms_access_group_constrains_dms_field_ref(self): + group = self.env["dms.access.group"].create( + { + "name": "Test 1", + "dms_field_ref": "%s,%s" % (self.partner._name, self.partner.id), + } + ) + with self.assertRaises(UserError): + group.copy({"name": "Test 2"}) + def test_template_directory(self): self.assertTrue(self.template.dms_directory_ids) self.assertIn( self.template.group_ids, self.template.dms_directory_ids.group_ids ) + @mute_logger("odoo.models.unlink") def test_creation_process_01(self): self.assertFalse(self.partner.dms_directory_ids) template = self.env["dms.field.template"].with_context( @@ -119,9 +131,13 @@ def test_creation_process_01(self): self.assertFalse(directory_0.parent_id) self.assertTrue(directory_0.is_root_directory) self.assertTrue(directory_0.inherit_group_ids) - self.assertNotIn(self.template.group_ids, directory_0.group_ids) + self.assertIn(self.template.group_ids, directory_0.group_ids) self.assertIn(self.group, directory_0.group_ids.group_ids) - self.assertEqual(directory_0.group_ids.model_ref, self.partner) + self.assertIn(self.partner, directory_0.mapped("group_ids.dms_field_ref")) + group_custom = directory_0.group_ids.filtered("dms_field_ref") + self.assertTrue(group_custom.perm_create) + self.assertTrue(group_custom.perm_write) + self.assertTrue(group_custom.perm_unlink) self.assertIn(self.user_b, directory_0.group_ids.explicit_user_ids) self.assertIn(self.user_a, directory_0.group_ids.users) self.assertIn(self.user_b, directory_0.group_ids.users) @@ -132,9 +148,9 @@ def test_creation_process_01(self): # Remove folder: El grupo de acceso todavía existe old_groups = directory_0.group_ids directory_0.unlink() - model_ref_value = "%s,%s" % (self.partner._name, self.partner.id) + dms_field_ref_value = "%s,%s" % (self.partner._name, self.partner.id) total = self.env["dms.access.group"].search_count( - [("model_ref", "=", model_ref_value)] + [("dms_field_ref", "=", dms_field_ref_value)] ) self.assertEqual(total, 1) # Create directory again (access groups are the same) @@ -158,7 +174,7 @@ def test_creation_process_01_with_parent(self): self.assertEqual(directory_0.parent_id, self.template.parent_directory_id) self.assertFalse(directory_0.is_root_directory) self.assertFalse(directory_0.inherit_group_ids) - self.assertNotIn(self.template.group_ids, directory_0.group_ids) + self.assertIn(self.template.group_ids, directory_0.group_ids) self.assertIn(self.group, directory_0.group_ids.group_ids) self.assertIn(self.user_b, directory_0.group_ids.explicit_user_ids) self.assertIn(self.user_a, directory_0.group_ids.users) diff --git a/dms_field/views/dms_access_group_views.xml b/dms_field/views/dms_access_group_views.xml new file mode 100644 index 000000000..f558cf874 --- /dev/null +++ b/dms_field/views/dms_access_group_views.xml @@ -0,0 +1,23 @@ + + + + dms_access_groups.tree + dms.access.group + + + + + + + + + dms_access.group.form + dms.access.group + + + + + + + +