diff --git a/base_group_backend/README.rst b/base_group_backend/README.rst new file mode 100644 index 000000000..58c151ab1 --- /dev/null +++ b/base_group_backend/README.rst @@ -0,0 +1,181 @@ +============= +Group backend +============= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:94aa0fca553bd76339b493d1406d1fad68c724126ff95cfecea7d30228bd6b90 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png + :target: https://odoo-community.org/page/development-status + :alt: Alpha +.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--backend-lightgray.png?logo=github + :target: https://github.com/OCA/server-backend/tree/18.0/base_group_backend + :alt: OCA/server-backend +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/server-backend-18-0/server-backend-18-0-base_group_backend + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/server-backend&target_branch=18.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module adds two "Backend User" groups (``group_backend`` and +``group_backend_ui_users``) with restricted access to odoo backend only +(``/web``), with less and more controlled access than the native +"Internal User" group. + + The problem with the "Internal User" group (``base.group_user``) is + that it can be used by any new module added to your project, so you + don't control clearly this group's accesses. + +The UI access is provided only for ``group_backend_ui_users`` : + +- minimal default access rules to access the user's own data: + + - users and partners + - mail activity, notification and channel + - presence + +- minimal default menu to restrict the available ones: + + - notification + - activities + +Here is an example where a user from ``group_backend_ui_users`` can only +access and use the Dummy App. No other application is available to this +user (you may define your own application instead of the Dummy one). + +|image1| + +We suggest to use this module with its companion ``base_user_role``. + +Limitations +----------- + +At the time of writing, Odoo uses ``user.share == False`` and +``user.has_group("base.group_user") == True`` to give the backend access +to ``user``. + +So technically, the module does 2 things : + +- It sets the ``share`` parameter to ``False`` for ``group_backend`` + users. +- It hijacks the ``has_group`` method of res.users by returning + ``True`` for ``group_backend`` users when the requested group is + ``base.group_user`` + +This avoids to write a lot of overwrite in different controllers from +different modules ('portal', 'web', 'base', 'website') with hard coded +statements that check if user is part of the ``base.group_user`` or +``share == False`` group. + +.. |image1| image:: https://raw.githubusercontent.com/OCA/server-backend/18.0/base_group_backend/static/description/dummy_app.png + +.. IMPORTANT:: + This is an alpha version, the data model and design can change at any time without warning. + Only for development or testing purpose, do not use in production. + `More details on development status `_ + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +To allow a user from the ``group_backend_ui_users`` group to interact +with a specific model you can either add an access rules to this model +for ``group_backend_ui_users`` or you can add ``group_backend_ui_users`` +to the ``implied_ids`` of a new specific group. + +The Backend groups are from the "User types" category +(``base.module_category_user_type``), the same category as "Internal +User" (``base.group_user``), "Portal" (``base.group_portal``) or Public +(``base.group_public``). Be aware that a user can only belongs to **one +group of this category**. + +Usage +===== + +To use this module, add a user to the group "Backend user" or "Backend +UI user" through the user's form page. + +|image1| + +If you created a specific group with ``group_backend`` or +``group_backend_ui_users`` in its ``implied_ids``, you need to go +through the group's form page in order to add the user to this specific +group, because it won't be displayed on the user's form page (a specific +group with its own category is displayed on user's form page only if the +group inherits the "Internal user" group). + +This module also **restricts the root menus** displayed to Backend +users, so be sure to explicitly add your Backend group to all the +necessary root menus for these users. + +.. |image1| image:: https://raw.githubusercontent.com/OCA/server-backend/18.0/base_group_backend/static/description/backend_ui.png + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Pierre Verkest + +Contributors +------------ + +- Pierre Verkest +- François Poizat + +Do not contact contributors directly about support or help with +technical issues. + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +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. + +.. |maintainer-FranzPoize| image:: https://github.com/FranzPoize.png?size=40px + :target: https://github.com/FranzPoize + :alt: FranzPoize +.. |maintainer-bealdav| image:: https://github.com/bealdav.png?size=40px + :target: https://github.com/bealdav + :alt: bealdav + +Current `maintainers `__: + +|maintainer-FranzPoize| |maintainer-bealdav| + +This module is part of the `OCA/server-backend `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/base_group_backend/__init__.py b/base_group_backend/__init__.py new file mode 100644 index 000000000..fc95f8e72 --- /dev/null +++ b/base_group_backend/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import demo diff --git a/base_group_backend/__manifest__.py b/base_group_backend/__manifest__.py new file mode 100644 index 000000000..885347af5 --- /dev/null +++ b/base_group_backend/__manifest__.py @@ -0,0 +1,29 @@ +# Copyright 2021 Pierre Verkest +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +{ + "name": "Group backend", + "version": "18.0.1.0.0", + "development_status": "Alpha", + "category": "Tools", + "author": "Pierre Verkest, Odoo Community Association (OCA)", + "license": "LGPL-3", + "website": "https://github.com/OCA/server-backend", + "depends": [ + "base", + "mail", + "calendar", + ], + "maintainers": ["FranzPoize", "bealdav"], + "demo": [ + "demo/test-model.xml", + "demo/ir.model.access.csv", + "demo/backend_dummy_model.xml", + "demo/res_partners.xml", + "demo/res_users.xml", + ], + "data": [ + "data/res_groups.xml", + "security/ir.model.access.csv", + ], + "installable": True, +} diff --git a/base_group_backend/data/res_groups.xml b/base_group_backend/data/res_groups.xml new file mode 100644 index 000000000..b1f644693 --- /dev/null +++ b/base_group_backend/data/res_groups.xml @@ -0,0 +1,42 @@ + + + Backend user + + + This group is used to gives user backend access. + + While users in `base.group_user` gets a lot of default access + which makes hard to define properly records/rules/menu access. + + So for maintainability you shouldn't linked any access right, rules, + menu, and so on to this group directly. + + The only intent of this groups is to be able to get a session + to Odoo backend (`/web`). + + + + + Backend UI user + + + This group is used to gives user basic ui access. + + + + diff --git a/base_group_backend/demo/__init__.py b/base_group_backend/demo/__init__.py new file mode 100644 index 000000000..87682b5ef --- /dev/null +++ b/base_group_backend/demo/__init__.py @@ -0,0 +1,4 @@ +from odoo.tools import config + +if not config["without_demo"]: + from . import backend_dummy_model diff --git a/base_group_backend/demo/backend_dummy_model.py b/base_group_backend/demo/backend_dummy_model.py new file mode 100644 index 000000000..649f22418 --- /dev/null +++ b/base_group_backend/demo/backend_dummy_model.py @@ -0,0 +1,15 @@ +from odoo import fields, models + + +class BackendDummyModel(models.Model): + _name = "backend.dummy.model" + _description = "Backend Dummy Model demo" + + my_value = fields.Char(name="Value", required=True) + my_other_value = fields.Char(name="Other value", required=True) + date_start = fields.Datetime( + name="Date start", required=True, default=fields.Datetime.now + ) + date_stop = fields.Datetime( + name="Date stop", required=True, default=fields.Datetime.now + ) diff --git a/base_group_backend/demo/backend_dummy_model.xml b/base_group_backend/demo/backend_dummy_model.xml new file mode 100644 index 000000000..ff412d0c2 --- /dev/null +++ b/base_group_backend/demo/backend_dummy_model.xml @@ -0,0 +1,53 @@ + + + + Backend dummy list view + backend.dummy.model + + + + + + + + + + Dummies + ir.actions.act_window + backend.dummy.model + list,form,kanban,calendar,pivot,graph,activity + + + + + + + + + + diff --git a/base_group_backend/demo/ir.model.access.csv b/base_group_backend/demo/ir.model.access.csv new file mode 100644 index 000000000..6c353bcb6 --- /dev/null +++ b/base_group_backend/demo/ir.model.access.csv @@ -0,0 +1,3 @@ +"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" +"backend_dummy_models","backend dummy.model","model_backend_dummy_model",group_backend_ui_users,1,0,0,0 +"backend_dummy_models_user_grp","backend dummy.model user grp","model_backend_dummy_model",base.group_user,1,0,0,0 diff --git a/base_group_backend/demo/res_partners.xml b/base_group_backend/demo/res_partners.xml new file mode 100644 index 000000000..32b455809 --- /dev/null +++ b/base_group_backend/demo/res_partners.xml @@ -0,0 +1,12 @@ + + + + Demo partner backend + + + Demo partner backend 1 + + + Demo partner backend 2 + + diff --git a/base_group_backend/demo/res_users.xml b/base_group_backend/demo/res_users.xml new file mode 100644 index 000000000..37baa44a6 --- /dev/null +++ b/base_group_backend/demo/res_users.xml @@ -0,0 +1,21 @@ + + + + demo backend user + + + + + demo backend user 1 + + + + + demo backend user 2 + + + + diff --git a/base_group_backend/demo/test-model.xml b/base_group_backend/demo/test-model.xml new file mode 100644 index 000000000..3ced409a7 --- /dev/null +++ b/base_group_backend/demo/test-model.xml @@ -0,0 +1,7 @@ + + + + hello + hello + + diff --git a/base_group_backend/i18n/base_group_backend.pot b/base_group_backend/i18n/base_group_backend.pot new file mode 100644 index 000000000..1d5b89f94 --- /dev/null +++ b/base_group_backend/i18n/base_group_backend.pot @@ -0,0 +1,145 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * base_group_backend +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: base_group_backend +#: model:res.groups,comment:base_group_backend.base_group_backend +msgid "" +"\n" +" This group is used to gives user backend access.\n" +"\n" +" While users in `base.group_user` gets a lot of default access\n" +" which makes hard to define properly records/rules/menu access.\n" +"\n" +" So for maintainability you shouldn't linked any access right, rules,\n" +" menu, and so on to this group directly.\n" +"\n" +" The only intent of this groups is to be able to get a session\n" +" to Odoo backend (`/web`).\n" +" " +msgstr "" + +#. module: base_group_backend +#: model:res.groups,comment:base_group_backend.group_backend_ui_users +msgid "" +"\n" +" This group is used to gives user basic ui access.\n" +" " +msgstr "" + +#. module: base_group_backend +#: model:ir.model,name:base_group_backend.model_backend_dummy_model +msgid "Backend Dummy Model demo" +msgstr "" + +#. module: base_group_backend +#: model:res.groups,name:base_group_backend.group_backend_ui_users +msgid "Backend UI user" +msgstr "" + +#. module: base_group_backend +#: model:res.groups,name:base_group_backend.base_group_backend +msgid "Backend user" +msgstr "" + +#. module: base_group_backend +#: model:ir.model.fields,field_description:base_group_backend.field_backend_dummy_model__create_uid +msgid "Created by" +msgstr "" + +#. module: base_group_backend +#: model:ir.model.fields,field_description:base_group_backend.field_backend_dummy_model__create_date +msgid "Created on" +msgstr "" + +#. module: base_group_backend +#: model:ir.model.fields,field_description:base_group_backend.field_backend_dummy_model__date_start +msgid "Date Start" +msgstr "" + +#. module: base_group_backend +#: model:ir.model.fields,field_description:base_group_backend.field_backend_dummy_model__date_stop +msgid "Date Stop" +msgstr "" + +#. module: base_group_backend +#: model:ir.model.fields,field_description:base_group_backend.field_backend_dummy_model__display_name +msgid "Display Name" +msgstr "" + +#. module: base_group_backend +#: model:ir.actions.act_window,name:base_group_backend.action_dummy_list +msgid "Dummies" +msgstr "" + +#. module: base_group_backend +#: model:ir.ui.menu,name:base_group_backend.menu_dummy_menu +#: model:ir.ui.menu,name:base_group_backend.menu_dummy_root +msgid "Dummy" +msgstr "" + +#. module: base_group_backend +#: model:ir.ui.menu,name:base_group_backend.menu_dummy_list +msgid "Dummy list" +msgstr "" + +#. module: base_group_backend +#: model:ir.ui.menu,name:base_group_backend.menu_dummy_list_no_group +msgid "Dummy list No group" +msgstr "" + +#. module: base_group_backend +#: model:ir.model.fields,field_description:base_group_backend.field_backend_dummy_model__id +msgid "ID" +msgstr "" + +#. module: base_group_backend +#: model:ir.model.fields,field_description:base_group_backend.field_backend_dummy_model____last_update +msgid "Last Modified on" +msgstr "" + +#. module: base_group_backend +#: model:ir.model.fields,field_description:base_group_backend.field_backend_dummy_model__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: base_group_backend +#: model:ir.model.fields,field_description:base_group_backend.field_backend_dummy_model__write_date +msgid "Last Updated on" +msgstr "" + +#. module: base_group_backend +#: model:ir.model,name:base_group_backend.model_ir_ui_menu +msgid "Menu" +msgstr "" + +#. module: base_group_backend +#: model:ir.model.fields,field_description:base_group_backend.field_backend_dummy_model__my_other_value +msgid "My Other Value" +msgstr "" + +#. module: base_group_backend +#: model:ir.model.fields,field_description:base_group_backend.field_backend_dummy_model__my_value +msgid "My Value" +msgstr "" + +#. module: base_group_backend +#: model:ir.ui.menu,name:base_group_backend.menu_root_no_group +msgid "No Group" +msgstr "" + +#. module: base_group_backend +#: model:ir.model,name:base_group_backend.model_res_users +msgid "User" +msgstr "" diff --git a/base_group_backend/i18n/it.po b/base_group_backend/i18n/it.po new file mode 100644 index 000000000..00a65592a --- /dev/null +++ b/base_group_backend/i18n/it.po @@ -0,0 +1,170 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * base_group_backend +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2025-01-22 12:06+0000\n" +"Last-Translator: mymage \n" +"Language-Team: none\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 5.6.2\n" + +#. module: base_group_backend +#: model:res.groups,comment:base_group_backend.base_group_backend +msgid "" +"\n" +" This group is used to gives user backend access.\n" +"\n" +" While users in `base.group_user` gets a lot of default access\n" +" which makes hard to define properly records/rules/menu access.\n" +"\n" +" So for maintainability you shouldn't linked any access right, " +"rules,\n" +" menu, and so on to this group directly.\n" +"\n" +" The only intent of this groups is to be able to get a session\n" +" to Odoo backend (`/web`).\n" +" " +msgstr "" +"\n" +" Questo gruppo viene utilizzato per fornire all'utente l'accesso " +"al backend.\n" +"\n" +" Mentre gli utenti in `base.group_user` ottengono molti accessi " +"predefiniti\n" +" il che rende difficile definire correttamente l'accesso a " +"record/regole/menu.\n" +"\n" +" Quindi per la manutenibilità non si dovrebbe collegare alcun " +"diritto di accesso, regole,\n" +" menu e così via direttamente a questo gruppo.\n" +"\n" +" L'unico intento di questi gruppi è riuscire ad ottenere una " +"sessione\n" +" nel backend di Odoo (`/web`).\n" +" " + +#. module: base_group_backend +#: model:res.groups,comment:base_group_backend.group_backend_ui_users +msgid "" +"\n" +" This group is used to gives user basic ui access.\n" +" " +msgstr "" +"\n" +" Questo gruppo viene utilizzato per fornire all'utente l'accesso " +"di base all'interfaccia utente.\n" +" " + +#. module: base_group_backend +#: model:ir.model,name:base_group_backend.model_backend_dummy_model +msgid "Backend Dummy Model demo" +msgstr "Demo modello semplice backend" + +#. module: base_group_backend +#: model:res.groups,name:base_group_backend.group_backend_ui_users +msgid "Backend UI user" +msgstr "Utente UI backend" + +#. module: base_group_backend +#: model:res.groups,name:base_group_backend.base_group_backend +msgid "Backend user" +msgstr "Utente backend" + +#. module: base_group_backend +#: model:ir.model.fields,field_description:base_group_backend.field_backend_dummy_model__create_uid +msgid "Created by" +msgstr "Creato da" + +#. module: base_group_backend +#: model:ir.model.fields,field_description:base_group_backend.field_backend_dummy_model__create_date +msgid "Created on" +msgstr "Creato il" + +#. module: base_group_backend +#: model:ir.model.fields,field_description:base_group_backend.field_backend_dummy_model__date_start +msgid "Date Start" +msgstr "Data inizio" + +#. module: base_group_backend +#: model:ir.model.fields,field_description:base_group_backend.field_backend_dummy_model__date_stop +msgid "Date Stop" +msgstr "Data fine" + +#. module: base_group_backend +#: model:ir.model.fields,field_description:base_group_backend.field_backend_dummy_model__display_name +msgid "Display Name" +msgstr "Nome visualizzato" + +#. module: base_group_backend +#: model:ir.actions.act_window,name:base_group_backend.action_dummy_list +msgid "Dummies" +msgstr "Principianti" + +#. module: base_group_backend +#: model:ir.ui.menu,name:base_group_backend.menu_dummy_menu +#: model:ir.ui.menu,name:base_group_backend.menu_dummy_root +msgid "Dummy" +msgstr "Principiante" + +#. module: base_group_backend +#: model:ir.ui.menu,name:base_group_backend.menu_dummy_list +msgid "Dummy list" +msgstr "Elenco principiante" + +#. module: base_group_backend +#: model:ir.ui.menu,name:base_group_backend.menu_dummy_list_no_group +msgid "Dummy list No group" +msgstr "Lista fittizia senza gruppo" + +#. module: base_group_backend +#: model:ir.model.fields,field_description:base_group_backend.field_backend_dummy_model__id +msgid "ID" +msgstr "ID" + +#. module: base_group_backend +#: model:ir.model.fields,field_description:base_group_backend.field_backend_dummy_model____last_update +msgid "Last Modified on" +msgstr "Ultima modifica il" + +#. module: base_group_backend +#: model:ir.model.fields,field_description:base_group_backend.field_backend_dummy_model__write_uid +msgid "Last Updated by" +msgstr "Ultimo aggiornamento di" + +#. module: base_group_backend +#: model:ir.model.fields,field_description:base_group_backend.field_backend_dummy_model__write_date +msgid "Last Updated on" +msgstr "Ultimo aggiornamento il" + +#. module: base_group_backend +#: model:ir.model,name:base_group_backend.model_ir_ui_menu +msgid "Menu" +msgstr "Menu" + +#. module: base_group_backend +#: model:ir.model.fields,field_description:base_group_backend.field_backend_dummy_model__my_other_value +msgid "My Other Value" +msgstr "Altro valore mio" + +#. module: base_group_backend +#: model:ir.model.fields,field_description:base_group_backend.field_backend_dummy_model__my_value +msgid "My Value" +msgstr "Mio valore" + +#. module: base_group_backend +#: model:ir.ui.menu,name:base_group_backend.menu_root_no_group +msgid "No Group" +msgstr "Nessun gruppo" + +#. module: base_group_backend +#: model:ir.model,name:base_group_backend.model_res_users +msgid "User" +msgstr "Utente" diff --git a/base_group_backend/models/__init__.py b/base_group_backend/models/__init__.py new file mode 100644 index 000000000..716b818c8 --- /dev/null +++ b/base_group_backend/models/__init__.py @@ -0,0 +1,2 @@ +from . import res_users +from . import ir_ui_menu diff --git a/base_group_backend/models/ir_ui_menu.py b/base_group_backend/models/ir_ui_menu.py new file mode 100644 index 000000000..db449af5c --- /dev/null +++ b/base_group_backend/models/ir_ui_menu.py @@ -0,0 +1,22 @@ +# Copyright 2024 Akretion +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import api, models + + +class IrUiMenu(models.Model): + _inherit = "ir.ui.menu" + + @api.model + @api.returns("self") + def get_user_roots(self): + """Avoid to display root menus with no defined groups_id to Backend UI Users + like 'spreadsheet_dashboard.spreadsheet_dashboard_menu_root' + or 'base.menu_management'. + + """ + res = super().get_user_roots() + if self.env.user.has_group("base_group_backend.group_backend_ui_users"): + return res.filtered(lambda m: m.groups_id) + else: + return res diff --git a/base_group_backend/models/res_users.py b/base_group_backend/models/res_users.py new file mode 100644 index 000000000..99fcb2d57 --- /dev/null +++ b/base_group_backend/models/res_users.py @@ -0,0 +1,50 @@ +import logging + +from odoo import api, models + +_logger = logging.getLogger(__name__) + + +class Users(models.Model): + _inherit = "res.users" + + @api.model + def _has_group(self, group_ext_id): + """While ensuring a user is part of `base.group_user` this code will + try if user is in the `base_group_backend.group_backend` group to let access + to the odoo backend. + + This code avoid to overwrite a lot of places in controllers from + different modules ('portal', 'web', 'base') with hardcoded statement + that check if user is part of `base.group_user` group. + + As far `base.group_user` have a lot of default permission this + makes hard to maintain proper access right according your business. + """ + res = super()._has_group(group_ext_id) + if not res and (group_ext_id == "base.group_user"): + has_base_group_backend = super()._has_group( + "base_group_backend.base_group_backend" + ) or super()._has_group("base_group_backend.group_backend_ui_users") + if has_base_group_backend: + _logger.debug( + "Forcing has_group to return True" + + " for base_group_backend and base_group_backend_ui_users" + ) + return has_base_group_backend + return res + + @api.depends("groups_id") + def _compute_share(self): + res = super()._compute_share() + backend_user_group_id = self.env["ir.model.data"]._xmlid_to_res_id( + "base_group_backend.base_group_backend" + ) + backend_ui_user_group_id = self.env["ir.model.data"]._xmlid_to_res_id( + "base_group_backend.group_backend_ui_users" + ) + internal_users = self.filtered_domain( + [("groups_id", "in", [backend_user_group_id, backend_ui_user_group_id])] + ) + internal_users.share = False + return res diff --git a/base_group_backend/pyproject.toml b/base_group_backend/pyproject.toml new file mode 100644 index 000000000..4231d0ccc --- /dev/null +++ b/base_group_backend/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/base_group_backend/readme/CONFIGURE.md b/base_group_backend/readme/CONFIGURE.md new file mode 100644 index 000000000..03527fbc0 --- /dev/null +++ b/base_group_backend/readme/CONFIGURE.md @@ -0,0 +1,10 @@ +To allow a user from the `group_backend_ui_users` group to interact with +a specific model you can either add an access rules to this model for +`group_backend_ui_users` or you can add `group_backend_ui_users` to the +`implied_ids` of a new specific group. + +The Backend groups are from the "User types" category +(`base.module_category_user_type`), the same category as "Internal User" +(`base.group_user`), "Portal" (`base.group_portal`) or Public +(`base.group_public`). Be aware that a user can only belongs to **one +group of this category**. diff --git a/base_group_backend/readme/CONTRIBUTORS.md b/base_group_backend/readme/CONTRIBUTORS.md new file mode 100644 index 000000000..bde928132 --- /dev/null +++ b/base_group_backend/readme/CONTRIBUTORS.md @@ -0,0 +1,5 @@ +- Pierre Verkest \<\> +- François Poizat \<\> + +Do not contact contributors directly about support or help with +technical issues. diff --git a/base_group_backend/readme/DESCRIPTION.md b/base_group_backend/readme/DESCRIPTION.md new file mode 100644 index 000000000..7176773fb --- /dev/null +++ b/base_group_backend/readme/DESCRIPTION.md @@ -0,0 +1,44 @@ +This module adds two "Backend User" groups (`group_backend` and +`group_backend_ui_users`) with restricted access to odoo backend only +(`/web`), with less and more controlled access than the native "Internal +User" group. + +> The problem with the "Internal User" group (`base.group_user`) is that +> it can be used by any new module added to your project, so you don't +> control clearly this group's accesses. + +The UI access is provided only for `group_backend_ui_users` : + +- minimal default access rules to access the user's own data: + - users and partners + - mail activity, notification and channel + - presence + +- minimal default menu to restrict the available ones: + - notification + - activities + +Here is an example where a user from `group_backend_ui_users` can only +access and use the Dummy App. No other application is available to this +user (you may define your own application instead of the Dummy one). + +![](../static/description/dummy_app.png) + +We suggest to use this module with its companion `base_user_role`. + +## Limitations + +At the time of writing, Odoo uses `user.share == False` and +`user.has_group("base.group_user") == True` to give the backend access +to `user`. + +So technically, the module does 2 things : + +- It sets the `share` parameter to `False` for `group_backend` users. +- It hijacks the `has_group` method of res.users by returning `True` for + `group_backend` users when the requested group is `base.group_user` + +This avoids to write a lot of overwrite in different controllers from +different modules ('portal', 'web', 'base', 'website') with hard coded +statements that check if user is part of the `base.group_user` or +`share == False` group. diff --git a/base_group_backend/readme/USAGE.md b/base_group_backend/readme/USAGE.md new file mode 100644 index 000000000..a862a104a --- /dev/null +++ b/base_group_backend/readme/USAGE.md @@ -0,0 +1,15 @@ +To use this module, add a user to the group "Backend user" or "Backend +UI user" through the user's form page. + +![](../static/description/backend_ui.png) + +If you created a specific group with `group_backend` or +`group_backend_ui_users` in its `implied_ids`, you need to go through +the group's form page in order to add the user to this specific group, +because it won't be displayed on the user's form page (a specific group +with its own category is displayed on user's form page only if the group +inherits the "Internal user" group). + +This module also **restricts the root menus** displayed to Backend +users, so be sure to explicitly add your Backend group to all the +necessary root menus for these users. diff --git a/base_group_backend/security/ir.model.access.csv b/base_group_backend/security/ir.model.access.csv new file mode 100644 index 000000000..e64c17787 --- /dev/null +++ b/base_group_backend/security/ir.model.access.csv @@ -0,0 +1,37 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +backend_ui_users_ir_default,backend_ui_users_ir_default,base.model_ir_default,group_backend_ui_users,1,1,1,1 +backend_ui_users_ir_filters,backend_ui_users_ir_filters,base.model_ir_filters,group_backend_ui_users,1,1,1,1 +backend_ui_users_ir_model,backend_ui_users_ir_model,base.model_ir_model,group_backend_ui_users,1,0,0,0 +backend_ui_users_ir_model_fields,backend_ui_users_ir_model_fields,base.model_ir_model_fields,group_backend_ui_users,1,0,0,0 +backend_ui_users_ir_model_data,backend_ui_users_ir_model_data,base.model_ir_model_data,group_backend_ui_users,1,0,1,0 +backend_ui_users_ir_model_fields_selection,backend_ui_users_ir_model_fields_selection,base.model_ir_model_fields_selection,group_backend_ui_users,1,0,0,0 +backend_ui_users_ir_sequence,backend_ui_users_ir_sequence,base.model_ir_sequence,group_backend_ui_users,1,0,0,0 +backend_ui_users_ir_sequence_date_range,backend_ui_users_ir_sequence_date_range,base.model_ir_sequence_date_range,group_backend_ui_users,1,0,0,0 +backend_ui_users_ir_ui_menu,backend_ui_users_ir_ui_menu,base.model_ir_ui_menu,group_backend_ui_users,1,0,0,0 +backend_ui_users_ir_attachment,backend_ui_users_ir_attachment,base.model_ir_attachment,group_backend_ui_users,1,0,1,0 +backend_ui_users_res_partner,backend_ui_users_res_partner,base.model_res_partner,group_backend_ui_users,1,0,0,0 +backend_ui_users_bus_presence,backend_ui_users_bus_presence,bus.model_bus_presence,group_backend_ui_users,1,1,1,1 +backend_ui_users_discuss_channel_member_public,backend_ui_users_discuss_channel_member,mail.model_discuss_channel_member,group_backend_ui_users,1,1,1,0 +backend_ui_users_discuss_channel_public,backend_ui_users_discuss_channel_member,mail.model_discuss_channel,group_backend_ui_users,1,1,1,0 +backend_ui_users_mail_activity,backend_ui_users_mail_activity,mail.model_mail_activity,group_backend_ui_users,1,1,1,1 +backend_ui_users_mail_activity_type,backend_ui_users_mail_activity_type,mail.model_mail_activity_type,group_backend_ui_users,1,0,0,0 +backend_ui_users_mail_followers,backend_ui_users_mail_followers,mail.model_mail_followers,group_backend_ui_users,1,0,0,0 +backend_ui_users_mail_mail,backend_ui_users_mail_mail,mail.model_mail_mail,group_backend_ui_users,0,0,0,0 +backend_ui_users_mail_compose_message,backend_ui_users_mail_compose_message,mail.model_mail_compose_message,group_backend_ui_users,1,1,1,0 +backend_ui_users_mail_wizard_invite,backend_ui_users_mail_wizard_invite,mail.model_mail_wizard_invite,group_backend_ui_users,1,1,1,0 +backend_ui_users_mail_template,backend_ui_users_mail_template,mail.model_mail_template,group_backend_ui_users,1,0,0,0 +backend_ui_users_mail_template_preview,backend_ui_users_mail_template_preview,mail.model_mail_template_preview,group_backend_ui_users,1,0,0,0 +backend_ui_users_mail_message,backend_ui_users_mail_message,mail.model_mail_message,group_backend_ui_users,1,1,1,0 +backend_ui_users_mail_resend_message,backend_ui_users_mail_resend_message,mail.model_mail_resend_message,group_backend_ui_users,1,1,1,0 +backend_ui_users_mail_notification,backend_ui_users_mail_notification,mail.model_mail_notification,group_backend_ui_users,1,1,1,1 +backend_ui_users_mail_alias,backend_ui_users_mail_alias,mail.model_mail_alias,group_backend_ui_users,1,0,0,0 +backend_ui_users_mail_guest,backend_ui_users_mail_guest,mail.model_mail_guest,group_backend_ui_users,1,0,0,0 +backend_ui_users_res_groups,backend_ui_users_res_groups,base.model_res_groups,group_backend_ui_users,1,0,0,0 +backend_ui_users_res_partner_category,backend_ui_users_res_partner_category,base.model_res_partner_category,group_backend_ui_users,1,0,0,0 +backend_ui_users_res_partner_industry,backend_ui_users_res_partner_industry,base.model_res_partner_industry,group_backend_ui_users,1,0,0,0 +backend_ui_users_res_users_identitycheck,backend_ui_users_res_users_identitycheck,base.model_res_users_identitycheck,group_backend_ui_users,1,1,1,0 +backend_ui_users_res_public,res_users all,model_res_users,group_backend_ui_users,1,0,0,0 +backend_ui_users_res_bank,backend_ui_users_res_bank,base.model_res_bank,group_backend_ui_users,1,0,0,0 +backend_ui_users_res_partner_bank,backend_ui_users_res_partner_bank,base.model_res_partner_bank,group_backend_ui_users,1,0,0,0 +backend_ui_users_res_calendar_event,backend_ui_users_res_calendar_event,calendar.model_calendar_event,group_backend_ui_users,1,0,0,0 +backend_ui_users_res_calendar_attendee,backend_ui_users_res_calendar_attendee,calendar.model_calendar_attendee,group_backend_ui_users,1,0,0,0 diff --git a/base_group_backend/static/description/backend_ui.png b/base_group_backend/static/description/backend_ui.png new file mode 100644 index 000000000..f0c6a0b8f Binary files /dev/null and b/base_group_backend/static/description/backend_ui.png differ diff --git a/base_group_backend/static/description/dummy_app.png b/base_group_backend/static/description/dummy_app.png new file mode 100644 index 000000000..70bd4571a Binary files /dev/null and b/base_group_backend/static/description/dummy_app.png differ diff --git a/base_group_backend/static/description/icon.png b/base_group_backend/static/description/icon.png new file mode 100644 index 000000000..3a0328b51 Binary files /dev/null and b/base_group_backend/static/description/icon.png differ diff --git a/base_group_backend/static/description/index.html b/base_group_backend/static/description/index.html new file mode 100644 index 000000000..e9e9832ee --- /dev/null +++ b/base_group_backend/static/description/index.html @@ -0,0 +1,483 @@ + + + + + +Group backend + + + +
+

