Files
odoo_source/addons/hr/tests/test_self_user_access.py
T
RomainLibert c9ca376146 [IMP] hr: Introduce the public employee profile
Purpose
=======

1/ Robustness & security: right now it is not easy to understand and do something
   clean in term of security (hr people vs employees, private info vs public). A
   HR officer doesn't know if he can write something on the chatter. Currently, a
   note will be visible for all the employees who have access to the employee form
   view for example.
2/ In term of business, it makes sense to let a hr manages payroll stuff (contract,
   employees private information, ... and other employee see public information
   (résumé and work information)

Specification
=============

Introduce 2 new models:

- hr.employee.base (AbstractModel): This represents the basic skeleton
  model on which the shared fields and methods between the public and
  the private employees models.
- hr.employee.public (_auto=False): This is a sql view based on the
  employee values, readable for an internal user (i.e. an employee).

The model hr.employee is not readable anymore for an employee.

There are now 3 ways to access the employee data:
1/ From the hr.employee views. HR officer access rights are required
2/ From the public profile. The public data for an employee are accessible
   but can't be modified.
3/ From the 'My Profile' menu. A classic employee can access its own
   data from there, and can modify them.
2019-05-31 10:21:20 +02:00

120 lines
5.2 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from collections import OrderedDict
from odoo.addons.hr.tests.common import TestHrCommon
from odoo.tests import new_test_user
from odoo.exceptions import AccessError
class TestSelfAccessRights(TestHrCommon):
def setUp(self):
super(TestSelfAccessRights, self).setUp()
self.richard = new_test_user(self.env, login='ric', groups='base.group_user', name='Simple employee', email='ric@example.com')
self.richard_emp = self.env['hr.employee'].create({
'name': 'Richard',
'user_id': self.richard.id,
'address_home_id': self.env['res.partner'].create({'name': 'Richard', 'phone': '21454', 'type': 'private'}).id,
})
self.hubert = new_test_user(self.env, login='hub', groups='base.group_user', name='Simple employee', email='hub@example.com')
self.hubert_emp = self.env['hr.employee'].create({
'name': 'Hubert',
'user_id': self.hubert.id,
'address_home_id': self.env['res.partner'].create({'name': 'Hubert', 'type': 'private'}).id,
})
self.protected_fields_emp = OrderedDict([(k, v) for k, v in self.env['hr.employee']._fields.items() if v.groups == 'hr.group_hr_user'])
# Compute fields and id field are always readable by everyone
self.read_protected_fields_emp = OrderedDict([(k, v) for k, v in self.env['hr.employee']._fields.items() if not v.compute and k != 'id'])
self.self_protected_fields_user = OrderedDict([
(k, v)
for k, v in self.env['res.users']._fields.items()
if v.groups == 'hr.group_hr_user' and k in self.env['res.users'].SELF_READABLE_FIELDS
])
# Read hr.employee #
def testReadSelfEmployee(self):
with self.assertRaises(AccessError):
self.hubert_emp.sudo(self.richard).read(self.protected_fields_emp.keys())
def testReadOtherEmployee(self):
with self.assertRaises(AccessError):
self.hubert_emp.sudo(self.richard).read(self.protected_fields_emp.keys())
# Write hr.employee #
def testWriteSelfEmployee(self):
for f in self.protected_fields_emp:
with self.assertRaises(AccessError):
self.richard_emp.sudo(self.richard).write({f: 'dummy'})
def testWriteOtherEmployee(self):
for f in self.protected_fields_emp:
with self.assertRaises(AccessError):
self.hubert_emp.sudo(self.richard).write({f: 'dummy'})
# Read res.users #
def testReadSelfUserEmployee(self):
for f in self.self_protected_fields_user:
self.richard.sudo(self.richard).read([f]) # should not raise
def testReadOtherUserEmployee(self):
with self.assertRaises(AccessError):
self.hubert.sudo(self.richard).read(self.self_protected_fields_user)
# Write res.users #
def testWriteSelfUserEmployeeSettingFalse(self):
for f, v in self.self_protected_fields_user.items():
with self.assertRaises(AccessError):
self.richard.sudo(self.richard).write({f: 'dummy'})
def testWriteSelfUserEmployee(self):
self.env['ir.config_parameter'].set_param('hr.hr_employee_self_edit', True)
for f, v in self.self_protected_fields_user.items():
val = None
if v.type == 'char' or v.type == 'text':
val = '0000' if f == 'pin' else 'dummy'
if val is not None:
self.richard.sudo(self.richard).write({f: val})
def testWriteSelfUserPreferencesEmployee(self):
# self should always be able to update non hr.employee fields if
# they are in SELF_READABLE_FIELDS
self.env['ir.config_parameter'].set_param('hr.hr_employee_self_edit', False)
# should not raise
vals = [
{'tz': "Australia/ACT"},
{'email': "new@example.com"},
{'signature': "<p>I'm Richard!</p>"},
{'notification_type': "email"},
]
for v in vals:
# should not raise
self.richard.sudo(self.richard).write(v)
def testWriteOtherUserPreferencesEmployee(self):
# self should always be able to update non hr.employee fields if
# they are in SELF_READABLE_FIELDS
self.env['ir.config_parameter'].set_param('hr.hr_employee_self_edit', False)
vals = [
{'tz': "Australia/ACT"},
{'email': "new@example.com"},
{'signature': "<p>I'm Richard!</p>"},
{'notification_type': "email"},
]
for v in vals:
with self.assertRaises(AccessError):
self.hubert.sudo(self.richard).write(v)
def testWriteSelfPhoneEmployee(self):
# phone is a related from res.partner (from base) but added in SELF_READABLE_FIELDS
self.env['ir.config_parameter'].set_param('hr.hr_employee_self_edit', False)
with self.assertRaises(AccessError):
self.richard.sudo(self.richard).write({'phone': '2154545'})
def testWriteOtherUserEmployee(self):
for f in self.self_protected_fields_user:
with self.assertRaises(AccessError):
self.hubert.sudo(self.richard).write({f: 'dummy'})