mirror of https://github.com/muk-it/muk_base
Mathias Markl
6 years ago
37 changed files with 1234 additions and 288 deletions
-
2muk_autovacuum/__manifest__.py
-
6muk_autovacuum/models/ir_autovacuum.py
-
7muk_autovacuum/models/rules.py
-
5muk_security/__init__.py
-
6muk_security/__manifest__.py
-
23muk_security/base/__init__.py
-
36muk_security/base/api.py
-
40muk_security/base/models.py
-
35muk_security/data/autovacuum.xml
-
5muk_security/doc/changelog.rst
-
4muk_security/doc/index.rst
-
5muk_security/models/__init__.py
-
41muk_security/models/access.py
-
171muk_security/models/access_groups.py
-
178muk_security/models/groups.py
-
39muk_security/models/ir_model_access.py
-
39muk_security/models/ir_rule.py
-
31muk_security/models/lock.py
-
82muk_security/models/locking.py
-
31muk_security/models/res_groups.py
-
57muk_security/models/res_users.py
-
43muk_security/models/security_groups.py
-
5muk_security/security/ir.model.access.csv
-
45muk_security/security/security.xml
-
7muk_security/static/description/index.html
-
22muk_security/tests/__init__.py
-
50muk_security/tests/test_suspend_security.py
-
22muk_security/tools/__init__.py
-
36muk_security/tools/helper.py
-
6muk_security/views/groups.xml
-
5muk_utils/__manifest__.py
-
41muk_utils/data/ir_cron.xml
-
3muk_utils/models/__init__.py
-
180muk_utils/models/groups.py
-
61muk_utils/models/model.py
-
68muk_utils/models/res_groups.py
-
85muk_utils/models/res_users.py
@ -0,0 +1,23 @@ |
|||
################################################################################### |
|||
# |
|||
# MuK Document Management System |
|||
# |
|||
# Copyright (C) 2018 MuK IT GmbH |
|||
# |
|||
# 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 api |
|||
from . import models |
@ -0,0 +1,36 @@ |
|||
################################################################################### |
|||
# |
|||
# Copyright (C) 2018 MuK IT GmbH |
|||
# |
|||
# 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/>. |
|||
# |
|||
################################################################################### |
|||
|
|||
import logging |
|||
|
|||
from odoo import models, api, SUPERUSER_ID |
|||
|
|||
from odoo.addons.muk_utils.tools import patch |
|||
from odoo.addons.muk_security.tools import helper |
|||
|
|||
_logger = logging.getLogger(__name__) |
|||
|
|||
@api.model |
|||
@patch.monkey_patch(api.Environment) |
|||
def __call__(self, cr=None, user=None, context=None): |
|||
env = __call__.super(self, cr, user, context) |
|||
if user and isinstance(user, helper.NoSecurityUid): |
|||
env.uid = user |
|||
return env |
|||
return env |
@ -0,0 +1,40 @@ |
|||
################################################################################### |
|||
# |
|||
# Copyright (C) 2018 MuK IT GmbH |
|||
# |
|||
# 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/>. |
|||
# |
|||
################################################################################### |
|||
|
|||
import logging |
|||
|
|||
from odoo import models, api, SUPERUSER_ID |
|||
|
|||
from odoo.addons.muk_utils.tools import patch |
|||
from odoo.addons.muk_security.tools import helper |
|||
|
|||
_logger = logging.getLogger(__name__) |
|||
|
|||
@api.model |
|||
def suspend_security(self, user=None): |
|||
return self.sudo(user=helper.NoSecurityUid(user or self.env.uid)) |
|||
|
|||
models.BaseModel.suspend_security = suspend_security |
|||
|
|||
@api.model |
|||
@patch.monkey_patch_model(models.BaseModel) |
|||
def check_field_access_rights(self, operation, fields): |
|||
if isinstance(self.env.uid, helper.NoSecurityUid): |
|||
return fields or list(self._fields) |
|||
return check_field_access_rights.super(self, operation, fields) |
@ -0,0 +1,35 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
|
|||
<!-- |
|||
Copyright (C) 2018 MuK IT GmbH |
|||
|
|||
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/>. |
|||
--> |
|||
|
|||
<odoo noupdate="1"> |
|||
|
|||
<record id="security_lock_autovacuum_rule" model="muk_autovacuum.rules"> |
|||
<field name="name">Cleans up locks that have not been removed correctly</field> |
|||
<field name="state">code</field> |
|||
<field name="model" ref="model_muk_security_lock"/> |
|||
<field name="code"> |
|||
locks = env['muk_security.lock'] |
|||
for lock in model.search([]): |
|||
if not lock.lock_ref: |
|||
locks |= lock |
|||
locks.unlink() |
|||
</field> |
|||
</record> |
|||
|
|||
</odoo> |
@ -1,3 +1,8 @@ |
|||
`1.1.0` |
|||
------- |
|||
|
|||
- Updated dependencies |
|||
|
|||
`1.0.0` |
|||
------- |
|||
|
|||
|
@ -1,178 +0,0 @@ |
|||
################################################################################### |
|||
# |
|||
# Copyright (C) 2017 MuK IT GmbH |
|||
# |
|||
# 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 odoo import models, fields, api |
|||
|
|||
class AccessGroups(models.Model): |
|||
|
|||
_name = 'muk_security.groups' |
|||
_description = "Access Groups" |
|||
_inherit = 'muk_utils.model' |
|||
|
|||
_parent_store = True |
|||
_parent_name = "parent_group" |
|||
_parent_order = 'parent_left' |
|||
_order = 'parent_left' |
|||
|
|||
#---------------------------------------------------------- |
|||
# Database |
|||
#---------------------------------------------------------- |
|||
|
|||
name = fields.Char( |
|||
string="Group Name", |
|||
required=True) |
|||
|
|||
parent_group = fields.Many2one( |
|||
comodel_name='muk_security.groups', |
|||
string='Parent Group', |
|||
ondelete='cascade', |
|||
auto_join=True, |
|||
index=True) |
|||
|
|||
child_groups = fields.One2many( |
|||
comodel_name='muk_security.groups', |
|||
inverse_name='parent_group', |
|||
string='Child Groups') |
|||
|
|||
parent_left = fields.Integer( |
|||
string='Left Parent', |
|||
index=True) |
|||
|
|||
parent_right = fields.Integer( |
|||
string='Right Parent', |
|||
index=True) |
|||
|
|||
perm_read = fields.Boolean( |
|||
string='Read Access') |
|||
|
|||
perm_create = fields.Boolean( |
|||
string='Create Access') |
|||
|
|||
perm_write = fields.Boolean( |
|||
string='Write Access') |
|||
|
|||
perm_unlink = fields.Boolean( |
|||
string='Unlink Access') |
|||
|
|||
groups = fields.Many2many( |
|||
comodel_name='res.groups', |
|||
relation='muk_groups_groups_rel', |
|||
column1='gid', |
|||
column2='rid', |
|||
string='Groups') |
|||
|
|||
explicit_users = fields.Many2many( |
|||
comodel_name='res.users', |
|||
relation='muk_groups_explicit_users_rel', |
|||
column1='gid', |
|||
column2='uid', |
|||
string='Explicit Users') |
|||
|
|||
users = fields.Many2many( |
|||
comodel_name='res.users', |
|||
relation='muk_groups_users_rel', |
|||
column1='gid', |
|||
column2='uid', |
|||
string='Users', |
|||
compute='_compute_users', |
|||
store=True) |
|||
|
|||
count_users = fields.Integer( |
|||
compute='_compute_count_users', |
|||
string="Users") |
|||
|
|||
_sql_constraints = [ |
|||
('name_uniq', 'unique (name)', 'The name of the group must be unique!') |
|||
] |
|||
|
|||
#---------------------------------------------------------- |
|||
# Functions |
|||
#---------------------------------------------------------- |
|||
|
|||
def trigger_computation_up(self, fields): |
|||
parent_group = self.parent_group |
|||
if parent_group: |
|||
parent_group.trigger_computation(fields) |
|||
|
|||
def trigger_computation_down(self, fields): |
|||
for child in self.child_groups: |
|||
child.with_context(is_subnode=True).trigger_computation(fields) |
|||
|
|||
def trigger_computation(self, fields): |
|||
values = {} |
|||
if "users" in fields: |
|||
values.update(self._compute_users(write=False)) |
|||
if values: |
|||
self.write(values); |
|||
if "users" in fields: |
|||
self.trigger_computation_down(fields) |
|||
|
|||
#---------------------------------------------------------- |
|||
# Read, View |
|||
#---------------------------------------------------------- |
|||
|
|||
@api.model |
|||
def check_user_values(self, values): |
|||
if any(field in values for field in ['parent_group', 'groups', 'explicit_users']): |
|||
return True |
|||
return False |
|||
|
|||
@api.multi |
|||
def get_users(self): |
|||
self.ensure_one() |
|||
users = self.env['res.users'] |
|||
if self.parent_group: |
|||
users |= self.parent_group.users |
|||
users |= self.groups.mapped('users') |
|||
users |= self.explicit_users |
|||
return users |
|||
|
|||
def _compute_users(self, write=True): |
|||
if write: |
|||
for record in self: |
|||
record.users = record.get_users() |
|||
else: |
|||
self.ensure_one() |
|||
return {'users': [(6, 0, self.get_users().mapped('id'))]} |
|||
|
|||
@api.depends('users') |
|||
def _compute_count_users(self): |
|||
for record in self: |
|||
record.count_users = len(record.users) |
|||
|
|||
#---------------------------------------------------------- |
|||
# Create, Write, Delete |
|||
#---------------------------------------------------------- |
|||
|
|||
def _after_create(self, vals): |
|||
record = super(AccessGroups, self)._after_create(vals) |
|||
record._check_recomputation(vals) |
|||
return record |
|||
|
|||
def _after_write_record(self, vals): |
|||
vals = super(AccessGroups, self)._after_write_record(vals) |
|||
self._check_recomputation(vals) |
|||
return vals |
|||
|
|||
def _check_recomputation(self, values): |
|||
fields = [] |
|||
if self.check_user_values(values): |
|||
fields.extend(['users']) |
|||
if fields: |
|||
self.trigger_computation(fields) |
@ -0,0 +1,39 @@ |
|||
################################################################################### |
|||
# |
|||
# Copyright (C) 2017 MuK IT GmbH |
|||
# |
|||
# 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/>. |
|||
# |
|||
################################################################################### |
|||
|
|||
import logging |
|||
|
|||
from odoo import api, fields, models |
|||
from odoo import tools, _ |
|||
from odoo.exceptions import ValidationError |
|||
|
|||
from odoo.addons.muk_security.tools import helper |
|||
|
|||
_logger = logging.getLogger(__name__) |
|||
|
|||
class ExtendedIrModelAccess(models.Model): |
|||
|
|||
_inherit = 'ir.model.access' |
|||
|
|||
@api.model |
|||
@tools.ormcache_context('self._uid', 'model', 'mode', 'raise_exception', keys=('lang',)) |
|||
def check(self, model, mode='read', raise_exception=True): |
|||
if isinstance(self.env.uid, helper.NoSecurityUid): |
|||
return True |
|||
return super(ExtendedIrModelAccess, self).check(model, mode=mode, raise_exception=raise_exception) |
@ -0,0 +1,39 @@ |
|||
################################################################################### |
|||
# |
|||
# Copyright (C) 2017 MuK IT GmbH |
|||
# |
|||
# 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/>. |
|||
# |
|||
################################################################################### |
|||
|
|||
import logging |
|||
|
|||
from odoo import api, fields, models |
|||
from odoo import tools, _ |
|||
from odoo.exceptions import ValidationError |
|||
|
|||
from odoo.addons.muk_security.tools import helper |
|||
|
|||
_logger = logging.getLogger(__name__) |
|||
|
|||
class ExtendedIrRule(models.Model): |
|||
|
|||
_inherit = 'ir.rule' |
|||
|
|||
@api.model |
|||
@tools.ormcache('self._uid', 'model_name', 'mode') |
|||
def _compute_domain(self, model_name, mode="read"): |
|||
if isinstance(self.env.uid, helper.NoSecurityUid): |
|||
return None |
|||
return super(ExtendedIrRule, self)._compute_domain(model_name, mode=mode) |
@ -0,0 +1,57 @@ |
|||
################################################################################### |
|||
# |
|||
# Copyright (C) 2017 MuK IT GmbH |
|||
# |
|||
# 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/>. |
|||
# |
|||
################################################################################### |
|||
|
|||
import logging |
|||
|
|||
from odoo import api, fields, models |
|||
from odoo import tools, _ |
|||
from odoo.exceptions import ValidationError |
|||
|
|||
from odoo.addons.base.res import res_users |
|||
|
|||
from odoo.addons.muk_security.tools import helper |
|||
|
|||
_logger = logging.getLogger(__name__) |
|||
|
|||
class AccessUser(models.Model): |
|||
|
|||
_inherit = 'res.users' |
|||
|
|||
#---------------------------------------------------------- |
|||
# Database |
|||
#---------------------------------------------------------- |
|||
|
|||
security_groups = fields.Many2many( |
|||
comodel_name='muk_security.groups', |
|||
relation='muk_security_groups_explicit_users_rel', |
|||
column1='uid', |
|||
column2='gid', |
|||
string='Groups', |
|||
readonly=True) |
|||
|
|||
#---------------------------------------------------------- |
|||
# Functions |
|||
#---------------------------------------------------------- |
|||
|
|||
@classmethod |
|||
def _browse(cls, ids, env, prefetch=None): |
|||
return super(AccessUser, cls)._browse([ |
|||
id if not isinstance(id, helper.NoSecurityUid) |
|||
else super(helper.NoSecurityUid, id).__int__() |
|||
for id in ids], env, prefetch=prefetch) |
@ -0,0 +1,43 @@ |
|||
################################################################################### |
|||
# |
|||
# Copyright (C) 2017 MuK IT GmbH |
|||
# |
|||
# 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 odoo import models, fields, api |
|||
|
|||
class AccessGroups(models.Model): |
|||
|
|||
_name = 'muk_security.groups' |
|||
_description = "Access Groups" |
|||
_inherit = 'muk_utils.groups' |
|||
|
|||
#---------------------------------------------------------- |
|||
# Database |
|||
#---------------------------------------------------------- |
|||
|
|||
perm_read = fields.Boolean( |
|||
string='Read Access') |
|||
|
|||
perm_create = fields.Boolean( |
|||
string='Create Access') |
|||
|
|||
perm_write = fields.Boolean( |
|||
string='Write Access') |
|||
|
|||
perm_unlink = fields.Boolean( |
|||
string='Unlink Access') |
|||
|
@ -1,4 +1,5 @@ |
|||
id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink |
|||
|
|||
access_security_lock_admin,security_lock_admin,model_muk_security_lock,base.group_erp_manager,1,0,0,1 |
|||
access_security_groups_admin,security_groups_admin,model_muk_security_groups,base.group_erp_manager,1,1,1,1 |
|||
access_security_groups_user,security_groups_user,model_muk_security_groups,base.group_user,1,1,1,1 |
|||
|
|||
access_security_lock_admin,security_lock_admin,model_muk_security_lock,base.group_erp_manager,1,0,0,1 |
@ -0,0 +1,45 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
|
|||
<!-- |
|||
Copyright (C) 2017 MuK IT GmbH |
|||
|
|||
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/>. |
|||
--> |
|||
|
|||
<odoo> |
|||
|
|||
<record id="rule_security_groups_user" model="ir.rule"> |
|||
<field name="name">User can only edit and delete their own groups.</field> |
|||
<field name="model_id" ref="model_muk_security_groups"/> |
|||
<field name="groups" eval="[(4, ref('base.group_user'))]"/> |
|||
<field name="perm_read" eval="0"/> |
|||
<field name="perm_create" eval="0"/> |
|||
<field name="perm_write" eval="1"/> |
|||
<field name="perm_unlink" eval="1" /> |
|||
<field name="domain_force">[('create_uid','=',user.id)]</field> |
|||
</record> |
|||
|
|||
<record id="rule_security_groups_manager" model="ir.rule"> |
|||
<field name="name">Admins can edit and delete all groups.</field> |
|||
<field name="model_id" ref="model_muk_security_groups"/> |
|||
<field name="groups" eval="[(4, ref('base.group_erp_manager'))]"/> |
|||
<field name="perm_read" eval="0"/> |
|||
<field name="perm_create" eval="0"/> |
|||
<field name="perm_write" eval="1"/> |
|||
<field name="perm_unlink" eval="1" /> |
|||
<field name="domain_force">[(1 ,'=', 1)]</field> |
|||
</record> |
|||
|
|||
</odoo> |
|||
|
@ -0,0 +1,22 @@ |
|||
################################################################################### |
|||
# |
|||
# MuK Document Management System |
|||
# |
|||
# Copyright (C) 2018 MuK IT GmbH |
|||
# |
|||
# 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_suspend_security |
@ -0,0 +1,50 @@ |
|||
################################################################################### |
|||
# |
|||
# Copyright (C) 2017 MuK IT GmbH |
|||
# |
|||
# 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/>. |
|||
# |
|||
################################################################################### |
|||
|
|||
import os |
|||
import base64 |
|||
import logging |
|||
|
|||
from odoo import exceptions |
|||
from odoo.tests import common |
|||
|
|||
_path = os.path.dirname(os.path.dirname(__file__)) |
|||
_logger = logging.getLogger(__name__) |
|||
|
|||
class SuspendSecurityTestCase(common.TransactionCase): |
|||
|
|||
at_install = False |
|||
post_install = True |
|||
|
|||
def setUp(self): |
|||
super(SuspendSecurityTestCase, self).setUp() |
|||
|
|||
def tearDown(self): |
|||
super(SuspendSecurityTestCase, self).tearDown() |
|||
|
|||
def test_suspend_security(self): |
|||
user_id = self.env.ref('base.user_demo').id |
|||
with self.assertRaises(exceptions.AccessError): |
|||
self.env.ref('base.user_root').sudo(user_id).name = 'test' |
|||
self.env.ref('base.user_root').sudo(user_id).suspend_security().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) |
|||
|
|||
def test_normalize(self): |
|||
self.env['res.users'].browse(self.env['res.users'].suspend_security().env.uid) |
@ -0,0 +1,22 @@ |
|||
################################################################################### |
|||
# |
|||
# MuK Document Management System |
|||
# |
|||
# Copyright (C) 2018 MuK IT GmbH |
|||
# |
|||
# 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 helper |
@ -0,0 +1,36 @@ |
|||
################################################################################### |
|||
# |
|||
# MuK Document Management System |
|||
# |
|||
# Copyright (C) 2018 MuK IT GmbH |
|||
# |
|||
# 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 NoSecurityUid(int): |
|||
|
|||
def __int__(self): |
|||
return self |
|||
|
|||
def __eq__(self, other): |
|||
if isinstance(other, int): |
|||
return False |
|||
return super(NoSecurityUid, self).__int__() == other |
|||
|
|||
def __iter__(self): |
|||
yield super(NoSecurityUid, self).__int__() |
|||
|
|||
def __hash__(self): |
|||
return super(NoSecurityUid, self).__hash__() |
@ -0,0 +1,41 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
|
|||
<!-- |
|||
Copyright (C) 2017 MuK IT GmbH |
|||
|
|||
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/>. |
|||
--> |
|||
|
|||
<odoo noupdate="1"> |
|||
|
|||
<record id="cron_utils_update_groups" model="ir.cron"> |
|||
<field name="name">Cron job to update the Groups</field> |
|||
<field name="active" eval="True" /> |
|||
<field name="user_id" ref="base.user_root" /> |
|||
<field name="model_id" ref="muk_utils.model_muk_utils_groups" /> |
|||
<field name="interval_number">1</field> |
|||
<field name="interval_type">days</field> |
|||
<field name="numbercall">-1</field> |
|||
<field name="priority" eval="5" /> |
|||
<field name="state">code</field> |
|||
<field name="code"> |
|||
model_names = model.pool.descendants(['muk_utils.groups'], '_inherit', '_inherits') |
|||
for model_name in model_names: |
|||
group = model.env[model_name].sudo() |
|||
if not group._abstract: |
|||
group.update_groups() |
|||
</field> |
|||
</record> |
|||
|
|||
</odoo> |
@ -0,0 +1,180 @@ |
|||
################################################################################### |
|||
# |
|||
# Copyright (C) 2017 MuK IT GmbH |
|||
# |
|||
# 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 odoo import models, fields, api |
|||
|
|||
class Groups(models.AbstractModel): |
|||
|
|||
_name = 'muk_utils.groups' |
|||
_inherit = 'muk_utils.model' |
|||
|
|||
_parent_store = True |
|||
_parent_name = "parent_group" |
|||
_parent_order = 'parent_left' |
|||
_order = 'parent_left' |
|||
|
|||
#---------------------------------------------------------- |
|||
# Database |
|||
#---------------------------------------------------------- |
|||
|
|||
name = fields.Char( |
|||
string="Group Name", |
|||
required=True, |
|||
translate=True) |
|||
|
|||
parent_left = fields.Integer( |
|||
string='Left Parent', |
|||
index=True) |
|||
|
|||
parent_right = fields.Integer( |
|||
string='Right Parent', |
|||
index=True) |
|||
|
|||
count_users = fields.Integer( |
|||
compute='_compute_count_users', |
|||
string="Users") |
|||
|
|||
@api.model |
|||
def _add_magic_fields(self): |
|||
super(Groups, self)._add_magic_fields() |
|||
def add(name, field): |
|||
if name not in self._fields: |
|||
self._add_field(name, field) |
|||
base, model = self._name.split(".") |
|||
add('parent_group', fields.Many2one( |
|||
_module=base, |
|||
comodel_name=self._name, |
|||
string='Parent Group', |
|||
ondelete='cascade', |
|||
auto_join=True, |
|||
index=True, |
|||
automatic=True)) |
|||
add('child_groups', fields.One2many( |
|||
_module=base, |
|||
comodel_name=self._name, |
|||
inverse_name='parent_group', |
|||
string='Child Groups', |
|||
automatic=True)) |
|||
add('groups', fields.Many2many( |
|||
_module=base, |
|||
comodel_name='res.groups', |
|||
relation='%s_groups_rel' % (self._table), |
|||
column1='gid', |
|||
column2='rid', |
|||
string='Groups', |
|||
automatic=True)) |
|||
add('explicit_users', fields.Many2many( |
|||
_module=base, |
|||
comodel_name='res.users', |
|||
relation='%s_explicit_users_rel' % (self._table), |
|||
column1='gid', |
|||
column2='uid', |
|||
string='Explicit Users', |
|||
automatic=True)) |
|||
add('users', fields.Many2many( |
|||
_module=base, |
|||
comodel_name='res.users', |
|||
relation='%s_users_rel' % (self._table), |
|||
column1='gid', |
|||
column2='uid', |
|||
string='Users', |
|||
compute='_compute_users', |
|||
store=True, |
|||
automatic=True)) |
|||
|
|||
_sql_constraints = [ |
|||
('name_uniq', 'unique (name)', 'The name of the group must be unique!') |
|||
] |
|||
|
|||
#---------------------------------------------------------- |
|||
# Functions |
|||
#---------------------------------------------------------- |
|||
|
|||
@api.multi |
|||
def trigger_computation_up(self, fields, *largs, **kwargs): |
|||
parent_groups = self.mapped('parent_group') |
|||
if parent_groups.exists(): |
|||
parent_groups.with_context(is_parent=True).trigger_computation(fields) |
|||
|
|||
@api.multi |
|||
def trigger_computation_down(self, fields, *largs, **kwargs): |
|||
child_groups = self.mapped('child_groups') |
|||
if child_groups.exists(): |
|||
child_groups.with_context(is_child=True).trigger_computation(fields) |
|||
|
|||
@api.multi |
|||
def trigger_computation(self, fields, *largs, **kwargs): |
|||
super(Groups, self).trigger_computation(fields, *largs, **kwargs) |
|||
if "users" in fields: |
|||
self.suspend_security()._compute_users() |
|||
self.suspend_security().trigger_computation_down(fields) |
|||
|
|||
@api.model |
|||
def check_user_values(self, values): |
|||
if any(field in values for field in [ |
|||
'parent_group', 'groups', 'explicit_users']): |
|||
return True |
|||
return False |
|||
|
|||
@api.multi |
|||
@api.returns('res.users') |
|||
def get_users(self): |
|||
self.ensure_one() |
|||
users = self.env['res.users'] |
|||
if self.parent_group: |
|||
users |= self.parent_group.users |
|||
users |= self.groups.mapped('users') |
|||
users |= self.explicit_users |
|||
return users |
|||
|
|||
#---------------------------------------------------------- |
|||
# Read, View |
|||
#---------------------------------------------------------- |
|||
|
|||
@api.multi |
|||
def _compute_users(self): |
|||
for record in self: |
|||
record.users = record.get_users() |
|||
|
|||
@api.depends('users') |
|||
def _compute_count_users(self): |
|||
for record in self: |
|||
record.count_users = len(record.users) |
|||
|
|||
#---------------------------------------------------------- |
|||
# Create, Write, Delete |
|||
#---------------------------------------------------------- |
|||
|
|||
@api.multi |
|||
def _check_recomputation(self, vals, olds, *largs, **kwargs): |
|||
super(Groups, self)._check_recomputation(vals, olds, *largs, **kwargs) |
|||
fields = [] |
|||
if self.check_user_values(vals): |
|||
fields.extend(['users']) |
|||
if fields: |
|||
self.trigger_computation(fields) |
|||
|
|||
#---------------------------------------------------------- |
|||
# Cron Job Functions |
|||
#---------------------------------------------------------- |
|||
|
|||
@api.model |
|||
def update_groups(self, *args, **kwargs): |
|||
self.search([]).trigger_computation(['users']) |
|||
|
@ -0,0 +1,68 @@ |
|||
################################################################################### |
|||
# |
|||
# Copyright (C) 2017 MuK IT GmbH |
|||
# |
|||
# 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/>. |
|||
# |
|||
################################################################################### |
|||
|
|||
import logging |
|||
|
|||
from collections import defaultdict |
|||
|
|||
from odoo import api, fields, models |
|||
from odoo import tools, _ |
|||
from odoo.exceptions import ValidationError |
|||
|
|||
_logger = logging.getLogger(__name__) |
|||
|
|||
class ResGroups(models.Model): |
|||
|
|||
_inherit = "res.groups" |
|||
|
|||
#---------------------------------------------------------- |
|||
# Create, Update, Delete |
|||
#---------------------------------------------------------- |
|||
|
|||
@api.multi |
|||
def write(self, vals): |
|||
model_recs = defaultdict(set) |
|||
model_names = self.pool.descendants(['muk_utils.groups'], '_inherit', '_inherits') |
|||
if any(field in vals for field in ['users']): |
|||
for model_name in model_names: |
|||
model = self.env[model_name].sudo() |
|||
if not model._abstract: |
|||
model_recs[model_name] = model.search([['groups', 'in', self.mapped('id')]]) |
|||
result = super(ResGroups, self).write(vals) |
|||
if any(field in vals for field in ['users']): |
|||
for model_name in model_names: |
|||
model = self.env[model_name].sudo() |
|||
if not model._abstract: |
|||
model_recs[model_name] = model_recs[model_name] | model.search([['groups', 'in', self.mapped('id')]]) |
|||
for tuple in model_recs.items(): |
|||
tuple[1].trigger_computation(['users']) |
|||
return result |
|||
|
|||
@api.multi |
|||
def unlink(self): |
|||
model_recs = defaultdict(set) |
|||
model_names = self.pool.descendants(['muk_utils.groups'], '_inherit', '_inherits') |
|||
for model_name in model_names: |
|||
model = self.env[model_name].sudo() |
|||
if not model._abstract: |
|||
model_recs[model_name] = model.search([['groups', 'in', self.mapped('id')]]) |
|||
result = super(ResGroups, self).unlink(vals) |
|||
for tuple in model_recs.items(): |
|||
tuple[1].trigger_computation(['users']) |
|||
return result |
@ -0,0 +1,85 @@ |
|||
################################################################################### |
|||
# |
|||
# Copyright (C) 2017 MuK IT GmbH |
|||
# |
|||
# 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/>. |
|||
# |
|||
################################################################################### |
|||
|
|||
import logging |
|||
|
|||
from collections import defaultdict |
|||
|
|||
from odoo import api, fields, models |
|||
from odoo import tools, _ |
|||
from odoo.exceptions import ValidationError |
|||
|
|||
from odoo.addons.base.res import res_users |
|||
|
|||
from odoo.addons.muk_security.tools import helper |
|||
|
|||
_logger = logging.getLogger(__name__) |
|||
|
|||
class ResUser(models.Model): |
|||
|
|||
_inherit = 'res.users' |
|||
|
|||
#---------------------------------------------------------- |
|||
# Create, Update, Delete |
|||
#---------------------------------------------------------- |
|||
|
|||
@api.model |
|||
def create(self, values): |
|||
result = super(ResUser, self).create(values) |
|||
model_recs = defaultdict(set) |
|||
model_names = self.pool.descendants(['muk_utils.groups'], '_inherit', '_inherits') |
|||
for model_name in model_names: |
|||
model = self.env[model_name].sudo() |
|||
if not model._abstract: |
|||
model_recs[model_name] = model.search([['groups', 'in', self.mapped('groups_id.id')]]) |
|||
for tuple in model_recs.items(): |
|||
tuple[1].trigger_computation(['users']) |
|||
return result |
|||
|
|||
@api.multi |
|||
def write(self, vals): |
|||
group_ids = self.mapped('groups_id.id') |
|||
result = super(ResUser, self).write(vals) |
|||
group_ids += [vals[k] for k in vals if res_users.is_selection_groups(k) and vals[k]] |
|||
group_ids += [vals[k] for k in vals if res_users.is_boolean_group(k) and vals[k]] |
|||
if any(field in vals for field in ['groups_id']): |
|||
group_ids += self.mapped('groups_id.id') |
|||
if group_ids: |
|||
model_recs = defaultdict(set) |
|||
model_names = self.pool.descendants(['muk_utils.groups'], '_inherit', '_inherits') |
|||
for model_name in model_names: |
|||
model = self.env[model_name].sudo() |
|||
if not model._abstract: |
|||
model_recs[model_name] = model.search([['groups', 'in', group_ids]]) |
|||
for tuple in model_recs.items(): |
|||
tuple[1].trigger_computation(['users']) |
|||
return result |
|||
|
|||
@api.multi |
|||
def unlink(self): |
|||
model_recs = defaultdict(set) |
|||
model_names = self.pool.descendants(['muk_utils.groups'], '_inherit', '_inherits') |
|||
for model_name in model_names: |
|||
model = self.env[model_name].sudo() |
|||
if not model._abstract: |
|||
model_recs[model_name] = model.search([['groups', 'in', self.mapped('groups_id.id')]]) |
|||
result = super(ResUser, self).unlink() |
|||
for tuple in model_recs.items(): |
|||
tuple[1].trigger_computation(['users']) |
|||
return result |
Write
Preview
Loading…
Cancel
Save
Reference in new issue