Group backend

+ + +

Alpha License: LGPL-3 OCA/server-backend Translate me on Weblate Try me on Runboat

+

This module adds two “Backend User” groups (group_backend and group_backend_ui_users) with restricted access to odoo backend only (/web), with less and more controlled access than the native “Internal User” group.

+
+The problem with the “Internal User” group (base.group_user) is that it can be used by any new module added to your project, so you don’t control clearly this group’s accesses.
+

The UI access is provided only for group_backend_ui_users :

+
    +
  • +
    minimal default access rules to access the user’s own data:
    +
      +
    • users and partners
    • +
    • mail activity, notification and channel
    • +
    • presence
    • +
    +
    +
    +
  • +
  • +
    minimal default menu to restrict the available ones:
    +
      +
    • notification
    • +
    • activities
    • +
    +
    +
    +
  • +
+

Here is an example where a user from group_backend_ui_users can only access and use the Dummy App. No other application is available to this user (you may define your own application instead of the Dummy one).

+
+Dummy app for demo +
+

We suggest to use this module with its companion base_user_role.

+
+

Limitations

+

At the time of writing, Odoo uses user.share == False and user.has_group("base.group_user") == True to give the backend access to user.

+

So technically, the module does 2 things :

+
    +
  • It sets the share parameter to False for group_backend users.
  • +
  • It hijacks the has_group method of res.users by returning True for group_backend users when the requested group is base.group_user
  • +
