Browse Source

Merge pull request #204 from hbrunn/8.0-base_suspend_security

[ADD] base_suspend_security
pull/222/head
Pedro M. Baeza 9 years ago
parent
commit
5c600cbf5f
  1. 56
      base_suspend_security/README.rst
  2. 20
      base_suspend_security/__init__.py
  3. 38
      base_suspend_security/__openerp__.py
  4. 35
      base_suspend_security/base_suspend_security.py
  5. 22
      base_suspend_security/models/__init__.py
  6. 34
      base_suspend_security/models/ir_model_access.py
  7. 38
      base_suspend_security/models/ir_rule.py
  8. 36
      base_suspend_security/models/res_users.py
  9. BIN
      base_suspend_security/static/description/icon.png
  10. 20
      base_suspend_security/tests/__init__.py
  11. 51
      base_suspend_security/tests/test_base_suspend_security.py

56
base_suspend_security/README.rst

@ -0,0 +1,56 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:alt: License: AGPL-3
Suspend security
=====================
This module was written to allow you to call code with some `uid` while being sure no security checks (`ir.model.access` and `ir.rule`) are done. In this way, it's the same as `sudo()`, but the crucial difference is that the code still runs with the original user id. This can be important for inherited code that calls workflow functions, subscribes the current user to some object, etc.
Usually, you'll be in in the situation to want something like this if you inherit from a module you can't or don't want to change, and call `super()`.
Usage
=====
To use this module, you need to:
* depend on this module
* call `yourmodel.suspend_security().function_to_run()`, just the same as you would use `sudo()`
For further information, please visit:
* https://www.odoo.com/forum/help-1
Known issues / Roadmap
======================
* the magic works by wrapping uid in a marker class, so if some code unwraps this in the calling tree, security checks will be reenabled
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/server-tools/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed feedback
`here <https://github.com/OCA/server-tools/issues/new?body=module:%20base_suspend_security%0Aversion:%208.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Credits
=======
Contributors
------------
* Holger Brunn <hbrunn@therp.nl>
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 http://odoo-community.org.

20
base_suspend_security/__init__.py

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# This module copyright (C) 2015 Therp BV <http://therp.nl>.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from . import models

38
base_suspend_security/__openerp__.py

@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# This module copyright (C) 2015 Therp BV <http://therp.nl>.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
"name": "Suspend security",
"version": "1.0",
"author": "Therp BV",
"license": "AGPL-3",
"category": "Hidden/Dependency",
"summary": "Suspend security checks for a call",
"depends": [
'base',
],
"test": [
],
"auto_install": False,
"installable": True,
"application": False,
"external_dependencies": {
'python': [],
},
}

35
base_suspend_security/base_suspend_security.py

@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# This module copyright (C) 2015 Therp BV <http://therp.nl>.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
class BaseSuspendSecurityUid(int):
def __int__(self):
return self
def __eq__(self, other):
if isinstance(other, (int, long)):
return False
return super(BaseSuspendSecurityUid, self).__int__() == other
def __iter__(self):
yield super(BaseSuspendSecurityUid, self).__int__()
SUSPEND_METHOD = 'suspend_security'

22
base_suspend_security/models/__init__.py

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# This module copyright (C) 2015 Therp BV <http://therp.nl>.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from . import ir_rule
from . import ir_model_access
from . import res_users

34
base_suspend_security/models/ir_model_access.py

@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# This module copyright (C) 2015 Therp BV (<http://therp.nl>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp import models, tools
from ..base_suspend_security import BaseSuspendSecurityUid
class IrModelAccess(models.Model):
_inherit = 'ir.model.access'
@tools.ormcache_context(accepted_keys=('lang'))
def check(self, cr, uid, model, mode='read', raise_exception=True,
context=None):
if isinstance(uid, BaseSuspendSecurityUid):
return True
return super(IrModelAccess, self).check(
cr, uid, model, mode=mode, raise_exception=raise_exception,
context=context)

38
base_suspend_security/models/ir_rule.py

@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# This module copyright (C) 2015 Therp BV (<http://therp.nl>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp import models, api
from ..base_suspend_security import BaseSuspendSecurityUid, SUSPEND_METHOD
class IrRule(models.Model):
_inherit = 'ir.rule'
@api.model
def domain_get(self, model_name, mode='read'):
if isinstance(self.env.uid, BaseSuspendSecurityUid):
return [], [], ['"%s"' % self.pool[model_name]._table]
return super(IrRule, self).domain_get(model_name, mode=mode)
def _register_hook(self, cr):
if not hasattr(models.BaseModel, SUSPEND_METHOD):
setattr(models.BaseModel, SUSPEND_METHOD,
lambda self: self.sudo(
user=BaseSuspendSecurityUid(self.env.uid)))
return super(IrRule, self)._register_hook(cr)

36
base_suspend_security/models/res_users.py

@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# This module copyright (C) 2015 Therp BV (<http://therp.nl>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp import models
from ..base_suspend_security import BaseSuspendSecurityUid
class ResUsers(models.Model):
_inherit = 'res.users'
@classmethod
def _browse(cls, env, ids):
"""be sure we browse ints, ids laread is normalized"""
return super(ResUsers, cls)._browse(
env,
[
i if not isinstance(i, BaseSuspendSecurityUid)
else super(BaseSuspendSecurityUid, i).__int__()
for i in ids
])

BIN
base_suspend_security/static/description/icon.png

After

Width: 128  |  Height: 128  |  Size: 9.2 KiB

20
base_suspend_security/tests/__init__.py

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# This module copyright (C) 2015 Therp BV <http://therp.nl>.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from . import test_base_suspend_security

51
base_suspend_security/tests/test_base_suspend_security.py

@ -0,0 +1,51 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# This module copyright (C) 2015 Therp BV (<http://therp.nl>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp import exceptions
from openerp.tests.common import TransactionCase
class TestBaseSuspendSecurity(TransactionCase):
def test_base_suspend_security(self):
# tests are called before register_hook
self.env['ir.rule']._register_hook()
user_id = self.env.ref('base.user_demo').id
other_company = self.env['res.company'].create({
'name': 'other company',
# without this, a partner is created and mail's constraint on
# notify_email kicks in
'partner_id': self.env.ref('base.partner_demo').id,
})
# be sure what we try is forbidden
with self.assertRaises(exceptions.AccessError):
self.env.ref('base.user_root').sudo(user_id).name = 'test'
with self.assertRaises(exceptions.AccessError):
other_company.sudo(user_id).name = 'test'
# this tests ir.model.access
self.env.ref('base.user_root').sudo(user_id).suspend_security().write({
'name': 'test'})
self.assertEqual(self.env.ref('base.user_root').name, 'test')
self.assertEqual(self.env.ref('base.user_root').write_uid.id, user_id)
# this tests ir.rule
other_company.sudo(user_id).suspend_security().write({'name': 'test'})
self.assertEqual(other_company.name, 'test')
self.assertEqual(other_company.write_uid.id, user_id)
# this tests if _normalize_args conversion works
self.env['res.users'].browse(
self.env['res.users'].suspend_security().env.uid)
Loading…
Cancel
Save