Public release from ruodoo-project: 19.0 - 2026-05-31 21:19:12 UTC

This commit is contained in:
CI Publish Bot
2026-05-31 21:19:21 +00:00
commit aa4214c195
1213 changed files with 183945 additions and 0 deletions

30
access_apps/README.rst Normal file
View File

@ -0,0 +1,30 @@
.. image:: https://itpp.dev/images/infinity-readme.png
:alt: Tested and maintained by IT Projects Labs
:target: https://itpp.dev
========================
Control access to Apps
========================
Allows to configure administrators which don't have access to Apps.
Adds **Apps access** selection in user's access rights tab. Two options are available:
* *Allow installing apps*
* *Allow installing apps only from settings*
Questions?
==========
To get an assistance on this module contact us by email :arrow_right: help@itpp.dev
Contributors
============
* `Ivan Yelizariev <https://it-projects.info/team/yelizariev>`__
* `Ildar Nasyrov <https://it-projects.info/team/iledarn>`__
Further information
===================
Tested on `Odoo 17.0 <https://github.com/odoo/odoo/commit/40b19d89846303016098840f4958fe7cc105067c>`_

2
access_apps/__init__.py Normal file
View File

@ -0,0 +1,2 @@
from . import models
from .hooks import uninstall_hook

View File

@ -0,0 +1,29 @@
# Copyright 2018,2021 Ivan Yelizariev <https://it-projects.info/team/yelizariev>
# Copyright 2018 Ildar Nasyrov <https://it-projects.info/team/iledarn>
# License MIT (https://opensource.org/licenses/MIT).
{
"name": """Control access to Apps""",
"summary": """You can configure administrators which don't have access to Apps""",
"category": "Extra Tools",
# "live_test_url": "",
"images": ["images/banner.png"],
"version": "19.0.2.0.0",
"application": False,
"author": "IT-Projects LLC, Ivan Yelizariev",
"support": "apps@itpp.dev",
"website": "https://twitter.com/OdooFree",
"license": "Other OSI approved licence", # MIT
# "price": 10.00,
"currency": "EUR",
"depends": ["access_restricted"],
"external_dependencies": {"python": [], "bin": []},
"data": ["security/access_apps_security.xml", "security/ir.model.access.csv"],
"demo": [],
"qweb": [],
"post_load": None,
"pre_init_hook": None,
"post_init_hook": None,
"uninstall_hook": "uninstall_hook",
"auto_install": False,
"installable": True,
}

View File

@ -0,0 +1,37 @@
`2.0.0`
-------
- **Fix:** restore original access rights on uninstallation
- **Fix:** error in Settings menu when some modules are installed
`1.3.3`
-------
- **Fix:** Grant `Allow installing apps` to Admin and System users (it was only System)
`1.3.2`
-------
- **Fix:** allow users in group `Allow install apps only from settings` also to uninstall from settings
- **Fix:** `Allow install apps only from settings` security group should imply `Administration: Settings` - no access to settings otherwise
`1.3.1`
-------
- **Fix:** `Access Error` when administrators without access to apps trying to open ``[[ Website Admin ]] >> Configuratiion >> Settings``
`1.3.0`
-------
- **Fix:** the "Allow install apps" group is now implies "Administration: Settings" ("base.group_system") since in Odoo 11.0 only group_system users can install apps
`1.2.0`
-------
- **Improvement:** rename "Show Apps Menu" to "Allow install apps"
- **New:** "Allow install apps only from settings"
- **Improvement:** group "Show Apps Menu" and "Allow install apps only from settings" under "Apps access" security category
`1.0.1`
-------
- **Fix:** updates for recent odoo 9.0
- **Improvement:** apps dashboard can be showed if user has access 'Show Apps Menu'

32
access_apps/doc/index.rst Normal file
View File

