Browse Source
[ADD] user_threshold: Create module (#836)
[ADD] user_threshold: Create module (#836)
* [ADD] user_threshold: Create module * [IMP] user_threshold: Fixes per PR * Fix README * Rename poorly named methods * Syntactic sugar * Remove direct SQL in favor of ORM API * Docstrings * [IMP] user_threshold: Fixes per PR * Update verbiage in README * Simplify access check calls * Use the same verbiage throughout error messages * Add Link to related modules in READMEpull/863/head
Ted Salmon
8 years ago
committed by
Dave Lasley
18 changed files with 777 additions and 0 deletions
-
95user_threshold/README.rst
-
5user_threshold/__init__.py
-
20user_threshold/__manifest__.py
-
14user_threshold/data/ir_config_parameter_data.xml
-
13user_threshold/data/user_threshold_data.xml
-
9user_threshold/models/__init__.py
-
45user_threshold/models/ir_config_parameter.py
-
47user_threshold/models/res_company.py
-
27user_threshold/models/res_groups.py
-
130user_threshold/models/res_users.py
-
8user_threshold/tests/__init__.py
-
31user_threshold/tests/common.py
-
87user_threshold/tests/test_ir_config_parameter.py
-
44user_threshold/tests/test_res_company.py
-
34user_threshold/tests/test_res_groups.py
-
127user_threshold/tests/test_res_users.py
-
19user_threshold/views/res_company_view.xml
-
22user_threshold/views/res_users_view.xml
@ -0,0 +1,95 @@ |
|||
.. image:: https://img.shields.io/badge/license-LGPL--3-blue.svg |
|||
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html |
|||
:alt: License: LGPL-3 |
|||
|
|||
============== |
|||
User Threshold |
|||
============== |
|||
|
|||
This module adds the ability to limit the amount of non-portal/public |
|||
users that exist in the database and per-company. |
|||
|
|||
It adds a group named `User Threshold Managers` which are the only users |
|||
who can alter the thresholds. |
|||
|
|||
This module also limits the ability of users to add membership |
|||
to the manager group to pre-existing members. By default, `Administrator` |
|||
is the only member of this group. |
|||
|
|||
Additionally, there is a flag that can be set on users so that they do not |
|||
count towards the user threshold. |
|||
|
|||
Using the `USER_THRESHOLD_HIDE` environment variable, you can also hide the |
|||
threshold exemption flag from users and the company setting for user |
|||
threshold. Setting this flag will also remove threshold exemptions for any |
|||
users who are not defined in the `USER_THRESHOLD_USER` environment variable. |
|||
|
|||
There are two modules available that also implement functionality similar to |
|||
what is provided in this module but in a more abstract way. They are: |
|||
|
|||
https://github.com/it-projects-llc/access-addons/tree/10.0/access_limit_records_number |
|||
https://github.com/it-projects-llc/access-addons/tree/10.0/access_restricted |
|||
|
|||
|
|||
Usage |
|||
===== |
|||
|
|||
A system parameter named `user.threshold.database` is added by default with |
|||
the value of '0' (Unlimited). Set this value to the total number of users |
|||
you wish to allow in the database. |
|||
|
|||
A field has been added to users to allow you to exempt them from the |
|||
thresholds. |
|||
|
|||
A field has been added to all companies, which allows you to define the max |
|||
number of users that the company can have. |
|||
|
|||
The following environment variables are available for your configuration ease: |
|||
|
|||
| Name | Description | |
|||
|------|-------------| |
|||
| USER_THRESHOLD_HIDE | Hide all threshold settings and default the exempt users to those defined by the USER_THRESHOLD_USERS variable |
|||
| USER_THRESHOLD_USER | White list of users who are exempt from the threshold. |
|||
|
|||
|
|||
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas |
|||
:alt: Try me on Runbot |
|||
:target: https://runbot.odoo-community.org/runbot/149/10.0 |
|||
|
|||
Bug Tracker |
|||
=========== |
|||
|
|||
Bugs are tracked on `GitHub Issues |
|||
`<https://github.com/OCA/server-tools/issues>`_. In case of trouble, please |
|||
check there if your issue has already been reported. If you spotted it first, |
|||
help us smash it by providing detailed and welcomed feedback. |
|||
|
|||
|
|||
Credits |
|||
======= |
|||
|
|||
Images |
|||
------ |
|||
|
|||
* Odoo Community Association: `Icon <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_. |
|||
|
|||
Contributors |
|||
------------ |
|||
|
|||
* Ted Salmon <tsalmon@laslabs.com> |
|||
|
|||
|
|||
Maintainer |
|||
---------- |
|||
|
|||
.. image:: https://odoo-community.org/logo.png |
|||
:alt: Odoo Community Association |
|||
:target: https://odoo-community.org |
|||
|
|||
This module is maintained by the OCA. |
|||
|
|||
OCA, or the Odoo Community Association, is a nonprofit organization whose |
|||
mission is to support the collaborative development of Odoo features and |
|||
promote its widespread use. |
|||
|
|||
To contribute to this module, please visit https://odoo-community.org. |
@ -0,0 +1,5 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2017 LasLabs Inc. |
|||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). |
|||
|
|||
from . import models |
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2017 LasLabs Inc. |
|||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). |
|||
{ |
|||
"name": "User Threshold", |
|||
"summary": "Add Configurable User Threshold Support", |
|||
"version": "10.0.1.0.0", |
|||
"category": "Authentication", |
|||
"website": "https://www.laslabs.com", |
|||
"author": "LasLabs, Odoo Community Association (OCA)", |
|||
"license": "LGPL-3", |
|||
"application": False, |
|||
'installable': True, |
|||
"data": [ |
|||
'data/user_threshold_data.xml', |
|||
'data/ir_config_parameter_data.xml', |
|||
'views/res_company_view.xml', |
|||
'views/res_users_view.xml', |
|||
], |
|||
} |
@ -0,0 +1,14 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!-- Copyright 2017 LasLabs Inc. |
|||
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). --> |
|||
|
|||
<odoo noupdate="1"> |
|||
|
|||
<record id="config_user_threshold" model="ir.config_parameter"> |
|||
<field name="key">user.threshold.database</field> |
|||
<field name="value">0</field> |
|||
<field name="group_ids" |
|||
eval="[(4, ref('user_threshold.group_threshold_manager'))]" /> |
|||
</record> |
|||
|
|||
</odoo> |
@ -0,0 +1,13 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!-- Copyright 2017 LasLabs Inc. |
|||
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). --> |
|||
|
|||
<odoo> |
|||
|
|||
<record id="group_threshold_manager" model="res.groups"> |
|||
<field name="name">User Threshold Manager</field> |
|||
<field name="category_id" ref="base.module_category_hidden"/> |
|||
<field name="users" eval="[(4, ref('base.user_root'))]" /> |
|||
</record> |
|||
|
|||
</odoo> |
@ -0,0 +1,9 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2017 LasLabs Inc. |
|||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). |
|||
|
|||
from . import ir_config_parameter |
|||
from . import res_company |
|||
from . import res_groups |
|||
from . import res_users |
|||
|
@ -0,0 +1,45 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2017 LasLabs Inc. |
|||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). |
|||
|
|||
import os |
|||
|
|||
from odoo import _, api, models |
|||
from odoo.exceptions import AccessError |
|||
|
|||
from .res_groups import THRESHOLD_MANAGER |
|||
|
|||
MAX_DB_USER_PARAM = 'user.threshold.database' |
|||
THRESHOLD_HIDE = str(os.environ.get('USER_THRESHOLD_HIDE', '')) == '1' |
|||
|
|||
|
|||
class IrConfigParameter(models.Model): |
|||
_inherit = 'ir.config_parameter' |
|||
|
|||
@api.multi |
|||
def unlink(self): |
|||
""" |
|||
Override to disallow deletion of the user threshold parameter |
|||
when the user does not have the right access |
|||
""" |
|||
for rec in self.filtered(lambda r: r.key == MAX_DB_USER_PARAM): |
|||
if not self.env.user.has_group(THRESHOLD_MANAGER): |
|||
raise AccessError(_( |
|||
'You must be a member of the `User Threshold Manager` ' |
|||
'to delete this parameter' |
|||
)) |
|||
return super(IrConfigParameter, self).unlink() |
|||
|
|||
@api.multi |
|||
def write(self, vals): |
|||
""" |
|||
Override to disallow manipulation of the user threshold parameter |
|||
when the user does not have the right access |
|||
""" |
|||
for rec in self.filtered(lambda r: r.key == MAX_DB_USER_PARAM): |
|||
if not self.env.user.has_group(THRESHOLD_MANAGER): |
|||
raise AccessError(_( |
|||
'You must be a member of the `User Threshold Manager` ' |
|||
'to set this parameter' |
|||
)) |
|||
return super(IrConfigParameter, self).write(vals) |
@ -0,0 +1,47 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2017 LasLabs Inc. |
|||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). |
|||
|
|||
from lxml import etree |
|||
|
|||
from odoo import _, api, fields, models |
|||
from odoo.exceptions import AccessError |
|||
|
|||
from .ir_config_parameter import THRESHOLD_HIDE |
|||
from .res_groups import THRESHOLD_MANAGER |
|||
|
|||
|
|||
class ResCompany(models.Model): |
|||
_inherit = 'res.company' |
|||
|
|||
max_users = fields.Integer( |
|||
'Maximum Number of users allowed for this company', |
|||
) |
|||
|
|||
@api.model |
|||
def fields_view_get(self, view_id=None, view_type='form', toolbar=False, |
|||
submenu=False): |
|||
""" Hide Max User Field when the env var to hide the field is set """ |
|||
res = super(ResCompany, self).fields_view_get( |
|||
view_id, view_type, toolbar, submenu |
|||
) |
|||
if THRESHOLD_HIDE: |
|||
doc = etree.XML(res['arch']) |
|||
for node in doc.xpath("//field[@name='max_users']"): |
|||
node.getparent().remove(node) |
|||
res['arch'] = etree.tostring(doc, pretty_print=True) |
|||
return res |
|||
|
|||
@api.multi |
|||
def write(self, vals): |
|||
""" |
|||
Override to disallow manipulation of the user threshold parameter |
|||
when the user does not have the right access |
|||
""" |
|||
is_manager = self.env.user.has_group(THRESHOLD_MANAGER) |
|||
if vals.get('max_users') and not is_manager: |
|||
raise AccessError(_( |
|||
'You must be a member of the `User Threshold Manager` to set ' |
|||
'this parameter' |
|||
)) |
|||
return super(ResCompany, self).write(vals) |
@ -0,0 +1,27 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2017 LasLabs Inc. |
|||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). |
|||
|
|||
from odoo import _, api, models |
|||
from odoo.exceptions import AccessError |
|||
|
|||
THRESHOLD_MANAGER = 'user_threshold.group_threshold_manager' |
|||
|
|||
|
|||
class ResGroups(models.Model): |
|||
_inherit = 'res.groups' |
|||
|
|||
@api.multi |
|||
def write(self, vals): |
|||
""" Override write to verify that membership of the Threshold Manager |
|||
group is not able to be set by users outside that group |
|||
""" |
|||
manager = self.env.ref(THRESHOLD_MANAGER, raise_if_not_found=False) |
|||
if manager: |
|||
is_manager = self.env.user.has_group(THRESHOLD_MANAGER) |
|||
if not is_manager and manager in self: |
|||
raise AccessError(_( |
|||
'You must be a member of the `User Threshold Manager` ' |
|||
'group to grant access to it.' |
|||
)) |
|||
return super(ResGroups, self).write(vals) |
@ -0,0 +1,130 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2017 LasLabs Inc. |
|||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). |
|||
|
|||
import os |
|||
from csv import reader |
|||
from lxml import etree |
|||
|
|||
from odoo import SUPERUSER_ID, _, api, fields, models, registry |
|||
from odoo.exceptions import AccessError, ValidationError |
|||
|
|||
from .ir_config_parameter import THRESHOLD_HIDE, MAX_DB_USER_PARAM |
|||
from .res_groups import THRESHOLD_MANAGER |
|||
|
|||
|
|||
class ResUsers(models.Model): |
|||
_inherit = 'res.users' |
|||
|
|||
threshold_exempt = fields.Boolean( |
|||
'Exempt User From User Count Thresholds', |
|||
) |
|||
|
|||
def __init__(self, pool, cr): |
|||
""" |
|||
Override to check if env var to hide threshold configuration and |
|||
reset the database state is set. If it is, run those actions |
|||
""" |
|||
if THRESHOLD_HIDE: |
|||
exempt_users_var = os.environ.get('USER_THRESHOLD_USER', '') |
|||
exempt_users = reader([exempt_users_var]) |
|||
with api.Environment.manage(): |
|||
with registry(cr.dbname).cursor() as new_cr: |
|||
new_env = api.Environment(new_cr, SUPERUSER_ID, {}) |
|||
installed = new_env['ir.module.module'].search_count([ |
|||
('name', '=', 'user_threshold'), |
|||
('state', '=', 'installed'), |
|||
]) |
|||
if installed: |
|||
users = new_env['res.users'].search([ |
|||
('share', '=', False), |
|||
('threshold_exempt', '=', True), |
|||
]) |
|||
non_ex = users.filtered( |
|||
lambda r: r.login not in exempt_users |
|||
) |
|||
for user in non_ex: |
|||
user.threshold_exempt = False |
|||
new_cr.commit() |
|||
|
|||
def _check_thresholds(self): |
|||
""" |
|||
Check to see if any user thresholds are met |
|||
Returns: |
|||
False when the thresholds aren't met and True when they are |
|||
""" |
|||
domain = [ |
|||
('threshold_exempt', '=', False), |
|||
('share', '=', False), |
|||
] |
|||
users = self.env['res.users'].search(domain) |
|||
max_db_users = int(self.env['ir.config_parameter'].get_param( |
|||
MAX_DB_USER_PARAM |
|||
)) |
|||
if max_db_users > 0 and len(users) >= max_db_users: |
|||
return True |
|||
company = self.env.user.company_id |
|||
company_users = users.filtered(lambda r: r.company_id.id == company.id) |
|||
if company.max_users > 0 and len(company_users) >= company.max_users: |
|||
return True |
|||
return False |
|||
|
|||
@api.multi |
|||
def copy(self, default=None): |
|||
""" |
|||
Override method to make sure the Thresholds aren't met before |
|||
creating a new user |
|||
""" |
|||
if self._check_thresholds(): |
|||
raise ValidationError(_( |
|||
'Cannot add user - Maximum number of allowed users reached' |
|||
)) |
|||
return super(ResUsers, self).copy(default=default) |
|||
|
|||
@api.multi |
|||
def create(self, vals): |
|||
""" |
|||
Override method to make sure the Thresholds aren't met before |
|||
creating a new user |
|||
""" |
|||
if self._check_thresholds(): |
|||
raise ValidationError(_( |
|||
'Cannot add user - Maximum number of allowed users reached' |
|||
)) |
|||
return super(ResUsers, self).create(vals) |
|||
|
|||
@api.model |
|||
def fields_view_get(self, view_id=None, view_type='form', toolbar=False, |
|||
submenu=False): |
|||
""" Hide Max User Field when the env var to hide the field is set """ |
|||
res = super(ResUsers, self).fields_view_get( |
|||
view_id, view_type, toolbar, submenu |
|||
) |
|||
if THRESHOLD_HIDE: |
|||
doc = etree.XML(res['arch']) |
|||
for node in doc.xpath("//group[@name='user_threshold']"): |
|||
node.getparent().remove(node) |
|||
res['arch'] = etree.tostring(doc, pretty_print=True) |
|||
return res |
|||
|
|||
@api.multi |
|||
def write(self, vals): |
|||
""" |
|||
Override write to verify that membership of the Threshold Manager |
|||
group is not able to be set by users outside that group |
|||
""" |
|||
thold_group = self.env.ref(THRESHOLD_MANAGER, raise_if_not_found=False) |
|||
if thold_group: |
|||
user_is_manager = self.env.user.has_group(THRESHOLD_MANAGER) |
|||
if vals.get('threshold_exempt') and not user_is_manager: |
|||
raise AccessError(_( |
|||
'You must be a member of the `User Threshold Manager`' |
|||
' group to grant threshold exemptions.' |
|||
)) |
|||
is_add_group = vals.get('in_group_%s' % thold_group.id) |
|||
if is_add_group and not user_is_manager: |
|||
raise AccessError(_( |
|||
'You must be a member of the `User Threshold Manager`' |
|||
' group to grant access to it.' |
|||
)) |
|||
return super(ResUsers, self).write(vals) |
@ -0,0 +1,8 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2017 LasLabs Inc. |
|||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). |
|||
|
|||
from . import test_ir_config_parameter |
|||
from . import test_res_company |
|||
from . import test_res_groups |
|||
from . import test_res_users |
@ -0,0 +1,31 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2017 LasLabs Inc. |
|||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). |
|||
|
|||
import random |
|||
import string |
|||
|
|||
from odoo.tests.common import TransactionCase |
|||
|
|||
MAX_DB_USER_PARAM = 'user.threshold.database' |
|||
|
|||
|
|||
class Common(TransactionCase): |
|||
|
|||
def _create_test_user(self): |
|||
""" Create a user for testing """ |
|||
user = self.env.ref('base.user_demo').copy() |
|||
rand_name = ''.join([ |
|||
random.choice(string.ascii_letters) for n in xrange(10) |
|||
]) |
|||
user.write({'login': rand_name}) |
|||
return user |
|||
|
|||
def _add_user_to_group(self, user): |
|||
""" Add a given user Record to the threshold manager group """ |
|||
th_group = self.env.ref('user_threshold.group_threshold_manager') |
|||
system_group = self.env.ref('base.group_system') |
|||
user.write({ |
|||
'in_group_%s' % th_group.id: True, |
|||
'in_group_%s' % system_group.id: True |
|||
}) |
@ -0,0 +1,87 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2017 LasLabs Inc. |
|||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). |
|||
|
|||
from odoo.exceptions import AccessError |
|||
from .common import Common, MAX_DB_USER_PARAM |
|||
|
|||
|
|||
class TestIrConfigParameter(Common): |
|||
|
|||
def _get_param(self): |
|||
return self.env['ir.config_parameter'].search([ |
|||
('key', '=', MAX_DB_USER_PARAM), |
|||
]) |
|||
|
|||
def test_can_set(self): |
|||
""" |
|||
It should test that users in the Threshold Manager group can |
|||
update the parameter |
|||
""" |
|||
mdl = self.env['ir.config_parameter'] |
|||
u = self._create_test_user() |
|||
self._add_user_to_group(u) |
|||
exp = '20' |
|||
mdl.sudo(u.id).set_param(MAX_DB_USER_PARAM, exp) |
|||
self.assertEquals(mdl.get_param(MAX_DB_USER_PARAM), exp) |
|||
|
|||
def test_cannot_set(self): |
|||
""" |
|||
It should test that users NOT in the Threshold Manager group |
|||
cannot alter the parameter |
|||
""" |
|||
u = self._create_test_user() |
|||
with self.assertRaises(AccessError): |
|||
self.env['ir.config_parameter'].sudo(u.id).set_param( |
|||
MAX_DB_USER_PARAM, 20 |
|||
) |
|||
|
|||
def test_can_unlink(self): |
|||
""" |
|||
It should test that users in the Threshold Manager group can |
|||
unlink the Threshold Param |
|||
""" |
|||
u = self._create_test_user() |
|||
self._add_user_to_group(u) |
|||
param = self._get_param() |
|||
self.assertTrue(param.sudo(u.id).unlink()) |
|||
|
|||
def test_cannot_unlink(self): |
|||
""" |
|||
It should test that users outside the Threshold Manager group |
|||
cannot unlink the Threshold Param |
|||
""" |
|||
u = self._create_test_user() |
|||
param = self._get_param() |
|||
system_group = self.env.ref('base.group_system') |
|||
u.write({'in_group_%s' % system_group.id: True}) |
|||
with self.assertRaises(AccessError): |
|||
param.sudo(u.id).unlink() |
|||
|
|||
def test_can_write(self): |
|||
""" |
|||
It should test that users in the Threshold Manager group can |
|||
write the Threshold Param |
|||
""" |
|||
u = self._create_test_user() |
|||
self._add_user_to_group(u) |
|||
param = self._get_param() |
|||
res = '10' |
|||
param.sudo(u.id).write({'value': res}) |
|||
self.assertEquals(param.value, res) |
|||
|
|||
def test_cannot_write(self): |
|||
""" |
|||
It should test that users outside the Threshold Manager group |
|||
cannot write the Threshold Param |
|||
""" |
|||
u = self._create_test_user() |
|||
system_group = self.env.ref('base.group_system') |
|||
access_group = self.env.ref('base.group_erp_manager') |
|||
u.write({ |
|||
'in_group_%s' % system_group.id: True, |
|||
'in_group_%s' % access_group.id: True, |
|||
}) |
|||
param = self._get_param() |
|||
with self.assertRaises(AccessError): |
|||
param.sudo(u.id).write({'value': '10'}) |
@ -0,0 +1,44 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2017 LasLabs Inc. |
|||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). |
|||
|
|||
from lxml import etree |
|||
|
|||
from odoo.exceptions import AccessError |
|||
from .common import Common |
|||
|
|||
|
|||
class TestResCompany(Common): |
|||
|
|||
def test_fields_view_get(self): |
|||
""" |
|||
It should verify that setting THRESHOLD_HIDE removes the parameter |
|||
from the view |
|||
""" |
|||
import odoo.addons.user_threshold.models.res_company as mdl |
|||
mdl.THRESHOLD_HIDE = True |
|||
view = self.env.ref('user_threshold.view_company_form') |
|||
c = self.env['res.company'].browse(1) |
|||
ret = c.fields_view_get(view.id) |
|||
doc = etree.XML(ret['arch']) |
|||
self.assertEquals(doc.xpath("//field[@name='max_users']"), []) |
|||
|
|||
def test_can_write_max_users(self): |
|||
""" |
|||
It should restrict the max users parameter to Threshold Managers |
|||
""" |
|||
u = self._create_test_user() |
|||
self._add_user_to_group(u) |
|||
c = self.env['res.company'].browse(1) |
|||
res = 10 |
|||
c.sudo(u.id).write({'max_users': res}) |
|||
self.assertEquals(c.max_users, res) |
|||
|
|||
def test_cannot_write_max_users(self): |
|||
""" |
|||
It should restrict the max users parameter to Threshold Managers |
|||
""" |
|||
u = self._create_test_user() |
|||
c = self.env['res.company'].browse(1) |
|||
with self.assertRaises(AccessError): |
|||
c.sudo(u.id).write({'max_users': 10}) |
@ -0,0 +1,34 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2017 LasLabs Inc. |
|||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). |
|||
|
|||
from odoo.exceptions import AccessError |
|||
from .common import Common |
|||
|
|||
|
|||
class TestResGroups(Common): |
|||
|
|||
def test_can_write_max_users(self): |
|||
""" |
|||
It should restrict membership additions to Threshold Managers to |
|||
pre-existing members of that group |
|||
""" |
|||
u = self._create_test_user() |
|||
u.write({ |
|||
'in_group_%s' % self.env.ref('base.group_erp_manager').id: True |
|||
}) |
|||
g = self.env.ref('user_threshold.group_threshold_manager') |
|||
with self.assertRaises(AccessError): |
|||
g.sudo(u.id).write({'users': self.env.ref('base.user_demo').id}) |
|||
|
|||
def test_cannot_write_max_users(self): |
|||
""" |
|||
It should restrict membership additions to Threshold Managers to |
|||
pre-existing members of that group |
|||
""" |
|||
u = self._create_test_user() |
|||
self._add_user_to_group(u) |
|||
g = self.env.ref('user_threshold.group_threshold_manager') |
|||
demo_user = self.env.ref('base.user_demo') |
|||
g.sudo(u.id).write({'users': [(4, [demo_user.id])]}) |
|||
self.assertTrue(demo_user.id in g.users.ids) |
@ -0,0 +1,127 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2017 LasLabs Inc. |
|||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). |
|||
|
|||
from lxml import etree |
|||
|
|||
from odoo.exceptions import AccessError, ValidationError |
|||
from .common import Common, MAX_DB_USER_PARAM |
|||
|
|||
|
|||
class TestResUsers(Common): |
|||
|
|||
def setUp(self): |
|||
super(TestResUsers, self).setUp() |
|||
self.env['ir.config_parameter'].set_param(MAX_DB_USER_PARAM, '0') |
|||
|
|||
def test_copy_global(self): |
|||
""" |
|||
It should restrict the user count in copy() as prescribed by the |
|||
global threshold parameter |
|||
""" |
|||
self.env['ir.config_parameter'].set_param(MAX_DB_USER_PARAM, 3) |
|||
self._create_test_user() |
|||
with self.assertRaises(ValidationError): |
|||
self._create_test_user() |
|||
|
|||
def test_create_global(self): |
|||
""" |
|||
It should restrict the user count as prescribed by the global |
|||
threshold parameter |
|||
""" |
|||
self.env['ir.config_parameter'].set_param(MAX_DB_USER_PARAM, 3) |
|||
self._create_test_user() |
|||
with self.assertRaises(ValidationError): |
|||
self.env['res.users'].create({ |
|||
'login': 'Derp Derpington', |
|||
'email': 'dderpington@example.com', |
|||
'notify_email': 'always', |
|||
}) |
|||
|
|||
def test_copy_company(self): |
|||
""" |
|||
It should restrict the user count in copy() as prescribed by the |
|||
companies threshold parameter |
|||
""" |
|||
c = self.env['res.company'].browse(1) |
|||
c.max_users = 3 |
|||
self._create_test_user() |
|||
with self.assertRaises(ValidationError): |
|||
self._create_test_user() |
|||
|
|||
def test_create_company(self): |
|||
""" |
|||
It should restrict the user count as prescribed by the companies |
|||
threshold parameter |
|||
""" |
|||
c = self.env['res.company'].browse(1) |
|||
c.max_users = 3 |
|||
self._create_test_user() |
|||
with self.assertRaises(ValidationError): |
|||
self.env['res.users'].create({ |
|||
'login': 'Derp Derpington', |
|||
'email': 'dderpington@example.com', |
|||
'notify_email': 'always', |
|||
}) |
|||
|
|||
def test_fields_view_get(self): |
|||
""" |
|||
It should verify that setting THRESHOLD_HIDE removes the parameter |
|||
from the view |
|||
""" |
|||
import odoo.addons.user_threshold.models.res_users as mdl |
|||
mdl.THRESHOLD_HIDE = True |
|||
view = self.env.ref('user_threshold.view_users_form') |
|||
u = self._create_test_user() |
|||
ret = u.fields_view_get(view.id) |
|||
doc = etree.XML(ret['arch']) |
|||
self.assertEquals(doc.xpath("//group[@name='user_threshold']"), []) |
|||
|
|||
def test_cannot_write_exempt(self): |
|||
""" |
|||
It should restrict the threshold exempt parameter to Threshold |
|||
Managers |
|||
""" |
|||
u = self._create_test_user() |
|||
tu = self._create_test_user() |
|||
with self.assertRaises(AccessError): |
|||
tu.sudo(u.id).write({'threshold_exempt': True}) |
|||
|
|||
def test_can_write_exempt(self): |
|||
""" |
|||
It should restrict the threshold exempt parameter to Threshold |
|||
Managers |
|||
""" |
|||
u = self._create_test_user() |
|||
self._add_user_to_group(u) |
|||
tu = self._create_test_user() |
|||
tu.sudo(u.id).write({'threshold_exempt': True}) |
|||
self.assertEquals(tu.threshold_exempt, True) |
|||
|
|||
def test_cannot_write_group(self): |
|||
""" |
|||
It should restrict additions to the Threshold Managers to users in |
|||
that group |
|||
""" |
|||
u = self._create_test_user() |
|||
u.write({ |
|||
'in_group_%s' % self.env.ref('base.group_erp_manager').id: True |
|||
}) |
|||
tu = self._create_test_user() |
|||
th_group = self.env.ref('user_threshold.group_threshold_manager') |
|||
with self.assertRaises(AccessError): |
|||
tu.sudo(u.id).write({'in_group_%s' % th_group.id: True}) |
|||
|
|||
def test_can_write_group(self): |
|||
""" |
|||
It should restrict additions to the Threshold Managers to users in |
|||
that group |
|||
""" |
|||
u = self._create_test_user() |
|||
self._add_user_to_group(u) |
|||
tu = self._create_test_user() |
|||
th_group = self.env.ref('user_threshold.group_threshold_manager') |
|||
tu.sudo(u.id).write({'in_group_%s' % th_group.id: True}) |
|||
self.assertEquals( |
|||
tu.has_group('user_threshold.group_threshold_manager'), True |
|||
) |
@ -0,0 +1,19 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!-- Copyright 2017 LasLabs Inc. |
|||
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). |
|||
--> |
|||
|
|||
<odoo> |
|||
|
|||
<record id="view_company_form" model="ir.ui.view"> |
|||
<field name="name">res.company.form</field> |
|||
<field name="model">res.company</field> |
|||
<field name="inherit_id" ref="base.view_company_form" /> |
|||
<field name="arch" type="xml"> |
|||
<xpath expr="//notebook/page[1]/group/group[1]" position="inside"> |
|||
<field string="Maximum Users" name="max_users" /> |
|||
</xpath> |
|||
</field> |
|||
</record> |
|||
|
|||
</odoo> |
@ -0,0 +1,22 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!-- Copyright 2017 LasLabs Inc. |
|||
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). |
|||
--> |
|||
|
|||
<odoo> |
|||
|
|||
<record id="view_users_form" model="ir.ui.view"> |
|||
<field name="name">res.users.form</field> |
|||
<field name="model">res.users</field> |
|||
<field name="inherit_id" ref="base.view_users_form" /> |
|||
<field name="arch" type="xml"> |
|||
<xpath expr="//page[@name='access_rights']" position="inside"> |
|||
<group name="user_threshold" string="User Threshold"> |
|||
<field name="threshold_exempt" |
|||
string="Exempt From Threshold" /> |
|||
</group> |
|||
</xpath> |
|||
</field> |
|||
</record> |
|||
|
|||
</odoo> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue