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.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 |
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