diff --git a/.travis.yml b/.travis.yml index d93895204..f117abe8a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,8 @@ python: - "2.7" addons: - postgresql: "9.2" # minimal postgresql version for the daterange method + postgresql: "9.3" # minimal postgresql version for the base_import_security_group module + # more info: https://github.com/OCA/maintainer-quality-tools/issues/432 apt: packages: - expect-dev # provides unbuffer utility @@ -29,6 +30,13 @@ env: virtualenv: system_site_packages: true +before_install: + - "export PATH=$PWD/travis_phantomjs/phantomjs-2.1.1-linux-x86_64/bin:$PATH" + - "if [ $(phantomjs --version) != '2.1.1' ]; then rm -rf $PWD/travis_phantomjs; mkdir -p $PWD/travis_phantomjs; fi" + - "if [ $(phantomjs --version) != '2.1.1' ]; then wget https://assets.membergetmember.co/software/phantomjs-2.1.1-linux-x86_64.tar.bz2 -O $PWD/travis_phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2; fi" + - "if [ $(phantomjs --version) != '2.1.1' ]; then tar -xvf $PWD/travis_phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2 -C $PWD/travis_phantomjs; fi" + - "phantomjs --version" + install: - git clone https://github.com/OCA/maintainer-quality-tools.git ${HOME}/maintainer-quality-tools - export PATH=${HOME}/maintainer-quality-tools/travis:${PATH} diff --git a/base_import_security_group/README.rst b/base_import_security_group/README.rst new file mode 100644 index 000000000..febbf1fbb --- /dev/null +++ b/base_import_security_group/README.rst @@ -0,0 +1,62 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl + :alt: License: AGPL-3 + +=============================================== +Group-based permissions for importing CSV files +=============================================== + +This module makes importing data from CSV and Excel files optional for each user, +allowing it only for those users belonging to a specific group. +Any other user not belonging to such group will not have the "Import" button +available anywhere. The action will even be blocked internally (to prevent +XMLRPC access, for example). + +Usage +===== + +To allow a user to import data from CSV and Excel files, just follow this steps: + +* Go to *Settings/Users/Users* menu. +* Enter the user you want to allow. +* Within the "Access Rights" tab and "Technical Settings" group, check the + option "Allow importing CSV/Excel files". + +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 smash it by providing detailed and welcomed feedback. + +Credits +======= + +Contributors +------------ + +* Alejandro Santana +* Antonio Esposito + +Do not contact contributors directly about support or help with technical issues. + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +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. + +To contribute to this module, please visit https://odoo-community.org. + +Icon +---- + +Iconic fonts used in module icon are Font Awesome: http://fontawesome.io/ diff --git a/base_import_security_group/__init__.py b/base_import_security_group/__init__.py new file mode 100644 index 000000000..ca88ff9fd --- /dev/null +++ b/base_import_security_group/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# Copyright 2015 Anubía, soluciones en la nube,SL (http://www.anubia.es) +# Copyright 2017 Onestein (http://www.onestein.eu) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import models diff --git a/base_import_security_group/__manifest__.py b/base_import_security_group/__manifest__.py new file mode 100644 index 000000000..ad35af7be --- /dev/null +++ b/base_import_security_group/__manifest__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Copyright 2015 Anubía, soluciones en la nube,SL (http://www.anubia.es) +# Copyright 2017 Onestein (http://www.onestein.eu) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{ + 'name': 'Optional CSV import', + 'version': '10.0.1.0.0', + 'category': 'Server tools', + 'summary': 'Group-based permissions for importing CSV files', + 'license': 'AGPL-3', + 'author': 'Odoo Community Association (OCA), ' + 'Alejandro Santana , ' + 'Onestein', + 'maintainer': 'Odoo Community Association (OCA)', + 'website': 'http://odoo-community.org', + 'depends': [ + 'web', + 'base_import', + ], + 'data': [ + 'security/base_import_security_group_security.xml', + 'views/base_import.xml', + ], + 'installable': True, +} diff --git a/base_import_security_group/i18n/ca.po b/base_import_security_group/i18n/ca.po new file mode 100644 index 000000000..8264c7643 --- /dev/null +++ b/base_import_security_group/i18n/ca.po @@ -0,0 +1,21 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * base_import_security_group +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-08-06 18:37+0000\n" +"PO-Revision-Date: 2015-08-06 18:37+0000\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_import_security_group +#: model:res.groups,name:base_import_security_group.group_import_csv +msgid "Import CSV files" +msgstr "Importar arxius CSV" diff --git a/base_import_security_group/i18n/es.po b/base_import_security_group/i18n/es.po new file mode 100644 index 000000000..45980b00a --- /dev/null +++ b/base_import_security_group/i18n/es.po @@ -0,0 +1,21 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * base_import_security_group +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-08-06 18:37+0000\n" +"PO-Revision-Date: 2015-08-06 18:37+0000\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_import_security_group +#: model:res.groups,name:base_import_security_group.group_import_csv +msgid "Import CSV files" +msgstr "Importar archivos CSV" diff --git a/base_import_security_group/i18n/fr.po b/base_import_security_group/i18n/fr.po new file mode 100644 index 000000000..4ef9d1dd4 --- /dev/null +++ b/base_import_security_group/i18n/fr.po @@ -0,0 +1,21 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * base_import_security_group +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-08-06 18:37+0000\n" +"PO-Revision-Date: 2015-08-06 18:37+0000\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_import_security_group +#: model:res.groups,name:base_import_security_group.group_import_csv +msgid "Import CSV files" +msgstr "Importation de fichiers CSV" diff --git a/base_import_security_group/i18n/gl.po b/base_import_security_group/i18n/gl.po new file mode 100644 index 000000000..1c2b3de0c --- /dev/null +++ b/base_import_security_group/i18n/gl.po @@ -0,0 +1,21 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * base_import_security_group +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-08-06 18:37+0000\n" +"PO-Revision-Date: 2015-08-06 18:37+0000\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_import_security_group +#: model:res.groups,name:base_import_security_group.group_import_csv +msgid "Import CSV files" +msgstr "Importar arquivos CSV" diff --git a/base_import_security_group/i18n/it.po b/base_import_security_group/i18n/it.po new file mode 100644 index 000000000..5f3546161 --- /dev/null +++ b/base_import_security_group/i18n/it.po @@ -0,0 +1,21 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * base_import_security_group +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-08-06 18:37+0000\n" +"PO-Revision-Date: 2015-08-06 18:37+0000\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_import_security_group +#: model:res.groups,name:base_import_security_group.group_import_csv +msgid "Import CSV files" +msgstr "Importazione di file CSV" diff --git a/base_import_security_group/i18n/pt.po b/base_import_security_group/i18n/pt.po new file mode 100644 index 000000000..1c2b3de0c --- /dev/null +++ b/base_import_security_group/i18n/pt.po @@ -0,0 +1,21 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * base_import_security_group +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-08-06 18:37+0000\n" +"PO-Revision-Date: 2015-08-06 18:37+0000\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_import_security_group +#: model:res.groups,name:base_import_security_group.group_import_csv +msgid "Import CSV files" +msgstr "Importar arquivos CSV" diff --git a/base_import_security_group/i18n/sk.po b/base_import_security_group/i18n/sk.po new file mode 100644 index 000000000..8d1a57577 --- /dev/null +++ b/base_import_security_group/i18n/sk.po @@ -0,0 +1,21 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * base_import_security_group +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-08-06 18:37+0000\n" +"PO-Revision-Date: 2015-08-06 18:37+0000\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_import_security_group +#: model:res.groups,name:base_import_security_group.group_import_csv +msgid "Import CSV files" +msgstr "Importovať súbory CSV" diff --git a/base_import_security_group/models/__init__.py b/base_import_security_group/models/__init__.py new file mode 100644 index 000000000..ca88ff9fd --- /dev/null +++ b/base_import_security_group/models/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# Copyright 2015 Anubía, soluciones en la nube,SL (http://www.anubia.es) +# Copyright 2017 Onestein (http://www.onestein.eu) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import models diff --git a/base_import_security_group/models/models.py b/base_import_security_group/models/models.py new file mode 100644 index 000000000..bfef76e80 --- /dev/null +++ b/base_import_security_group/models/models.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +# Copyright 2015 Anubía, soluciones en la nube,SL (http://www.anubia.es) +# Copyright 2017 Onestein (http://www.onestein.eu) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import logging + +from odoo import api, models + +_logger = logging.getLogger(__name__) + + +class Base(models.AbstractModel): + _inherit = 'base' + + @api.model + def load(self, fields, data): + '''Overriding this method we only allow its execution + if current user belongs to the group allowed for CSV data import. + An exception is raised otherwise, and also log the import attempt. + ''' + current_user = self.env.user + allowed_group = 'base_import_security_group.group_import_csv' + allowed_group_id = self.env.ref( + allowed_group, + raise_if_not_found=False + ) + if not allowed_group_id or current_user.has_group(allowed_group): + res = super(Base, self).load(fields=fields, data=data) + else: + msg = ('User (ID: %s) is not allowed to import data ' + 'in model %s.') % (self.env.uid, self._name) + _logger.info(msg) + messages = [] + info = {} + messages.append( + dict(info, type='error', message=msg, moreinfo=None)) + res = {'ids': None, 'messages': messages} + return res diff --git a/base_import_security_group/security/base_import_security_group_security.xml b/base_import_security_group/security/base_import_security_group_security.xml new file mode 100644 index 000000000..d8d8c6b34 --- /dev/null +++ b/base_import_security_group/security/base_import_security_group_security.xml @@ -0,0 +1,11 @@ + + + + + + Import CSV/Excel files + + + + + diff --git a/base_import_security_group/static/description/icon.png b/base_import_security_group/static/description/icon.png new file mode 100644 index 000000000..4386c9359 Binary files /dev/null and b/base_import_security_group/static/description/icon.png differ diff --git a/base_import_security_group/static/description/icon.svg b/base_import_security_group/static/description/icon.svg new file mode 100644 index 000000000..18e65d7a7 --- /dev/null +++ b/base_import_security_group/static/description/icon.svg @@ -0,0 +1,168 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/base_import_security_group/static/src/js/import.js b/base_import_security_group/static/src/js/import.js new file mode 100644 index 000000000..12f043fb8 --- /dev/null +++ b/base_import_security_group/static/src/js/import.js @@ -0,0 +1,30 @@ +odoo.define('web.ListImport', function (require) { + "use strict"; + var core = require('web.core'); + var ListView = require('web.ListView'); + var Model = require('web.Model'); + + ListView.prototype.defaults.import_enabled = false; + ListView.include(/** @lends instance.web.ListView# */{ + + load_list: function (data, grouped) { + + var self = this; + var Users = new Model('res.users'); + + var result = this._super.apply(this, arguments); + Users.call('has_group', ['base_import_security_group.group_import_csv']) + .then(function (result) { + var import_enabled = result; + self.options.import_enabled = import_enabled; + + if (import_enabled === false) { + if (self.$buttons) { + self.$buttons.find('.o_button_import').remove(); + } + } + }); + return result; + } + }); +}); diff --git a/base_import_security_group/tests/__init__.py b/base_import_security_group/tests/__init__.py new file mode 100644 index 000000000..f065a1581 --- /dev/null +++ b/base_import_security_group/tests/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Onestein (http://www.onestein.eu) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import test_base_import_security_group diff --git a/base_import_security_group/tests/test_base_import_security_group.py b/base_import_security_group/tests/test_base_import_security_group.py new file mode 100644 index 000000000..985fe9325 --- /dev/null +++ b/base_import_security_group/tests/test_base_import_security_group.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Onestein (http://www.onestein.eu) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + + +from odoo.tests import common + + +class TestImportSecurityGroup(common.HttpCase): + def setUp(self): + super(TestImportSecurityGroup, self).setUp() + self.Access = self.env['ir.model.access'] + self.user_test = self.env.ref('base.user_demo') + + def has_button_import(self, falsify=False, user=None): + """ + Verify that the button is either visible or invisible. + After the adjacent button is loaded, allow for a second for + the asynchronous call to finish and update the visibility """ + code = """ + window.setTimeout(function () { + if (%s$('.o_button_import').length) { + console.log('ok'); + } else { + console.log('error'); + }; + }, 1000); + """ % ('!' if falsify else '') + action = self.env.ref('base.action_partner_category_form').id + link = '/web#action=%s' % action + self.phantom_js( + link, code, "$('button.o_list_button_add').length", + login=user.login) + + def test_01_load(self): + """ Admin user can import data, but the demo user cannot """ + fields = ( + 'id', + 'name', + 'perm_read', + 'perm_write', + 'perm_create', + 'perm_unlink', + ) + + data = [ + ('access_res_users_test', 'res.users test', '1', '0', '0', '0',), + ('access_res_users_test2', 'res.users test2', '1', '1', '1', '1'), + ] + + self.has_button_import(user=self.env.user) + res = self.Access.load(fields, data) + + self.assertEqual(res['ids'], False) + self.assertEqual(len(res['messages']), 2) + self.assertEqual( + res['messages'][0]['message'], + "Missing required value for the field 'Object' (model_id)") + self.assertEqual( + res['messages'][1]['message'], + "Missing required value for the field 'Object' (model_id)") + + self.has_button_import(falsify=True, user=self.user_test) + res2 = self.Access.sudo(self.user_test).load(fields, data) + + self.assertEqual(res2['ids'], None) + self.assertEqual(len(res2['messages']), 1) + self.assertEqual( + res2['messages'][0]['message'], + 'User (ID: %s) is not allowed to import data in ' + 'model ir.model.access.' % self.user_test.id) diff --git a/base_import_security_group/views/base_import.xml b/base_import_security_group/views/base_import.xml new file mode 100644 index 000000000..73aedfe32 --- /dev/null +++ b/base_import_security_group/views/base_import.xml @@ -0,0 +1,10 @@ + + + + + +