diff --git a/base_technical_features/README.rst b/base_technical_features/README.rst index 1d35fb35e..a6a2987a9 100644 --- a/base_technical_features/README.rst +++ b/base_technical_features/README.rst @@ -8,17 +8,26 @@ Access to technical features without activating debug mode In Odoo 9.0, the debug mode grants every employee user access to the technical features. This module enables persistent access to technical features based on -group access. +user preference. Configuration ============= After installation of this module, every employee can still access technical features for the applications that they have access to by enabling debug mode. -Additionally, users can be assigned the *Technical feature (w/o debug mode)* -access right on their user form which will enable technical features at any -time. As an Odoo administrator, you might want to review who to grant this -access to. +Additionally, users can check the *Technical feature* field in their +preferences to gain permanent access to the menus and views that fall under +this category. + +.. figure:: static/description/user_preferences.png + :alt: User preferences + +Upon installation of this module, this preference is already +set for the administrator user of the database. + +In the background, this preference is mapped to the *Technical feature (w/o +debug mode)* group that this module adds. As an administrator, you can +therefore manage this preference from the regular Users and Groups menu items. Usage ===== diff --git a/base_technical_features/__openerp__.py b/base_technical_features/__openerp__.py index 3fa65b707..14383e9f5 100644 --- a/base_technical_features/__openerp__.py +++ b/base_technical_features/__openerp__.py @@ -1,15 +1,17 @@ -# -*- coding: utf-8 -*- -# © 2016 Opener B.V. +# coding: utf-8 +# © 2016 Opener B.V. () # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). { "name": "Technical features group", "summary": "Access to technical features without activating debug mode", "version": "9.0.1.0.0", "category": "Usability", - "website": "https://odoo-community.org/", + "website": "https://github.com/oca/server-tools", "author": "Opener B.V., Odoo Community Association (OCA)", "data": [ 'security/res_groups.xml', + 'views/res_users.xml', + 'data/res_users.xml', ], "license": "AGPL-3", "installable": True, diff --git a/base_technical_features/data/res_users.xml b/base_technical_features/data/res_users.xml new file mode 100644 index 000000000..e9f87e586 --- /dev/null +++ b/base_technical_features/data/res_users.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/base_technical_features/i18n/nl.po b/base_technical_features/i18n/nl.po index 4f180b0b7..8d7ef8f31 100644 --- a/base_technical_features/i18n/nl.po +++ b/base_technical_features/i18n/nl.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 9.0c\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-01-01 17:57+0000\n" -"PO-Revision-Date: 2016-01-01 17:57+0000\n" +"POT-Creation-Date: 2016-01-03 16:11+0000\n" +"PO-Revision-Date: 2016-01-03 16:11+0000\n" "Last-Translator: <>\n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -15,7 +15,28 @@ msgstr "" "Content-Transfer-Encoding: \n" "Plural-Forms: \n" +#. module: base_technical_features +#: model:ir.model.fields,field_description:base_technical_features.field_res_users_show_technical_features +msgid "Show field Technical Features" +msgstr "Toon veld Technische mogelijkheden" + #. module: base_technical_features #: model:res.groups,name:base_technical_features.group_technical_features msgid "Technical Features (w/o debug mode)" msgstr "Technische mogelijkheden (zonder debugmodus)" + +#. module: base_technical_features +#: model:ir.model.fields,field_description:base_technical_features.field_res_users_technical_features +msgid "Technical features" +msgstr "Technische mogelijkheden" + +#. module: base_technical_features +#: code:addons/base_technical_features/models/res_users.py:45 +#, python-format +msgid "The user does not have access to technical features." +msgstr "De gebruiker heeft geen toegang tot technische mogelijkheden." + +#. module: base_technical_features +#: model:ir.model.fields,help:base_technical_features.field_res_users_show_technical_features +msgid "Whether to display the technical features field in the user preferences." +msgstr "Geeft aan of het veld Technische mogelijkheden wordt getoond in de voorkeuren van de gebruiker." diff --git a/base_technical_features/models/__init__.py b/base_technical_features/models/__init__.py index 7c5b68460..b26f7f495 100644 --- a/base_technical_features/models/__init__.py +++ b/base_technical_features/models/__init__.py @@ -1,2 +1,3 @@ from . import basemodel_monkeypatch from . import ir_ui_menu +from . import res_users diff --git a/base_technical_features/models/basemodel_monkeypatch.py b/base_technical_features/models/basemodel_monkeypatch.py index 9cc0bfd17..0652a12cd 100644 --- a/base_technical_features/models/basemodel_monkeypatch.py +++ b/base_technical_features/models/basemodel_monkeypatch.py @@ -1,4 +1,6 @@ # -*- coding: utf-8 -*- +# © 2016 Opener B.V. () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from openerp import models, api diff --git a/base_technical_features/models/ir_ui_menu.py b/base_technical_features/models/ir_ui_menu.py index 878507fca..112fe3957 100644 --- a/base_technical_features/models/ir_ui_menu.py +++ b/base_technical_features/models/ir_ui_menu.py @@ -1,4 +1,6 @@ -# -*- coding: utf-8 -*- +# coding: utf-8 +# © 2016 Opener B.V. () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from openerp import api, models diff --git a/base_technical_features/models/res_users.py b/base_technical_features/models/res_users.py new file mode 100644 index 000000000..824caefac --- /dev/null +++ b/base_technical_features/models/res_users.py @@ -0,0 +1,59 @@ +# coding: utf-8 +# © 2016 Opener B.V. () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from openerp import api, fields, models +from openerp.exceptions import AccessError +from openerp.tools.translate import _ + + +class ResUsers(models.Model): + _inherit = 'res.users' + + technical_features = fields.Boolean( + compute='get_technical_features', + inverse='set_technical_features') + show_technical_features = fields.Boolean( + string='Show field Technical Features', + compute='get_show_technical_features', + help=('Whether to display the technical features field in the user ' + 'preferences.')) + + @api.multi + @api.depends('groups_id') + def get_show_technical_features(self): + """ Only display the technical features checkbox in the user + preferences if the user has access to them """ + users = self.env.ref('base.group_no_one').users + for user in self: + user.show_technical_features = user in users + + @api.multi + @api.depends('groups_id') + def get_technical_features(self): + """ Map user membership to boolean field value """ + users = self.env.ref( + 'base_technical_features.group_technical_features').users + for user in self: + user.technical_features = user in users + + @api.multi + def set_technical_features(self): + """ Map boolean field value to group membership, but checking + access """ + group = self.env.ref( + 'base_technical_features.group_technical_features') + for user in self: + if self.env.ref('base.group_no_one') not in user.groups_id: + raise AccessError( + _('The user does not have access to technical ' + 'features.')) + if user.technical_features: + self.sudo().write({'groups_id': [(4, group.id)]}) + else: + self.sudo().write({'groups_id': [(3, group.id)]}) + + def __init__(self, pool, cr): + super(ResUsers, self).__init__(pool, cr) + self.SELF_READABLE_FIELDS += [ + 'technical_features', 'show_technical_features'] + self.SELF_WRITEABLE_FIELDS.append('technical_features') diff --git a/base_technical_features/security/res_groups.xml b/base_technical_features/security/res_groups.xml index d61ffc5c5..12846ece2 100644 --- a/base_technical_features/security/res_groups.xml +++ b/base_technical_features/security/res_groups.xml @@ -3,6 +3,5 @@ Technical Features (w/o debug mode) - diff --git a/base_technical_features/static/description/user_preferences.png b/base_technical_features/static/description/user_preferences.png new file mode 100644 index 000000000..c30837e13 Binary files /dev/null and b/base_technical_features/static/description/user_preferences.png differ diff --git a/base_technical_features/tests/test_base_technical_features.py b/base_technical_features/tests/test_base_technical_features.py index af2f7fc9b..3e9ac0348 100644 --- a/base_technical_features/tests/test_base_technical_features.py +++ b/base_technical_features/tests/test_base_technical_features.py @@ -1,4 +1,6 @@ # -*- coding: utf-8 -*- +from openerp import api +from openerp.exceptions import AccessError from openerp.tests import common from lxml import etree @@ -13,11 +15,9 @@ class TestBaseTechnicalFeatures(common.TransactionCase): menu_id = menu_obj.search( [('groups_id', '=', self.env.ref('base.group_no_one').id)], limit=1).id - self.env.user.groups_id -= self.env.ref( - 'base_technical_features.group_technical_features') + self.env.user.write({'technical_features': False}) self.assertNotIn(menu_id, menu_obj._visible_menu_ids()) - self.env.user.groups_id += self.env.ref( - 'base_technical_features.group_technical_features') + self.env.user.write({'technical_features': True}) self.assertIn(menu_id, menu_obj._visible_menu_ids()) def test02_visible_fields(self): @@ -33,9 +33,29 @@ class TestBaseTechnicalFeatures(common.TransactionCase): '//div/group/field[@name="partner_id"]')[0].get('invisible') self.env['basemodel.monkeypatch']._register_hook() - self.env.user.groups_id -= self.env.ref( - 'base_technical_features.group_technical_features') + self.env.user.write({'technical_features': False}) self.assertEqual(get_partner_field_invisible(), '1') - self.env.user.write({'groups_id': [(4, self.env.ref( - 'base_technical_features.group_technical_features').id)]}) + self.env.user.write({'technical_features': True}) self.assertEqual(get_partner_field_invisible(), None) + + def test03_user_access(self): + """ Setting the user pref raises an access error if the user is not \ + in group_no_one """ + user = self.env['res.users'].create({ + 'name': 'Test user technical features', + 'login': 'testusertechnicalfeatures', + 'groups_id': [(6, 0, [])]}) + with api.Environment.manage(): + env = api.Environment( + self.env.cr, user.id, self.env.context) + with self.assertRaises(AccessError): + env['res.users'].browse(user.id).write( + {'technical_features': True}) + with self.assertRaises(AccessError): + user.write({'technical_features': True}) + user.write({'groups_id': [(4, self.env.ref('base.group_no_one').id)]}) + with api.Environment.manage(): + env = api.Environment( + self.env.cr, user.id, self.env.context) + env['res.users'].browse(user.id).write({ + 'technical_features': True}) diff --git a/base_technical_features/views/res_users.xml b/base_technical_features/views/res_users.xml new file mode 100644 index 000000000..3fabefda9 --- /dev/null +++ b/base_technical_features/views/res_users.xml @@ -0,0 +1,16 @@ + + + + Add technical features checkbox to user preferences form + res.users + + + + + + + + + +