From b91add891c214c52559e0447c43207ea50bb06cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 5 Feb 2019 17:35:13 +0000 Subject: [PATCH] [IMP] website_slides: add tests Currently website_slides module lacks tests. This commit adds base for tests and add some tests related to recently cleaned access rules and rights. Future commits will gradually add more tests to the module as it evolves towards a more broad and up-to-date application. This commit is linked to task ID 1937411 and PR #30847. --- addons/website_slides/tests/__init__.py | 5 + addons/website_slides/tests/common.py | 67 ++++++++++ addons/website_slides/tests/test_security.py | 133 +++++++++++++++++++ 3 files changed, 205 insertions(+) create mode 100644 addons/website_slides/tests/__init__.py create mode 100644 addons/website_slides/tests/common.py create mode 100644 addons/website_slides/tests/test_security.py diff --git a/addons/website_slides/tests/__init__.py b/addons/website_slides/tests/__init__.py new file mode 100644 index 00000000000..bb7921266e3 --- /dev/null +++ b/addons/website_slides/tests/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import common +from . import test_security diff --git a/addons/website_slides/tests/common.py b/addons/website_slides/tests/common.py new file mode 100644 index 00000000000..5bf179cbdc8 --- /dev/null +++ b/addons/website_slides/tests/common.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from contextlib import contextmanager +from functools import partial + +from odoo.tests import common, new_test_user + +slides_new_test_user = partial(new_test_user, context={'mail_create_nolog': True, 'mail_create_nosubscribe': True, 'mail_notrack': True, 'no_reset_password': True}) + + +class SlidesCase(common.SavepointCase): + + def setUp(self): + super(SlidesCase, self).setUp() + + self.user_publisher = slides_new_test_user( + self.env, name='Paul Publisher', login='user_publisher', email='publisher@example.com', + groups='base.group_user,website.group_website_publisher' + ) + + self.user_emp = slides_new_test_user( + self.env, name='Eglantine Employee', login='user_emp', email='employee@example.com', + groups='base.group_user' + ) + + self.user_portal = slides_new_test_user( + self.env, name='Patrick Portal', login='user_portal', email='portal@example.com', + groups='base.group_portal' + ) + + self.user_public = slides_new_test_user( + self.env, name='Pauline Public', login='user_public', email='public@example.com', + groups='base.group_public' + ) + + self.customer = self.env['res.partner'].create({ + 'name': 'Caroline Customer', + 'email': 'customer@example.com', + 'customer': True, + }) + + self.channel = self.env['slide.channel'].sudo(self.user_publisher).create({ + 'name': 'Test Channel', + 'promote_strategy': 'most_voted', + 'visibility': 'public', + 'website_published': True, + }) + self.slide = self.env['slide.slide'].sudo(self.user_publisher).create({ + 'name': 'How To Cook Humans', + 'channel_id': self.channel.id, + 'slide_type': 'presentation', + 'website_published': True, + }) + + @contextmanager + def sudo(self, user): + """ Quick sudo environment """ + old_uid = self.uid + try: + self.uid = user.id + self.env = self.env(user=self.uid) + yield + finally: + # back + self.uid = old_uid + self.env = self.env(user=self.uid) diff --git a/addons/website_slides/tests/test_security.py b/addons/website_slides/tests/test_security.py new file mode 100644 index 00000000000..c73af1d932a --- /dev/null +++ b/addons/website_slides/tests/test_security.py @@ -0,0 +1,133 @@ +# -*- 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, UserError +from odoo.tests import tagged +from odoo.tests.common import users +from odoo.tools import mute_logger + + +@tagged('security') +class TestAccess(common.SlidesCase): + + @mute_logger('odoo.models') + def test_access_channel_invite(self): + """ Invite channels don't give visibility if not member """ + self.channel.write({'visibility': 'invite'}) + + self.channel.sudo(self.user_publisher).read(['name']) + self.channel.sudo(self.user_emp).read(['name']) + self.channel.sudo(self.user_portal).read(['name']) + self.channel.sudo(self.user_public).read(['name']) + + self.slide.sudo(self.user_publisher).read(['name']) + + with self.assertRaises(AccessError): + self.slide.sudo(self.user_emp).read(['name']) + with self.assertRaises(AccessError): + self.slide.sudo(self.user_portal).read(['name']) + with self.assertRaises(AccessError): + self.slide.sudo(self.user_portal).read(['name']) + + # if member -> can read + membership = self.env['slide.channel.partner'].create({ + 'channel_id': self.channel.id, + 'state': 'confirmed', + 'partner_id': self.user_emp.partner_id.id, + }) + self.channel.sudo(self.user_emp).read(['name']) + self.slide.sudo(self.user_emp).read(['name']) + + # unvalidated member -> cannot read + membership.write({ + 'state': 'draft', + }) + self.channel.sudo(self.user_emp).read(['name']) + with self.assertRaises(AccessError): + self.slide.sudo(self.user_emp).read(['name']) + + # not member anymore -> cannot read + membership.unlink() + self.channel.sudo(self.user_emp).read(['name']) + with self.assertRaises(AccessError): + self.slide.sudo(self.user_emp).read(['name']) + + @mute_logger('odoo.models') + def test_access_channel_public(self): + """ Public channels don't give visibility if not member """ + self.channel.write({'visibility': 'public'}) + + self.channel.sudo(self.user_publisher).read(['name']) + self.channel.sudo(self.user_emp).read(['name']) + self.channel.sudo(self.user_portal).read(['name']) + self.channel.sudo(self.user_public).read(['name']) + + self.slide.sudo(self.user_publisher).read(['name']) + + with self.assertRaises(AccessError): + self.slide.sudo(self.user_emp).read(['name']) + with self.assertRaises(AccessError): + self.slide.sudo(self.user_portal).read(['name']) + with self.assertRaises(AccessError): + self.slide.sudo(self.user_public).read(['name']) + + @mute_logger('odoo.models') + def test_access_channel_publish(self): + """ Unpublished channels and their content are visible only to website people """ + self.channel.write({'website_published': False, 'visibility': 'public'}) + + # channel available only to website + self.channel.sudo(self.user_publisher).read(['name']) + with self.assertRaises(AccessError): + self.channel.sudo(self.user_emp).read(['name']) + with self.assertRaises(AccessError): + self.channel.sudo(self.user_portal).read(['name']) + with self.assertRaises(AccessError): + self.channel.sudo(self.user_public).read(['name']) + + # slide available only to website + self.slide.sudo(self.user_publisher).read(['name']) + with self.assertRaises(AccessError): + self.slide.sudo(self.user_emp).read(['name']) + with self.assertRaises(AccessError): + self.slide.sudo(self.user_portal).read(['name']) + with self.assertRaises(AccessError): + self.slide.sudo(self.user_public).read(['name']) + + # even members cannot see unpublished content + self.env['slide.channel.partner'].create({ + 'channel_id': self.channel.id, + 'state': 'confirmed', + 'partner_id': self.user_emp.partner_id.id, + }) + with self.assertRaises(AccessError): + self.channel.sudo(self.user_emp).read(['name']) + with self.assertRaises(AccessError): + self.slide.sudo(self.user_emp).read(['name']) + + # publish channel but content unpublished (even if can be previewed) still unavailable + self.channel.write({'website_published': True}) + self.slide.write({ + 'is_preview': True, + 'website_published': False, + }) + + self.slide.sudo(self.user_publisher).read(['name']) + with self.assertRaises(AccessError): + self.slide.sudo(self.user_emp).read(['name']) + with self.assertRaises(AccessError): + self.slide.sudo(self.user_portal).read(['name']) + with self.assertRaises(AccessError): + self.slide.sudo(self.user_public).read(['name']) + + @mute_logger('odoo.models') + def test_access_slide_preview(self): + """ Slides with preview flag are always visible even to non members if published """ + self.channel.write({'visibility': 'invite'}) + self.slide.write({'is_preview': True}) + + self.slide.sudo(self.user_publisher).read(['name']) + self.slide.sudo(self.user_emp).read(['name']) + self.slide.sudo(self.user_portal).read(['name']) + self.slide.sudo(self.user_public).read(['name'])