@ -0,0 +1,32 @@
========================
Control access to Apps
========================
Installation
============
* `Install <https://odoo-development.readthedocs.io/en/latest/odoo/usage/install-module.html>`__ this module in a usual way
Configuration
=============
After the installation of this module by default only *default admin* and *superuser* have access to installing modules.
To update the permission follow for other users follow the steps below.
* Open menu ``[[ Settings ]] >> Users & Companies >> Users``, select the user you want to grant the access to
* On ``Access Rights`` tab, ``Other`` settings group there is an ``Apps access`` security category
* Select ``Allow installing apps`` - to allow apps installation from everywhere
* Select ``Allow installing apps only from settings`` - allow apps installation only from other module's ``Configuration >> Settings`` menu. More precisely, it just hides ``[[ Apps ]]`` menu
* Select blank line - to restrict application installation
Usage
=====
* Be sure that you don't test the functionality under the ``Administrator`` (superuser with id=1) user - he is immune to any access restriction except of hiding menus or buttons in UI
* If you don't select anything in ``Apps access``: there is no ``[[ Apps ]]`` menu - even if your user is in ``Administration: Settings`` security group. Also note that you
have no ability to include yourself in groups allowing to installing apps - this is what ``access_restricted`` module does (``access_apps`` depends on it)
* If you have ``Allow installing apps`` selected: there is ``[[ Apps ]]`` menu
* If you have ``Allow installing apps only from settings``: from other module's ``Configuration >> Settings`` menu, e.g. from ``[[ Website ]] >> Configuration >> Settings`` see that
you have the ability to check the ``Digital Content`` checkbox that actually installs the ``website_sale_digital`` module after clicking on ``[Apply]`` button.

7
access_apps/hooks.py Normal file
View File

@ -0,0 +1,7 @@
# Copyright 2021,2023 Ivan Yelizariev <https://it-projects.info/team/yelizariev>
# License MIT (https://opensource.org/licenses/MIT).
def uninstall_hook(env):
access = env.ref(
"base.access_ir_module_module_group_user", raise_if_not_found=False
)
access.write({"active": True})

View File

@ -0,0 +1,35 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * access_apps
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.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: access_apps
#: model:res.groups,name:access_apps.group_allow_apps
msgid "Allow installing apps"
msgstr ""
#. module: access_apps
#: model:res.groups,name:access_apps.group_allow_apps_only_from_settings
msgid "Allow installing apps only from settings"
msgstr ""
#. module: access_apps
#: model:ir.module.category,name:access_apps.module_category_access_apps
msgid "Apps access"
msgstr ""
#. module: access_apps
#: model:ir.model,name:access_apps.model_res_config_settings
msgid "Config Settings"
msgstr ""

42
access_apps/i18n/de.po Normal file
View File

@ -0,0 +1,42 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * access_apps
#
# Translators:
# Sergej Briesin <20bs18@gmail.com>, 2018
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 11.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-04-21 00:17+0000\n"
"PO-Revision-Date: 2018-04-21 00:17+0000\n"
"Last-Translator: Sergej Briesin <20bs18@gmail.com>, 2018\n"
"Language-Team: German (https://www.transifex.com/it-projects-llc/teams/76080/"
"de/)\n"
"Language: de\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"
#. module: access_apps
#: model:res.groups,name:access_apps.group_allow_apps
#, fuzzy
msgid "Allow installing apps"
msgstr "Erlaube Apps zu installieren"
#. module: access_apps
#: model:res.groups,name:access_apps.group_allow_apps_only_from_settings
#, fuzzy
msgid "Allow installing apps only from settings"
msgstr "Erlaube Apps nur vom Einstellungen zu installieren"
#. module: access_apps
#: model:ir.module.category,name:access_apps.module_category_access_apps
msgid "Apps access"
msgstr "Apps Zugriff"
#. module: access_apps
#: model:ir.model,name:access_apps.model_res_config_settings
msgid "Config Settings"
msgstr ""

45
access_apps/i18n/es.po Normal file
View File

@ -0,0 +1,45 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * access_apps
#
# Translators:
# charles paul requena palomino <rcharles84@gmail.com>, 2018
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-04-26 19:17+0000\n"
"PO-Revision-Date: 2018-04-26 19:17+0000\n"
"Last-Translator: charles paul requena palomino <rcharles84@gmail.com>, 2018\n"
"Language-Team: Spanish (https://www.transifex.com/it-projects-llc/"
"teams/76080/es/)\n"
"Language: es\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"
#. module: access_apps
#: model:res.groups,name:access_apps.group_allow_apps
#, fuzzy
msgid "Allow installing apps"
msgstr "Permitir instalar aplicaciones solo desde la configuración"
#. module: access_apps
#: model:res.groups,name:access_apps.group_allow_apps_only_from_settings
#, fuzzy
msgid "Allow installing apps only from settings"
msgstr "Permitir instalar aplicaciones solo desde la configuración"
#. module: access_apps
#: model:ir.module.category,name:access_apps.module_category_access_apps
msgid "Apps access"
msgstr "Acceso a aplicaciones"
#. module: access_apps
#: model:ir.model,name:access_apps.model_res_config_settings
msgid "Config Settings"
msgstr ""
#~ msgid "Access to Modules"
#~ msgstr "Acceso a los módulos"

