Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions trp_external_user/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
External users
==============

Define a group 'External Users' that only have access to selected partners,
usually their own organizations. These partners are indicated on the user's user
form. By default, this module only grants read access to these partners.

On a permission level, it seems necessary that the partners also need read access
to the database company partner, which this module also allows. Keep this in mind
when building functionality on top of this module that allows interaction with
the partner model. By means of precaution, this module does define separate
records for reading and writing so as to prevent modifications of the company
partner (even if global write access on partners are not granted to the external
users group in this module).

This module also disables the default assignment of the 'user' and 'partner manager'
groups to new users.
2 changes: 2 additions & 0 deletions trp_external_user/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from . import models
19 changes: 19 additions & 0 deletions trp_external_user/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
"name": "External users",
"summary": "Allow external users on your system",
"version": "13.0.1.0.0",
"author": "Therp BV, Sunflower IT",
"category": "External users",
"website": "https://therp.nl",
"depends": ["base", "portal"],
"demo": ["demo/res_users.xml"],
"data": [
"data/ir_module_category.xml",
"security/res_groups.xml",
"security/ir.model.access.csv",
"security/ir_rule.xml",
"views/res_users.xml",
],
"license": "AGPL-3",
}
8 changes: 8 additions & 0 deletions trp_external_user/data/ir_module_category.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="module_category_external_users" model="ir.module.category">
<field name="name">External users</field>
<field name="description">External users</field>
<field name="sequence">60</field>
</record>
</odoo>
9 changes: 9 additions & 0 deletions trp_external_user/demo/res_users.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<record id="user_external" model="res.users" context="{'no_reset_password': True}">
<field name="login">external</field>
<field name="name">External user</field>
<field name="groups_id" eval="[(4, ref('group_external_user'))]" />
<field name="external_user_partner_ids" eval="[(4, ref('base.res_partner_2'))]" />
</record>
</odoo>
2 changes: 2 additions & 0 deletions trp_external_user/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from . import res_users
39 changes: 39 additions & 0 deletions trp_external_user/models/res_users.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import api, fields, models


class ResUsers(models.Model):
_inherit = "res.users"

@api.model
def _default_groups(self):
"""Disable default assignment of group 'users' and 'partner manager'"""
filter_groups = self.env.ref("base.group_user") + self.env.ref(
"base.group_partner_manager"
)
return (
super(ResUsers, self)
._default_groups()
.filtered(lambda x: not x & filter_groups)
)

@api.depends("groups_id")
def _compute_is_external_user(self):
for this in self:
this.is_external_user = (
self.env["ir.model.access"]
.with_user(this)
.check_groups("trp_external_user.group_external_user")
)

external_user_partner_ids = fields.Many2many(
"res.partner",
"trp_external_user_partner_id_rel",
"user_id",
"partner_id",
"External access to related partners",
)
is_external_user = fields.Boolean(
"Is external user", compute="_compute_is_external_user"
)
groups_id = fields.Many2many(default=lambda self: self._default_groups())
3 changes: 3 additions & 0 deletions trp_external_user/security/ir.model.access.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
"external_access_partner","Read access on partners for external users","base.model_res_partner","trp_external_user.group_external_user",1,0,0,0
"external_access_mail_message","Read/create access on mail messages for external users","mail.model_mail_message","trp_external_user.group_external_user",1,0,1,0
35 changes: 35 additions & 0 deletions trp_external_user/security/ir_rule.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="rule_company_partner" model="ir.rule" >
<field name="name">Read access to own partners plus company partner</field>
<field name="model_id" ref="base.model_res_partner"/>
<field name="groups" eval="[(4, ref('trp_external_user.group_external_user'))]"/>
<field name="perm_write" eval="False" />
<field name="perm_unlink" eval="False" />
<field name="perm_create" eval="False" />
<field name="domain_force">['|', '|',
('id', '=', user.company_id.partner_id.id),
('id', '=', user.partner_id.id),
('id', 'in', user.external_user_partner_ids.ids),
]</field>
</record>

<record id="rule_partner" model="ir.rule" >
<field name="name">Access to own partners</field>
<field name="model_id" ref="base.model_res_partner"/>
<field name="groups" eval="[(4, ref('trp_external_user.group_external_user'))]"/>
<field name="domain_force">['|',
('id', '=', user.partner_id.id),
('id', 'in', user.external_user_partner_ids.ids),
]</field>
</record>

<record id="rule_user" model="ir.rule">
<field name="name">Access to own user</field>
<field name="model_id" ref="base.model_res_users"/>
<field name="groups" eval="[(4, ref('trp_external_user.group_external_user'))]"/>
<field name="domain_force">[
('id', '=', user.id),
]</field>
</record>
</odoo>
11 changes: 11 additions & 0 deletions trp_external_user/security/res_groups.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="group_external_user" model="res.groups">
<field name="name">External users</field>
<field name="category_id" ref="module_category_external_users"/>
<field
name="implied_ids"
eval="[(6, 0, [ref('base.group_user')])]"
/>
</record>
</odoo>
Binary file added trp_external_user/static/description/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions trp_external_user/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from . import test_trp_external_user
33 changes: 33 additions & 0 deletions trp_external_user/tests/test_trp_external_user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo.exceptions import AccessError
from odoo.tests.common import TransactionCase


class TestTrpExternalUser(TransactionCase):
def test_trp_external_user(self):
external_user = self.env.ref("trp_external_user.user_external")
# check some permissions
with self.assertRaises(AccessError):
self.env.ref("base.user_root").with_user(external_user).name
self.assertEqual(
self.env.ref("base.main_partner").name,
self.env.ref("base.main_partner").with_user(external_user).name,
)
self.assertEqual(
self.env.ref("base.res_partner_2").name,
self.env.ref("base.res_partner_2").with_user(external_user).name,
)
self.assertEqual(
external_user.name, external_user.with_user(external_user).name
)
# check flag
self.assertTrue(external_user.is_external_user)
self.assertFalse(self.env.ref("base.user_root").is_external_user)
# check user creation
test_user = self.env["res.users"].create(
{"login": "some login", "name": "Some name"}
)
self.assertNotIn(self.env.ref("base.group_user"), test_user.groups_id)
self.assertNotIn(
self.env.ref("base.group_partner_manager"), test_user.groups_id
)
18 changes: 18 additions & 0 deletions trp_external_user/views/res_users.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_users_form" model="ir.ui.view">
<field name="inherit_id" ref="base.view_users_form" />
<field name="model">res.users</field>
<field name="arch" type="xml">
<page name="access_rights" position="after">
<page
name="trp_external_user" string="Accessible partners"
attrs="{'invisible': [('is_external_user', '=', False)]}"
>
<field name="is_external_user" invisible="1" />
<field name="external_user_partner_ids" />
</page>
</page>
</field>
</record>
</odoo>