mirror of
https://github.com/OCA/server-backend.git
synced 2025-02-18 09:52:42 +02:00
[ADD] base_user_role_company: add per company user roles
This commit is contained in:
committed by
Holger Brunn
parent
88120541fb
commit
9e058c1a97
4
base_user_role_company/__init__.py
Normal file
4
base_user_role_company/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
# Copyright (C) 2021 Open Source Integrators
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from . import models
|
||||
19
base_user_role_company/__manifest__.py
Normal file
19
base_user_role_company/__manifest__.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# Copyright (C) 2021 Open Source Integrators
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
"name": "User roles by company",
|
||||
"version": "14.0.1.0.0",
|
||||
"category": "Tools",
|
||||
"author": "Open Source Integrators, Odoo Community Association (OCA)",
|
||||
"license": "AGPL-3",
|
||||
"website": "https://github.com/OCA/server-backend",
|
||||
"depends": ["base_user_role"],
|
||||
"data": [
|
||||
"views/role.xml",
|
||||
],
|
||||
"installable": True,
|
||||
"auto_install": True,
|
||||
"maintainer": "dreispt",
|
||||
"development_status": "Beta",
|
||||
}
|
||||
5
base_user_role_company/models/__init__.py
Normal file
5
base_user_role_company/models/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
# Copyright (C) 2021 Open Source Integrators
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from . import role
|
||||
from . import ir_http
|
||||
23
base_user_role_company/models/ir_http.py
Normal file
23
base_user_role_company/models/ir_http.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# Copyright (C) 2021 Open Source Integrators
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models
|
||||
from odoo.http import request
|
||||
|
||||
|
||||
class IrHttp(models.AbstractModel):
|
||||
_inherit = "ir.http"
|
||||
|
||||
def session_info(self):
|
||||
"""
|
||||
Based on the selected companies (cids),
|
||||
calculate the roles to enable.
|
||||
A role should be enabled only when it applies to all selected companies.
|
||||
"""
|
||||
result = super(IrHttp, self).session_info()
|
||||
if self.env.user.role_line_ids:
|
||||
cids_str = request.httprequest.cookies.get("cids", str(self.env.company.id))
|
||||
cids = [int(cid) for cid in cids_str.split(",")]
|
||||
self.env.user._set_session_active_roles(cids)
|
||||
self.env.user.set_groups_from_roles()
|
||||
return result
|
||||
65
base_user_role_company/models/role.py
Normal file
65
base_user_role_company/models/role.py
Normal file
@@ -0,0 +1,65 @@
|
||||
# Copyright (C) 2021 Open Source Integrators
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class ResUsersRoleLine(models.Model):
|
||||
_inherit = "res.users.role.line"
|
||||
|
||||
company_id = fields.Many2one(
|
||||
"res.company",
|
||||
"Company",
|
||||
help="If set, this role only applies when this is the main company selected."
|
||||
" Otherwise it applies to all companies.",
|
||||
)
|
||||
active_role = fields.Boolean(string="Active Role", default=True)
|
||||
|
||||
@api.constrains("user_id", "company_id")
|
||||
def _check_company(self):
|
||||
for record in self:
|
||||
if (
|
||||
record.company_id
|
||||
and record.company_id != record.user_id.company_id
|
||||
and record.company_id not in record.user_id.company_ids
|
||||
):
|
||||
raise ValidationError(
|
||||
_('User "{}" does not have access to the company "{}"').format(
|
||||
record.user_id.name, record.company_id.name
|
||||
)
|
||||
)
|
||||
|
||||
_sql_constraints = [
|
||||
(
|
||||
"user_role_uniq",
|
||||
"unique (user_id,role_id,company_id)",
|
||||
"Roles can be assigned to a user only once at a time",
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
class ResUsers(models.Model):
|
||||
_inherit = "res.users"
|
||||
|
||||
def _get_enabled_roles(self):
|
||||
res = super()._get_enabled_roles()
|
||||
return res.filtered("active_role")
|
||||
|
||||
@api.model
|
||||
def _set_session_active_roles(self, cids):
|
||||
"""
|
||||
Based on the selected companies (cids),
|
||||
calculate the roles to enable.
|
||||
A role should be enabled only when it applies to all selected companies.
|
||||
"""
|
||||
for role_line in self.env.user.role_line_ids:
|
||||
if not role_line.company_id:
|
||||
role_line.active_role = True
|
||||
elif role_line.company_id.id in cids:
|
||||
is_on_companies = self.env.user.role_line_ids.filtered(
|
||||
lambda x: x.role_id == role_line.role_id and x.company_id.id in cids
|
||||
)
|
||||
role_line.active_role = len(is_on_companies) == len(cids)
|
||||
else:
|
||||
role_line.active_role = False
|
||||
6
base_user_role_company/readme/CONFIGURE.rst
Normal file
6
base_user_role_company/readme/CONFIGURE.rst
Normal file
@@ -0,0 +1,6 @@
|
||||
Roles are set on the User form.
|
||||
|
||||
The "Company" additional column allows to set a Role as only valid for specific companies.
|
||||
|
||||
There is also a "Active Role" techincal field, only visible in developer mode.
|
||||
It shows what roles are active, after applying the company selection rules.
|
||||
4
base_user_role_company/readme/CONTRIBUTORS.rst
Normal file
4
base_user_role_company/readme/CONTRIBUTORS.rst
Normal file
@@ -0,0 +1,4 @@
|
||||
`Open Source Integrators <http://opensourceintegrators.com>`_
|
||||
|
||||
* Daniel Reis <dreis@opensourceintegrators.com>
|
||||
* Chandresh Thakkar <cthakkr@opensourceintegrators.com>
|
||||
9
base_user_role_company/readme/DESCRIPTION.rst
Normal file
9
base_user_role_company/readme/DESCRIPTION.rst
Normal file
@@ -0,0 +1,9 @@
|
||||
Enable User Roles depending on the Companies selected.
|
||||
|
||||
A company specific Role will only be enabled
|
||||
if it is set for **all** the currently selected companies.
|
||||
|
||||
For example, if a user is "Sales Manager" only for Company A,
|
||||
it will see that role enabled only if Company A is selected.
|
||||
If the user selects Company A and Company B,
|
||||
then the "Sales Manager" role won't be enabled.
|
||||
17
base_user_role_company/readme/USAGE.rst
Normal file
17
base_user_role_company/readme/USAGE.rst
Normal file
@@ -0,0 +1,17 @@
|
||||
Select the active companies from the web client widget, near the top right corner.
|
||||
When doing so, the User's security Groups are recomputed, based on the Roles.
|
||||
|
||||
When the user changes the company selection, only the groups available to all active companies will be activated.
|
||||
|
||||
For example:
|
||||
|
||||
* A "SALES PERSON" and a "SALES MANAGER" roles are created.
|
||||
|
||||
* A user is assigned to the roles:
|
||||
* "SALES PERSON", with no specific company assigned (meaning all)
|
||||
* "SALES MANAGER" only to "My Company (Chicago)"
|
||||
|
||||
* When selecting active companies from the UI widget:
|
||||
* If only "My Company (San Francisco)" is active, "SALES PERSON" will be active.
|
||||
* If only "My Company (Chicago)" is active, "SALES PERSON" and "SALES MANAGER" will be active.
|
||||
* If both "My Company (San Francisco)" and "My Company (Chicago)" is active, "SALES PERSON" will be active.
|
||||
1
base_user_role_company/tests/__init__.py
Normal file
1
base_user_role_company/tests/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import test_role_per_company
|
||||
62
base_user_role_company/tests/test_role_per_company.py
Normal file
62
base_user_role_company/tests/test_role_per_company.py
Normal file
@@ -0,0 +1,62 @@
|
||||
# Copyright 2021 Open Source Integrators
|
||||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
|
||||
|
||||
from odoo.tests.common import TransactionCase
|
||||
|
||||
|
||||
class TestUserRoleCompany(TransactionCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
# COMPANIES
|
||||
self.Company = self.env["res.company"]
|
||||
self.company1 = self.env.ref("base.main_company")
|
||||
self.company2 = self.Company.create({"name": "company2"})
|
||||
# ROLES
|
||||
self.Role = self.env["res.users.role"]
|
||||
self.roleA = self.Role.create({"name": "ROLE All Companies"})
|
||||
self.roleB = self.Role.create({"name": "ROLE Company 1"})
|
||||
self.roleC = self.Role.create({"name": "ROLE Company 1 and 2"})
|
||||
# USER
|
||||
# ==Role=== ==Company== C1 C2 C1+C2
|
||||
# Role A Yes Yes Yes
|
||||
# Role B Company1 Yes
|
||||
# Role C Company1 Yes Yes
|
||||
# Role C Company2 Yes Yes
|
||||
self.User = self.env["res.users"]
|
||||
user_vals = {
|
||||
"name": "ROLES TEST USER",
|
||||
"login": "test_user",
|
||||
"company_ids": [(6, 0, [self.company1.id, self.company2.id])],
|
||||
"role_line_ids": [
|
||||
(0, 0, {"role_id": self.roleA.id}),
|
||||
(0, 0, {"role_id": self.roleB.id, "company_id": self.company1.id}),
|
||||
(0, 0, {"role_id": self.roleC.id, "company_id": self.company1.id}),
|
||||
(0, 0, {"role_id": self.roleC.id, "company_id": self.company2.id}),
|
||||
],
|
||||
}
|
||||
self.test_user = self.User.create(user_vals)
|
||||
self.User = self.User.with_user(self.test_user)
|
||||
|
||||
def test_110_company_1(self):
|
||||
"Company 1 selected: Tech and Settings roles are activated"
|
||||
self.User._set_session_active_roles([self.company1.id])
|
||||
active_roles = self.test_user.role_line_ids.filtered("active_role").mapped(
|
||||
"role_id"
|
||||
)
|
||||
self.assertEqual(active_roles, self.roleA | self.roleB | self.roleC)
|
||||
|
||||
def test_120_company_2(self):
|
||||
"Company 2 selected: only Tech role enabled"
|
||||
self.User._set_session_active_roles([self.company2.id])
|
||||
active_roles = self.test_user.role_line_ids.filtered("active_role").mapped(
|
||||
"role_id"
|
||||
)
|
||||
self.assertEqual(active_roles, self.roleA | self.roleC)
|
||||
|
||||
def test_130_company_1_2(self):
|
||||
"Settings Role enabled for Company 1 and 2"
|
||||
self.User._set_session_active_roles([self.company1.id, self.company2.id])
|
||||
active_roles = self.test_user.role_line_ids.filtered("active_role").mapped(
|
||||
"role_id"
|
||||
)
|
||||
self.assertEqual(active_roles, self.roleA | self.roleC)
|
||||
14
base_user_role_company/views/role.xml
Normal file
14
base_user_role_company/views/role.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<record id="view_res_users_form_inherit_company" model="ir.ui.view">
|
||||
<field name="name">res.users.form.inherit.company</field>
|
||||
<field name="model">res.users</field>
|
||||
<field name="inherit_id" ref="base_user_role.view_res_users_form_inherit" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="role_id" position="after">
|
||||
<field name="company_id" groups="base.group_multi_company" />
|
||||
<field name="active_role" groups="base.group_no_one" readonly="1" />
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user