43
access_apps/i18n/es_CR.po Normal file
View File

@ -0,0 +1,43 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * access_apps
#
# Translators:
# Randall <randall_castro@me.com>, 2018
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 11.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-04-21 00:17+0000\n"
"PO-Revision-Date: 2017-11-28 13:02+0000\n"
"Last-Translator: Randall <randall_castro@me.com>, 2018\n"
"Language-Team: Spanish (Costa Rica) (https://www.transifex.com/it-projects-"
"llc/teams/76080/es_CR/)\n"
"Language: es_CR\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"
#. module: access_apps
#: model:res.groups,name:access_apps.group_allow_apps
#, fuzzy
msgid "Allow installing apps"
msgstr "Permitir instalar aplicaciones"
#. module: access_apps
#: model:res.groups,name:access_apps.group_allow_apps_only_from_settings
msgid "Allow installing apps only from settings"
msgstr "Permitir instalar aplicaciones sólo desde ajustes"
#. module: access_apps
#: model:ir.module.category,name:access_apps.module_category_access_apps
msgid "Apps access"
msgstr "Acceso aplicaciones"
#. module: access_apps
#: model:ir.model,name:access_apps.model_res_config_settings
#, fuzzy
msgid "Config Settings"
msgstr "res.config.settings"

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

View File

@ -0,0 +1 @@
from . import res_config

View File

