Skip to content

Commit 8ac9134

Browse files
committed
[T-7772][ADD] model_access_restriction
1 parent 36c2436 commit 8ac9134

File tree

16 files changed

+378
-0
lines changed

16 files changed

+378
-0
lines changed

model_access_restriction/README.rst

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
========================
2+
Model Access Restriction
3+
========================
4+
5+
..
6+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
7+
!! This file is generated by oca-gen-addon-readme !!
8+
!! changes will be overwritten. !!
9+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
10+
!! source digest: sha256:6337b5f5fe7be747949769f4c064d9a6ca5495d905fa33e50b868be80bde4557
11+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
12+
13+
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
14+
:target: https://odoo-community.org/page/development-status
15+
:alt: Beta
16+
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
17+
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
18+
:alt: License: AGPL-3
19+
.. |badge3| image:: https://img.shields.io/badge/github-sygel--technology%2Fsy--server--backend-lightgray.png?logo=github
20+
:target: https://github.com/sygel-technology/sy-server-backend/tree/15.0/model_access_restriction
21+
:alt: sygel-technology/sy-server-backend
22+
23+
|badge1| |badge2| |badge3|
24+
25+
[ This file must be max 2-3 paragraphs, and is required. ]
26+
27+
This module extends the functionality of ... to support ... and to allow
28+
you to ...
29+
30+
**Table of contents**
31+
32+
.. contents::
33+
:local:
34+
35+
Configuration
36+
=============
37+
38+
[ This file is optional, it should explain how to configure the module
39+
before using it; it is aimed at advanced users. ]
40+
41+
To configure this module, you need to:
42+
43+
- Go to ...
44+
45+
|alternative description|../static/description/image.png)
46+
47+
https://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/.https://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/.https://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/ https://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/|https://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/ahttps://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/lhttps://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/thttps://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/ehttps://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/rhttps://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/nhttps://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/ahttps://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/thttps://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/ihttps://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/vhttps://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/ehttps://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/ https://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/dhttps://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/ehttps://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/shttps://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/chttps://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/rhttps://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/ihttps://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/phttps://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/thttps://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/ihttps://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/ohttps://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/nhttps://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/|https://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/ https://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/ihttps://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/mhttps://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/ahttps://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/ghttps://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/ehttps://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/:https://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/:https://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/ https://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/
48+
https://raw.githubusercontent.com/sygel-technology/sy-server-backend/15.0/model_access_restriction/
49+
50+
Usage
51+
=====
52+
53+
[ This file must be present and contains the usage instructions for
54+
end-users. As all other rst files included in the README, it MUST NOT
55+
contain reStructuredText sections only body text (paragraphs, lists,
56+
tables, etc). Should you need a more elaborate structure to explain the
57+
addon, please create a Sphinx documentation (which may include this file
58+
as a "quick start" section). ]
59+
60+
To use this module, you need to:
61+
62+
1. Go to ...
63+
64+
Known issues / Roadmap
65+
======================
66+
67+
[ Enumerate known caveats and future potential improvements. It is
68+
mostly intended for end-users, and can also help potential new
69+
contributors discovering new features to implement. ]
70+
71+
- ...
72+
73+
Bug Tracker
74+
===========
75+
76+
Bugs are tracked on `GitHub Issues <https://github.com/sygel-technology/sy-server-backend/issues>`_.
77+
In case of trouble, please check there if your issue has already been reported.
78+
If you spotted it first, help us to smash it by providing a detailed and welcomed
79+
`feedback <https://github.com/sygel-technology/sy-server-backend/issues/new?body=module:%20model_access_restriction%0Aversion:%2015.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
80+
81+
Do not contact contributors directly about support or help with technical issues.
82+
83+
Credits
84+
=======
85+
86+
Authors
87+
-------
88+
89+
* Sygel
90+
91+
Contributors
92+
------------
93+
94+
- Alberto Martínez [email protected]
95+
- Valentin Vinagre [email protected]
96+
- Harald Panten [email protected]
97+
98+
Maintainers
99+
-----------
100+
101+
This module is part of the `sygel-technology/sy-server-backend <https://github.com/sygel-technology/sy-server-backend/tree/15.0/model_access_restriction>`_ project on GitHub.
102+
103+
You are welcome to contribute.