+

This avoids to write a lot of overwrite in different controllers from different modules (‘portal’, ‘web’, ‘base’, ‘website’) with hard coded statements that check if user is part of the base.group_user or share == False group.

+
+

Important

+

This is an alpha version, the data model and design can change at any time without warning. +Only for development or testing purpose, do not use in production. +More details on development status

+
+

Table of contents

+ +
+

Configuration

+

To allow a user from the group_backend_ui_users group to interact with a specific model you can either add an access rules to this model for group_backend_ui_users or you can add group_backend_ui_users to the implied_ids of a new specific group.

+

The Backend groups are from the “User types” category (base.module_category_user_type), the same category as “Internal User” (base.group_user), “Portal” (base.group_portal) or Public (base.group_public). Be aware that a user can only belongs to one group of this category.

+
+
+

Usage

+

To use this module, add a user to the group “Backend user” or “Backend UI user” through the user’s form page.

+
+Backend UI user +
+

If you created a specific group with group_backend or group_backend_ui_users in its implied_ids, you need to go through the group’s form page in order to add the user to this specific group, because it won’t be displayed on the user’s form page (a specific group with its own category is displayed on user’s form page only if the group inherits the “Internal user” group).

+

This module also restricts the root menus displayed to Backend users, so be sure to explicitly add your Backend group to all the necessary root menus for these users.

