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