Purpose ======= Change all masculine nouns in Odoo's code to neutral nouns (when possible), making sure that demo data is correctly handled. This is particularly important since our code is open source, and nowadays lots of machine learning models are trained on open source repositories. With this small change we contribute to training more "fair" models, and teaching models that "employee" or "user" != "he". This also affects some text visible by the user, hence making it more inclusive for Odoo users. Task-2853046 closes odoo/odoo#91292 Related: odoo/enterprise#27302 Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
300 lines
14 KiB
Python
300 lines
14 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo.addons.website_slides.tests import common
|
|
from odoo.exceptions import AccessError
|
|
from odoo.tests import tagged
|
|
from odoo.tools import mute_logger
|
|
|
|
|
|
@tagged('security')
|
|
class TestAccess(common.SlidesCase):
|
|
|
|
@mute_logger('odoo.models', 'odoo.addons.base.models.ir_rule')
|
|
def test_access_channel_invite(self):
|
|
""" Invite channels don't give enroll if not member """
|
|
self.channel.write({'enroll': 'invite'})
|
|
|
|
self.channel.with_user(self.user_officer).read(['name'])
|
|
self.channel.with_user(self.user_manager).read(['name'])
|
|
self.channel.with_user(self.user_emp).read(['name'])
|
|
self.channel.with_user(self.user_portal).read(['name'])
|
|
self.channel.with_user(self.user_public).read(['name'])
|
|
|
|
self.slide.with_user(self.user_officer).read(['name'])
|
|
self.slide.with_user(self.user_manager).read(['name'])
|
|
|
|
with self.assertRaises(AccessError):
|
|
self.slide.with_user(self.user_emp).read(['name'])
|
|
with self.assertRaises(AccessError):
|
|
self.slide.with_user(self.user_portal).read(['name'])
|
|
with self.assertRaises(AccessError):
|
|
self.slide.with_user(self.user_portal).read(['name'])
|
|
|
|
# if member -> can read
|
|
membership = self.env['slide.channel.partner'].create({
|
|
'channel_id': self.channel.id,
|
|
'partner_id': self.user_emp.partner_id.id,
|
|
})
|
|
self.channel.with_user(self.user_emp).read(['name'])
|
|
self.slide.with_user(self.user_emp).read(['name'])
|
|
|
|
# not member anymore -> cannot read
|
|
membership.unlink()
|
|
self.channel.with_user(self.user_emp).read(['name'])
|
|
with self.assertRaises(AccessError):
|
|
self.slide.with_user(self.user_emp).read(['name'])
|
|
|
|
@mute_logger('odoo.models', 'odoo.addons.base.models.ir_rule')
|
|
def test_access_channel_public(self):
|
|
""" Public channels don't give enroll if not member """
|
|
self.channel.write({'enroll': 'public'})
|
|
|
|
self.channel.with_user(self.user_officer).read(['name'])
|
|
self.channel.with_user(self.user_manager).read(['name'])
|
|
self.channel.with_user(self.user_emp).read(['name'])
|
|
self.channel.with_user(self.user_portal).read(['name'])
|
|
self.channel.with_user(self.user_public).read(['name'])
|
|
|
|
self.slide.with_user(self.user_officer).read(['name'])
|
|
self.slide.with_user(self.user_manager).read(['name'])
|
|
|
|
with self.assertRaises(AccessError):
|
|
self.slide.with_user(self.user_emp).read(['name'])
|
|
with self.assertRaises(AccessError):
|
|
self.slide.with_user(self.user_portal).read(['name'])
|
|
with self.assertRaises(AccessError):
|
|
self.slide.with_user(self.user_public).read(['name'])
|
|
|
|
@mute_logger('odoo.models', 'odoo.addons.base.models.ir_rule')
|
|
def test_access_channel_publish(self):
|
|
""" Unpublished channels and their content are visible only to eLearning people """
|
|
self.channel.write({'is_published': False, 'enroll': 'public'})
|
|
self.channel.flush(['is_published', 'website_published', 'enroll'])
|
|
|
|
# channel available only to eLearning
|
|
self.channel.invalidate_cache(['name'])
|
|
self.channel.with_user(self.user_officer).read(['name'])
|
|
self.channel.invalidate_cache(['name'])
|
|
self.channel.with_user(self.user_manager).read(['name'])
|
|
with self.assertRaises(AccessError):
|
|
self.channel.invalidate_cache(['name'])
|
|
self.channel.with_user(self.user_emp).read(['name'])
|
|
with self.assertRaises(AccessError):
|
|
self.channel.invalidate_cache(['name'])
|
|
self.channel.with_user(self.user_portal).read(['name'])
|
|
with self.assertRaises(AccessError):
|
|
self.channel.invalidate_cache(['name'])
|
|
self.channel.with_user(self.user_public).read(['name'])
|
|
|
|
# slide available only to eLearning
|
|
self.channel.invalidate_cache(['name'])
|
|
self.slide.with_user(self.user_officer).read(['name'])
|
|
self.channel.invalidate_cache(['name'])
|
|
self.slide.with_user(self.user_manager).read(['name'])
|
|
with self.assertRaises(AccessError):
|
|
self.slide.invalidate_cache(['name'])
|
|
self.slide.with_user(self.user_emp).read(['name'])
|
|
with self.assertRaises(AccessError):
|
|
self.slide.invalidate_cache(['name'])
|
|
self.slide.with_user(self.user_portal).read(['name'])
|
|
with self.assertRaises(AccessError):
|
|
self.slide.invalidate_cache(['name'])
|
|
self.slide.with_user(self.user_public).read(['name'])
|
|
|
|
# even members cannot see unpublished content
|
|
self.env['slide.channel.partner'].create({
|
|
'channel_id': self.channel.id,
|
|
'partner_id': self.user_emp.partner_id.id,
|
|
})
|
|
with self.assertRaises(AccessError):
|
|
self.channel.invalidate_cache(['name'])
|
|
self.channel.with_user(self.user_emp).read(['name'])
|
|
with self.assertRaises(AccessError):
|
|
self.slide.invalidate_cache(['name'])
|
|
self.slide.with_user(self.user_emp).read(['name'])
|
|
|
|
# publish channel but content unpublished (even if can be previewed) still unavailable
|
|
self.channel.write({'is_published': True})
|
|
self.slide.write({
|
|
'is_preview': True,
|
|
'is_published': False,
|
|
})
|
|
self.channel.flush(['website_published'])
|
|
self.slide.flush(['is_preview', 'website_published'])
|
|
|
|
self.slide.invalidate_cache(['name'])
|
|
self.slide.with_user(self.user_officer).read(['name'])
|
|
self.slide.invalidate_cache(['name'])
|
|
self.slide.with_user(self.user_manager).read(['name'])
|
|
with self.assertRaises(AccessError):
|
|
self.slide.invalidate_cache(['name'])
|
|
self.slide.with_user(self.user_emp).read(['name'])
|
|
with self.assertRaises(AccessError):
|
|
self.slide.invalidate_cache(['name'])
|
|
self.slide.with_user(self.user_portal).read(['name'])
|
|
with self.assertRaises(AccessError):
|
|
self.slide.invalidate_cache(['name'])
|
|
self.slide.with_user(self.user_public).read(['name'])
|
|
|
|
@mute_logger('odoo.models', 'odoo.addons.base.models.ir_rule')
|
|
def test_access_slide_preview(self):
|
|
""" Slides with preview flag are always visible even to non members if published """
|
|
self.channel.write({'enroll': 'invite'})
|
|
self.slide.write({'is_preview': True})
|
|
self.slide.flush(['is_preview'])
|
|
|
|
self.slide.with_user(self.user_officer).read(['name'])
|
|
self.slide.with_user(self.user_manager).read(['name'])
|
|
self.slide.with_user(self.user_emp).read(['name'])
|
|
self.slide.with_user(self.user_portal).read(['name'])
|
|
self.slide.with_user(self.user_public).read(['name'])
|
|
|
|
|
|
@tagged('functional', 'security')
|
|
class TestRemoveMembership(common.SlidesCase):
|
|
|
|
def setUp(self):
|
|
super(TestRemoveMembership, self).setUp()
|
|
self.channel_partner = self.env['slide.channel.partner'].create({
|
|
'channel_id': self.channel.id,
|
|
'partner_id': self.customer.id,
|
|
})
|
|
|
|
self.slide_partner = self.env['slide.slide.partner'].create({
|
|
'slide_id': self.slide.id,
|
|
'channel_id': self.channel.id,
|
|
'partner_id': self.customer.id
|
|
})
|
|
|
|
def test_security_unlink(self):
|
|
# Only the publisher can unlink channel_partner (and slide_partner by extension)
|
|
with self.assertRaises(AccessError):
|
|
self.channel_partner.with_user(self.user_public).unlink()
|
|
with self.assertRaises(AccessError):
|
|
self.channel_partner.with_user(self.user_portal).unlink()
|
|
with self.assertRaises(AccessError):
|
|
self.channel_partner.with_user(self.user_emp).unlink()
|
|
|
|
def test_slide_partner_remove(self):
|
|
id_slide_partner = self.slide_partner.id
|
|
id_channel_partner = self.channel_partner.id
|
|
self.channel_partner.with_user(self.user_officer).unlink()
|
|
self.assertFalse(self.env['slide.channel.partner'].search([('id', '=', '%d' % id_channel_partner)]))
|
|
# Slide(s) related to the channel and the partner is unlink too.
|
|
self.assertFalse(self.env['slide.slide.partner'].search([('id', '=', '%d' % id_slide_partner)]))
|
|
|
|
|
|
@tagged('functional')
|
|
class TestAccessFeatures(common.SlidesCase):
|
|
|
|
@mute_logger('odoo.models', 'odoo.addons.base.models.ir_rule')
|
|
def test_channel_auto_subscription(self):
|
|
user_employees = self.env['res.users'].search([('groups_id', 'in', self.ref('base.group_user'))])
|
|
|
|
channel = self.env['slide.channel'].with_user(self.user_officer).create({
|
|
'name': 'Test',
|
|
'enroll': 'invite',
|
|
'is_published': True,
|
|
'enroll_group_ids': [(4, self.ref('base.group_user'))]
|
|
})
|
|
channel.invalidate_cache(['partner_ids'])
|
|
self.assertEqual(channel.partner_ids, user_employees.mapped('partner_id'))
|
|
|
|
new_user = self.env['res.users'].create({
|
|
'name': 'NewUser',
|
|
'login': 'NewUser',
|
|
'groups_id': [(6, 0, [self.ref('base.group_user')])]
|
|
})
|
|
channel.invalidate_cache()
|
|
self.assertEqual(channel.partner_ids, user_employees.mapped('partner_id') | new_user.partner_id)
|
|
|
|
new_user_2 = self.env['res.users'].create({
|
|
'name': 'NewUser2',
|
|
'login': 'NewUser2',
|
|
'groups_id': [(5, 0)]
|
|
})
|
|
channel.invalidate_cache()
|
|
self.assertEqual(channel.partner_ids, user_employees.mapped('partner_id') | new_user.partner_id)
|
|
new_user_2.write({'groups_id': [(4, self.ref('base.group_user'))]})
|
|
channel.invalidate_cache()
|
|
self.assertEqual(channel.partner_ids, user_employees.mapped('partner_id') | new_user.partner_id | new_user_2.partner_id)
|
|
|
|
new_user_3 = self.env['res.users'].create({
|
|
'name': 'NewUser3',
|
|
'login': 'NewUser3',
|
|
'groups_id': [(5, 0)]
|
|
})
|
|
channel.invalidate_cache()
|
|
self.assertEqual(channel.partner_ids, user_employees.mapped('partner_id') | new_user.partner_id | new_user_2.partner_id)
|
|
self.env.ref('base.group_user').write({'users': [(4, new_user_3.id)]})
|
|
channel.invalidate_cache()
|
|
self.assertEqual(channel.partner_ids, user_employees.mapped('partner_id') | new_user.partner_id | new_user_2.partner_id | new_user_3.partner_id)
|
|
|
|
@mute_logger('odoo.models', 'odoo.addons.base.models.ir_rule')
|
|
def test_channel_access_fields_employee(self):
|
|
channel_manager = self.channel.with_user(self.user_manager)
|
|
channel_emp = self.channel.with_user(self.user_emp)
|
|
channel_portal = self.channel.with_user(self.user_portal)
|
|
self.assertFalse(channel_emp.can_upload)
|
|
self.assertFalse(channel_emp.can_publish)
|
|
self.assertFalse(channel_portal.can_upload)
|
|
self.assertFalse(channel_portal.can_publish)
|
|
|
|
# allow employees to upload
|
|
channel_manager.write({'upload_group_ids': [(4, self.ref('base.group_user'))]})
|
|
self.assertTrue(channel_emp.can_upload)
|
|
self.assertFalse(channel_emp.can_publish)
|
|
self.assertFalse(channel_portal.can_upload)
|
|
self.assertFalse(channel_portal.can_publish)
|
|
|
|
@mute_logger('odoo.models', 'odoo.addons.base.models.ir_rule')
|
|
def test_channel_access_fields_officer(self):
|
|
self.assertEqual(self.channel.user_id, self.user_officer)
|
|
|
|
channel_officer = self.channel.with_user(self.user_officer)
|
|
self.assertTrue(channel_officer.can_upload)
|
|
self.assertTrue(channel_officer.can_publish)
|
|
|
|
channel_officer.write({'upload_group_ids': [(4, self.ref('base.group_system'))]})
|
|
self.assertTrue(channel_officer.can_upload)
|
|
self.assertTrue(channel_officer.can_publish)
|
|
|
|
channel_manager = self.channel.with_user(self.user_manager)
|
|
channel_manager.write({
|
|
'upload_group_ids': [(5, 0)],
|
|
'user_id': self.user_manager.id
|
|
})
|
|
self.assertFalse(channel_officer.can_upload)
|
|
self.assertFalse(channel_officer.can_publish)
|
|
self.assertTrue(channel_manager.can_upload)
|
|
self.assertTrue(channel_manager.can_publish)
|
|
|
|
@mute_logger('odoo.models', 'odoo.addons.base.models.ir_rule')
|
|
def test_channel_access_fields_manager(self):
|
|
channel_manager = self.channel.with_user(self.user_manager)
|
|
self.assertTrue(channel_manager.can_upload)
|
|
self.assertTrue(channel_manager.can_publish)
|
|
|
|
# test upload group limitation: member of group_system OR responsible OR manager
|
|
channel_manager.write({'upload_group_ids': [(4, self.ref('base.group_system'))]})
|
|
self.assertFalse(channel_manager.can_upload)
|
|
self.assertFalse(channel_manager.can_publish)
|
|
channel_manager.write({'user_id': self.user_manager.id})
|
|
self.assertTrue(channel_manager.can_upload)
|
|
self.assertTrue(channel_manager.can_publish)
|
|
|
|
# Needs the manager to write on channel as user_officer is not the responsible anymore
|
|
channel_manager.write({'upload_group_ids': [(5, 0)]})
|
|
self.assertTrue(channel_manager.can_upload)
|
|
self.assertTrue(channel_manager.can_publish)
|
|
channel_manager.write({'user_id': self.user_officer.id})
|
|
self.assertTrue(channel_manager.can_upload)
|
|
self.assertTrue(channel_manager.can_publish)
|
|
|
|
# superuser should always be able to publish even if they are not the responsible
|
|
channel_superuser = self.channel.sudo()
|
|
channel_superuser.invalidate_cache(['can_upload', 'can_publish'])
|
|
self.assertTrue(channel_superuser.can_upload)
|
|
self.assertTrue(channel_superuser.can_publish)
|