model_access_restriction/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
2+
3+
from . import models
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Copyright 2025 Alberto Martínez <[email protected]>
2+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
3+
{
4+
"name": "Model Access Restriction",
5+
"summary": "Module summary",
6+
"version": "15.0.1.0.0",
7+
"category": "Tools",
8+
"website": "https://github.com/sygel-technology/sy-server-backend",
9+
"author": "Sygel, Odoo Community Association (OCA)",
10+
"license": "AGPL-3",
11+
"application": False,
12+
"installable": True,
13+
"depends": [
14+
"base",
15+
],
16+
"data": [
17+
"security/ir.model.access.csv",
18+
"views/ir_model_access_restriction_views.xml",
19+
],
20+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
2+
3+
from . import ir_model_access_restriction
4+
from . import models
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Copyright 2025 Alberto Martínez <[email protected]>
2+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
3+
4+
from odoo import _, api, exceptions, fields, models
5+
6+
7+
class IrModelAccessRestriction(models.Model):
8+
_name = "ir.model.access.restriction"
9+
_description = "Model Access Restrictions. Not having one will disable access."
10+
11+
_order = "model_id,name,id"
12+
13+
name = fields.Char(index=True)
14+
active = fields.Boolean(
15+
default=True,
16+
)
17+
model_id = fields.Many2one(
18+
"ir.model", string="Model", index=True, required=True, ondelete="cascade"
19+
)
20+
groups = fields.Many2many(
21+
comodel_name="res.groups",
22+
relation="model_access_restriction_group_rel",
23+
column1="model_access_restriction_id",
24+
column2="group_id",
25+
ondelete="restrict",
26+
)
27+
# perm_read = fields.Boolean(string='Apply for Read', default=True)
28+
# perm_write = fields.Boolean(string='Apply for Write', default=True)
29+
perm_create = fields.Boolean(string="Apply for Create", default=True)
30+
perm_unlink = fields.Boolean(string="Apply for Delete", default=True)
31+
32+
def _get_model_restrictions(self, model, operation):
33+
query = """ SELECT r.id
34+
FROM ir_model_access_restriction r JOIN ir_model m ON (r.model_id=m.id)
35+
WHERE m.model='{model}' AND r.active AND r.perm_{operation}
36+
ORDER BY r.id
37+
""".format(
38+
model=model, operation=operation
39+
)
40+
self._cr.execute(query)
41+
return self.browse(row[0] for row in self._cr.fetchall()).exists()
42+
43+
def _get_passed_restrictions(self, model, operation):
44+
query = """ SELECT r.id
45+
FROM ir_model_access_restriction r
46+
JOIN ir_model m ON (r.model_id=m.id)
47+
WHERE m.model='{model}' AND r.active AND r.perm_{operation}
48+
AND (r.id IN (
49+
SELECT model_access_restriction_id FROM model_access_restriction_group_rel rg
50+
JOIN res_groups_users_rel gu ON (rg.group_id=gu.gid)
51+
WHERE gu.uid={uid})
52+
)
53+
ORDER BY r.id
54+
""".format(
55+
model=model, operation=operation, uid=self._uid
56+
)
57+
self._cr.execute(query)
58+
return self.browse(row[0] for row in self._cr.fetchall()).exists()
59+
60+
def check_restrictions(self, model, operation):
61+
if operation not in ["create", "unlink"]:
62+
return True
63+
model_restrictions = self._get_model_restrictions(model, operation)
64+
return not model_restrictions or not (
65+
model_restrictions - self._get_passed_restrictions(model, operation)
66+
)
67+
68+
@api.constrains("groups")
69+
def _check_groups(self):
70+
for rec in self:
71+
if not any(rec.groups):
72+
raise exceptions.ValidationError(
73+
_("Restrictions must have at least one group")
74+
)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Copyright 2025 Alberto Martínez <[email protected]>
2+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
3+
4+
from odoo import api, models
5+
6+
7+
class Base(models.AbstractModel):
8+
_inherit = "base"
9+
10+
@api.model
11+
def check_access_rights(self, operation, raise_exception=True):
12+
not_access_restrictions = self.env[
13+
"ir.model.access.restriction"
14+
].check_restrictions(self._name, operation)
15+
return not_access_restrictions and super().check_access_rights(
16+
operation, raise_exception
17+
)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[ This file is optional, it should explain how to configure
2+
the module before using it; it is aimed at advanced users. ]
3+
4+
To configure this module, you need to:
5+
6+
- Go to ...
7+
8+
![alternative description]()../static/description/image.png)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
- Alberto Martínez <[email protected]>
2+
- Valentin Vinagre <[email protected]>
3+
- Harald Panten <[email protected]>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[ This file must be max 2-3 paragraphs, and is required. ]
2+
3+
This module extends the functionality of ... to support ...
4+
and to allow you to ...
5+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[ Enumerate known caveats and future potential improvements.
2+
It is mostly intended for end-users, and can also help
3+
potential new contributors discovering new features to implement. ]
4+
5+
- ...
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[ This file must be present and contains the usage instructions
2+
for end-users. As all other rst files included in the README,
3+
it MUST NOT contain reStructuredText sections
4+
only body text (paragraphs, lists, tables, etc). Should you need
5+
a more elaborate structure to explain the addon, please create a
6+
Sphinx documentation (which may include this file as a "quick start"
7+
section). ]
8+
9+
To use this module, you need to:
10+
11+
1. Go to ...
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
2+
access_ir_model_access_restriction,access_ir_model_access_restriction,model_ir_model_access_restriction,base.group_erp_manager,1,1,1,1
Loading
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<!-- Copyright 2025 Alberto Martínez <[email protected]>
3+
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
4+
<odoo>
5+
6+
<record id="view_model_access_restrictions_form" model="ir.ui.view">
7+
<field name="model">ir.model.access.restriction</field>
8+
<field name="arch" type="xml">
9+
<form string="Model Access Restrictions">
10+
<sheet>
11+
<group>
12+
<group string="General">
13+
<field name="name" />
14+
<field name="model_id" />
15+
<field name="active" widget="boolean_toggle" />
16+
</group>
17+
<group col="4" string="Access Rights">
18+
<!-- <field name="perm_read"/>
19+
<field name="perm_write"/> -->
20+
<field name="perm_create" />
21+
<field name="perm_unlink" />
22+
</group>
23+
</group>
24+
<group string="Groups">
25+
<field name="groups" nolabel="1" colspan="4" />
26+
</group>
27+
<i
28+
class="fa fa-info fa-3x text-info float-left"
29+
role="img"
30+
aria-label="Info"
31+
title="Info"
32+
/>
33+
<h3>Interaction between access records</h3>
34+
<div>
35+
<p>
36+
Normal access records give permissions. Access restriction records removes permissions, if a user does not have one group of a resctriction the access will be forbidden.
37+
</p>
38+
</div>
39+
</sheet>
40+
</form>
41+
</field>
42+
</record>
43+
44+
<record id="view_model_access_restrictions_tree" model="ir.ui.view">
45+
<field name="model">ir.model.access.restriction</field>
46+
<field name="arch" type="xml">
47+
<tree decoration-info="not groups">
48+
<field name="name" />
49+
<field name="model_id" />
50+
<field
51+
name="groups"
52+
widget="many2many_tags"
53+
options="{'no_create':True}"
54+
/>
55+
<!-- <field name="perm_read"/>
56+
<field name="perm_write"/> -->
57+
<field name="perm_create" />
58+
<field name="perm_unlink" />
59+
</tree>
60+
</field>
61+
</record>
62+
63+
<record id="view_model_access_restrictions_search" model="ir.ui.view">
64+
<field name="model">ir.model.access.restriction</field>
65+
<field name="arch" type="xml">
66+
<search string="Model Access Restrictions">
67+
<field name="name" />
68+
<field name="model_id" />
69+
<field name="groups" />
70+
<separator />
71+
<!-- <filter string="Read Access Right" name="read_access_right" domain="[('perm_read', '=', True)]"/>
72+
<filter string="Write Access Right" name="write_access_right" domain="[('perm_write', '=', True)]"/> -->
73+
<filter
74+
string="Create Access Right"
75+
name="create_access_right"
76+
domain="[('perm_create', '=' ,True)]"
77+
/>
78+
<filter
79+
string="Delete Access Right"
80+
name="delete_access_right"
81+
domain="[('perm_unlink', '=', True)]"
82+
/>
83+
<separator />
84+
<filter
85+
string="Archived"
86+
name="inactive"
87+
domain="[('active', '=', False)]"
88+
/>
89+
<group string="Group By">
90+
<filter
91+
string="Model"
92+
name="group_by_object"
93+
domain="[]"
94+
context="{'group_by': 'model_id'}"
95+
/>
96+
</group>
97+
</search>
98+
</field>
99+
</record>
100+
101+
<record id="action_model_access_restrictions" model="ir.actions.act_window">
102+
<field name="name">Model Access Restrictions</field>
103+
<field name="res_model">ir.model.access.restriction</field>
104+
<field name="view_id" ref="view_model_access_restrictions_tree" />
105+
<field name="search_view_id" ref="view_model_access_restrictions_search" />
106+
</record>
107+
108+
<menuitem
109+
action="action_model_access_restrictions"
110+
id="menu_action_model_access_restrictions"
111+
parent="base.menu_security"
112+
sequence="4"
113+
/>
114+
115+
116+
</odoo>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../../model_access_restriction
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import setuptools
2+
3+
setuptools.setup(
4+
setup_requires=['setuptools-odoo'],
5+
odoo_addon=True,
6+
)

0 commit comments

Comments
 (0)