@ -0,0 +1,70 @@
# Copyright 2018 Ivan Yelizariev <https://it-projects.info/team/yelizariev>
# Copyright 2018 Ildar Nasyrov <https://it-projects.info/team/iledarn>
# License MIT (https://opensource.org/licenses/MIT).
from odoo import api, models
class ResConfigSettings(models.TransientModel):
_inherit = "res.config.settings"
@api.model
def _install_modules(self, modules):
if self.env.user.has_group(
"access_apps.group_allow_apps_only_from_settings"
):
self = self.sudo()
return super(ResConfigSettings, self)._install_modules(modules)
@api.model
def default_get(self, fields):
# We restricted any access to apps by default (`ir.module.module`) but in `website_sale` module configuration
# there is a field that gets its default value by searching in apps.
# Without this there is a possibility to encounter the `Access Error` when trying to open settings
# - e.g. when administrators without access to apps open ``[[ Website Admin ]] >> Configuration >> Settings``
# TODO: this solution may lead to unexpected result
# if some of default methods uses self self.env.user to compute default value
res = super(ResConfigSettings, self.sudo()).default_get(fields)
# modules: which modules are installed/to install
classified = self._get_classified_fields()
for module in classified["to_uninstall"]:
name = f"module_{module.name}"
res[name] = module.state in ("installed", "to install", "to upgrade")
if self._fields[name].type == "selection":
res[name] = str(int(res[name]))
return res
@api.model
def _get_classified_fields(self, fnames=None):
# classify mudules to install and uninstall independently
res = super(ResConfigSettings, self)._get_classified_fields(fnames=fnames)
to_uninstall = res["module"].filtered(
lambda m: not self[f"module_{m.name}"]
and m.state in ("installed", "to upgrade")
)
modules = res["module"] - to_uninstall
res["module"] = modules
res["to_uninstall"] = to_uninstall
return res
def execute(self):
# base `exectute` doesn't know about new classification - it only has a list of modules to install now
res = super(ResConfigSettings, self).execute()
# uninstall modules if needed and a user has access
to_uninstall = self._get_classified_fields()["to_uninstall"]
if to_uninstall and self.env.user.has_group(
"access_apps.group_allow_apps_only_from_settings"
):
to_uninstall_modules = self.env["ir.module.module"]
for module in to_uninstall:
to_uninstall_modules += module
to_uninstall_modules.sudo().button_immediate_uninstall()
return res

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2018,2021 Ivan Yelizariev <https://twitter.com/yelizariev>
Copyright 2018 Ildar Nasyrov <https://it-projects.info/team/iledarn>
License MIT (https://opensource.org/licenses/MIT).
-->
<odoo>
<record id="base.access_ir_module_module_group_user" model="ir.model.access">
<field name="active" eval="False" />
</record>
<record id="module_category_access_apps" model="ir.module.category">
<field name="name">Apps access</field>
<field name="sequence">18</field>
</record>
<record id="group_allow_apps_only_from_settings" model="res.groups">
<field name="name">Allow installing apps only from settings</field>
<field name="implied_ids" eval="[(4, ref('base.group_system'))]" />
</record>
<record id="group_allow_apps" model="res.groups">
<field name="name">Allow installing apps</field>
<field
name="user_ids"
eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"
/>
<field
name="implied_ids"
eval="[(4, ref('group_allow_apps_only_from_settings'))]"
/>
</record>
<record model="ir.ui.menu" id="base.menu_management">
<field name="group_ids" eval="[(6,0, [ref('access_apps.group_allow_apps')])]" />
</record>
</odoo>

View File

@ -0,0 +1,6 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
"access_ir_module_category_group_user","ir_module_category group_user","base.model_ir_module_category","group_allow_apps",1,0,0,0
"access_ir_module_module_group_user","ir_module_module group_user","base.model_ir_module_module","group_allow_apps",1,1,1,1
"access_ir_module_module_dependency_group_allow_apps","ir_module_module_dependency group_allow_apps","base.model_ir_module_module_dependency","group_allow_apps",1,1,1,1
"access_ir_module_module_group_allow_apps_only_from_settings","ir_module_module_group_allow_apps_only_from_settings","base.model_ir_module_module","group_allow_apps_only_from_settings",1,1,0,0
"access_ir_module_module_all_can_read","ir_module_module_all_can_read","base.model_ir_module_module","base.group_system",1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_ir_module_category_group_user ir_module_category group_user base.model_ir_module_category group_allow_apps 1 0 0 0
3 access_ir_module_module_group_user ir_module_module group_user base.model_ir_module_module group_allow_apps 1 1 1 1
4 access_ir_module_module_dependency_group_allow_apps ir_module_module_dependency group_allow_apps base.model_ir_module_module_dependency group_allow_apps 1 1 1 1
5 access_ir_module_module_group_allow_apps_only_from_settings ir_module_module_group_allow_apps_only_from_settings base.model_ir_module_module group_allow_apps_only_from_settings 1 1 0 0
6 access_ir_module_module_all_can_read ir_module_module_all_can_read base.model_ir_module_module base.group_system 1 0 0 0

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

@ -0,0 +1 @@
from . import test_access

View File

@ -0,0 +1,64 @@
# Copyright 2024 DOB
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
from odoo.exceptions import AccessError
from odoo.tests import new_test_user
from odoo.tests.common import TransactionCase
class TestAccessApps(TransactionCase):
"""Tests for access_apps: access control to the Apps section.
Validates: Requirement 6.1
"""
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.env = cls.env(
context=dict(cls.env.context, tracking_disable=True, no_reset_password=True)
)
# Regular user without admin rights and without group_allow_apps
cls.regular_user = new_test_user(
cls.env,
name="Regular User",
login="test_regular_user_access_apps",
groups="base.group_user",
)
def test_non_admin_cannot_read_ir_module_module(self):
"""WHEN a user without admin rights tries to access the Apps section,
access_apps SHALL deny access.
Validates: Requirement 6.1
"""
# The module deactivates base.access_ir_module_module_group_user,
# so only users in group_allow_apps can read ir.module.module.
# A regular user (not in group_allow_apps) should get AccessError.
with self.assertRaises(AccessError):
self.env["ir.module.module"].with_user(self.regular_user).search([])
def test_admin_can_read_ir_module_module(self):
"""WHEN the admin user (in group_allow_apps) accesses the Apps section,
access_apps SHALL allow access.
Validates: Requirement 6.1 (positive case)
"""
# Admin is in group_allow_apps by default (see security XML)
admin_user = self.env.ref("base.user_admin")
modules = self.env["ir.module.module"].with_user(admin_user).search([], limit=1)
# Should not raise; result may be empty or non-empty
self.assertIsNotNone(modules)
def test_non_admin_not_in_group_allow_apps(self):
"""WHEN a regular user is not in group_allow_apps,
they SHALL NOT have access to ir.module.module.
Validates: Requirement 6.1
"""
group_allow_apps = self.env.ref("access_apps.group_allow_apps")
self.assertNotIn(
self.regular_user,
group_allow_apps.users,
"Regular user should not be in group_allow_apps",
)