+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+ +
+
+

Authors

+
    +
  • Pierre Verkest
  • +
+
+
+

Contributors

+ +

Do not contact contributors directly about support or help with technical issues.

+
+
+

Maintainers

+

This module is maintained by the OCA.

+ +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.

+

Current maintainers:

+

FranzPoize bealdav

+

This module is part of the OCA/server-backend project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+ + diff --git a/base_group_backend/tests/__init__.py b/base_group_backend/tests/__init__.py new file mode 100644 index 000000000..d9b96c4fa --- /dev/null +++ b/base_group_backend/tests/__init__.py @@ -0,0 +1 @@ +from . import test_module diff --git a/base_group_backend/tests/test_module.py b/base_group_backend/tests/test_module.py new file mode 100644 index 000000000..9c78b297e --- /dev/null +++ b/base_group_backend/tests/test_module.py @@ -0,0 +1,42 @@ +from odoo import Command +from odoo.tests.common import TransactionCase + + +class TestResUsers(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.base_group_backend = cls.env.ref("base_group_backend.base_group_backend") + cls.internal_user = cls.env.ref("base.user_demo") + cls.portal_user = cls.env.ref("base_group_backend.user_demo_external") + cls.portal_ui_user = cls.env.ref( + "base_group_backend.user_demo_external_with_ui" + ) + cls.menu_no_group = cls.env.ref("base_group_backend.menu_root_no_group") + + def test_has_groups(self): + self.assertTrue(self.internal_user.has_group("base.group_user")) + self.assertFalse(self.portal_user.has_group("base.group_user")) + self.assertTrue(self.portal_ui_user.has_group("base.group_user")) + self.portal_user.write( + {"groups_id": [Command.set([self.base_group_backend.id])]} + ) + self.assertTrue(self.portal_user.has_group("base.group_user")) + + def test_share(self): + self.assertTrue(self.portal_user.share) + self.portal_user.write( + {"groups_id": [Command.set([self.base_group_backend.id])]} + ) + self.assertFalse(self.portal_user.share) + self.assertFalse(self.portal_ui_user.share) + + def test_no_roots_menu_with_no_groups(self): + self.assertNotIn( + self.menu_no_group, + self.env["ir.ui.menu"].with_user(self.portal_ui_user).get_user_roots(), + ) + self.assertIn( + self.menu_no_group, + self.env["ir.ui.menu"].with_user(self.internal_user).get_user_roots(), + )