From df09c5c20f6498c0121f6934bbfe104ec5c3b1a2 Mon Sep 17 00:00:00 2001 From: Nikunj Ladava Date: Thu, 2 Jun 2022 06:43:49 +0000 Subject: [PATCH] [IMP] website_slides: update course visibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit before this commit, the wording of the visibility options can be quite confusing. after this commit, - Visibility has been updated - Visible to all: I see those training to the public - Visible to logged users only: I am a B2B business, and I do not want the public to see what I offer + the pricing I have on those - Visible to members only: I am a school, I want to invite my students but external visitors should not be able to enroll - Move the field above the "enroll policy" - Enroll Policy has been set to invite when visibility is set as a Course attendee and hide the enroll policy task- 2862003 closes odoo/odoo#102085 Related: odoo/upgrade#3946 Signed-off-by: Stéphane Debauche (std) --- .../website_sale_slides/data/product_demo.xml | 12 +++ .../data/sale_order_demo.xml | 24 +++++ .../website_sale_slides/data/slide_demo.xml | 7 ++ .../static/img/channel_demo_furniture_2.jpg | Bin 0 -> 28625 bytes .../data/slide_channel_demo.xml | 1 + addons/website_slides/models/slide_channel.py | 21 ++++- .../security/website_slides_security.xml | 72 +++++++++++--- addons/website_slides/tests/test_security.py | 89 ++++++++++++++++++ .../tests/test_slide_channel.py | 17 ++++ .../views/slide_channel_views.xml | 8 +- .../website_slides_forum_security.xml | 55 +++++++++-- 11 files changed, 279 insertions(+), 27 deletions(-) create mode 100644 addons/website_sale_slides/static/img/channel_demo_furniture_2.jpg diff --git a/addons/website_sale_slides/data/product_demo.xml b/addons/website_sale_slides/data/product_demo.xml index 95f549df859..ba26e19bbe9 100644 --- a/addons/website_sale_slides/data/product_demo.xml +++ b/addons/website_sale_slides/data/product_demo.xml @@ -12,6 +12,18 @@ + + + + Basics of Furniture Creation + 200.0 + 200.0 + course + order + + + + diff --git a/addons/website_sale_slides/data/sale_order_demo.xml b/addons/website_sale_slides/data/sale_order_demo.xml index 6af321868fd..5b57eb81da8 100644 --- a/addons/website_sale_slides/data/sale_order_demo.xml +++ b/addons/website_sale_slides/data/sale_order_demo.xml @@ -53,6 +53,29 @@ 100.0 + + + + + + + + + + + + + sale + + + + + + 1 + + 200.0 + + @@ -75,4 +98,5 @@ + diff --git a/addons/website_sale_slides/data/slide_demo.xml b/addons/website_sale_slides/data/slide_demo.xml index 00be884593c..5585ddaadf3 100644 --- a/addons/website_sale_slides/data/slide_demo.xml +++ b/addons/website_sale_slides/data/slide_demo.xml @@ -7,6 +7,13 @@ + + + + payment + + + diff --git a/addons/website_sale_slides/static/img/channel_demo_furniture_2.jpg b/addons/website_sale_slides/static/img/channel_demo_furniture_2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..375036f7d752319e34aadd770a540d5ea95f9c78 GIT binary patch literal 28625 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 literal 0 HcmV?d00001 diff --git a/addons/website_slides/data/slide_channel_demo.xml b/addons/website_slides/data/slide_channel_demo.xml index dc8fdb0e0a8..8f83af21ff8 100644 --- a/addons/website_slides/data/slide_channel_demo.xml +++ b/addons/website_slides/data/slide_channel_demo.xml @@ -99,6 +99,7 @@ will learn the basics of wood characteristics. Basics of Furniture Creation invite + connected training latest diff --git a/addons/website_slides/models/slide_channel.py b/addons/website_slides/models/slide_channel.py index f86f527a9b0..1e01f25a290 100644 --- a/addons/website_slides/models/slide_channel.py +++ b/addons/website_slides/models/slide_channel.py @@ -287,7 +287,8 @@ class Channel(models.Model): default=lambda self: self.env['ir.model.data']._xmlid_to_res_id('website_slides.mail_template_channel_completed'), domain=[('model', '=', 'slide.channel.partner')]) enroll = fields.Selection([ - ('public', 'Public'), ('invite', 'On Invitation')], + ('public', 'Open'), ('invite', 'On Invitation')], + compute='_compute_enroll', store=True, readonly=False, default='public', string='Enroll Policy', required=True, help='Defines how people can enroll to your Course.', copy=False) enroll_msg = fields.Html( @@ -295,8 +296,10 @@ class Channel(models.Model): default=_get_default_enroll_msg, translate=tools.html_translate, sanitize_attributes=False) enroll_group_ids = fields.Many2many('res.groups', string='Auto Enroll Groups', help="Members of those groups are automatically added as members of the channel.") visibility = fields.Selection([ - ('public', 'Open To All'), ('members', 'Members Only')], - default='public', string='Visibility', required=True, + ('public', 'Everyone'), + ('connected', 'Signed In'), + ('members', 'Course Attendees') + ], default='public', string='Show Course To', required=True, help='Defines who can access your courses and their content.') partner_ids = fields.Many2many( 'res.partner', 'slide_channel_partner', 'channel_id', 'partner_id', @@ -327,6 +330,18 @@ class Channel(models.Model): can_comment = fields.Boolean('Can Comment', compute='_compute_action_rights', compute_sudo=False) can_vote = fields.Boolean('Can Vote', compute='_compute_action_rights', compute_sudo=False) + _sql_constraints = [ + ( + "check_enroll", + "CHECK(visibility != 'members' OR enroll = 'invite')", + "The Enroll Policy should be set to 'On Invitation' when visibility is set to 'Course Attendees'" + ), + ] + + @api.depends('visibility') + def _compute_enroll(self): + self.filtered(lambda channel: channel.visibility == 'members').enroll = 'invite' + @api.depends('slide_ids.is_published') def _compute_slide_last_update(self): for record in self: diff --git a/addons/website_slides/security/website_slides_security.xml b/addons/website_slides/security/website_slides_security.xml index 908e3823bbe..a5b8d583571 100644 --- a/addons/website_slides/security/website_slides_security.xml +++ b/addons/website_slides/security/website_slides_security.xml @@ -29,11 +29,29 @@ [(1, '=', 1)] - - Channel: public/portal/user: restricted to published and (public or member only) + + Channel: public: restricted to public and published - - ['&', ('website_published', '=', True), '|', ('visibility', '=', 'public'), ('partner_ids', '=', user.partner_id.id)] + + [('website_published', '=', True), ('visibility', '=', 'public')] + + + + + + + + Channel: portal/user: restricted to published, public or connected User + + + [ + '&', + ('website_published', '=', True), + '|', + ('visibility', 'in', ('public', 'connected')), + ('partner_ids', '=', user.partner_id.id), + ] + @@ -90,15 +108,45 @@ [(1, '=', 1)] - - Slide: public/portal/user: restricted to published or uploaded by user, and either channel member or public channel & (category or previewable) + + Slide: public: restricted to published or public channel & (category or previewable) - - ['&', - '|', - '&', ('channel_id.visibility', '=', 'public'), '|', ('is_category','=', True), ('is_preview', '=', True), - ('channel_id.partner_ids', '=', user.partner_id.id), - '&', ('channel_id.website_published', '=', True), '|', ('user_id', '=', user.id), ('website_published', '=', True)] + + [ + ('channel_id.website_published', '=', True), + ('website_published', '=', True), + ('channel_id.visibility', '=', 'public'), + '|', + ('is_category','=', True), + ('is_preview', '=', True), + ] + + + + + + + + + Slide: portal/user: restricted to published and connected user + + + [ + '&', + '|', + ('user_id', '=', user.id), + '&', + ('website_published', '=', True), + ('channel_id.website_published', '=', True), + '|', + '&', + ('channel_id.visibility', 'in', ('public','connected')), + '|', + ('is_category', '=', True), + ('is_preview', '=', True), + ('channel_id.partner_ids', 'in', user.partner_id.ids), + ] + diff --git a/addons/website_slides/tests/test_security.py b/addons/website_slides/tests/test_security.py index 6be198abfbf..7b4bee22d8f 100644 --- a/addons/website_slides/tests/test_security.py +++ b/addons/website_slides/tests/test_security.py @@ -152,6 +152,95 @@ class TestAccess(common.SlidesCase): self.slide.with_user(self.user_portal).read(['name']) self.slide.with_user(self.user_public).read(['name']) + @mute_logger('odoo.models', 'odoo.addons.base.models.ir_rule') + def test_access_channel_visibility_public(self): + self.channel.write({'visibility': 'public'}) + self.slide.write({'is_preview': True}) + self.slide.flush_model() + + 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']) + 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']) + + @mute_logger('odoo.models', 'odoo.addons.base.models.ir_rule') + def test_access_channel_public_with_website_published(self): + self.channel.write({'visibility': 'public', 'website_published': False}) + + self.channel.with_user(self.user_officer).read(['name']) + self.channel.with_user(self.user_manager).read(['name']) + with self.assertRaises(AccessError): + self.channel.with_user(self.user_emp).read(['name']) + with self.assertRaises(AccessError): + self.channel.with_user(self.user_portal).read(['name']) + with self.assertRaises(AccessError): + 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_visibility_members(self): + self.channel.write({'visibility': 'members'}) + self.channel.flush_model() + user_emp_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']) + with self.assertRaises(AccessError): + self.channel.with_user(self.user_portal).read(['name']) + + user_emp_membership.unlink() + with self.assertRaises(AccessError): + self.channel.with_user(self.user_emp).read(['name']) + + @mute_logger('odoo.models', 'odoo.addons.base.models.ir_rule') + def test_access_channel_members_with_website_published(self): + self.channel.write({'visibility': 'members', 'website_published': False}) + self.channel.flush_model() + + with self.assertRaises(AccessError): + self.channel.with_user(self.user_emp).read(['name']) + + with self.assertRaises(AccessError): + self.channel.with_user(self.user_portal).read(['name']) + + + @mute_logger('odoo.models', 'odoo.addons.base.models.ir_rule') + def test_access_channel_visibility_connected(self): + self.channel.write({'visibility': 'connected'}) + + 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']) + with self.assertRaises(AccessError): + 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']) + @tagged('functional', 'security') class TestRemoveMembership(common.SlidesCase): diff --git a/addons/website_slides/tests/test_slide_channel.py b/addons/website_slides/tests/test_slide_channel.py index ff24c49d953..8fe333653cb 100644 --- a/addons/website_slides/tests/test_slide_channel.py +++ b/addons/website_slides/tests/test_slide_channel.py @@ -220,3 +220,20 @@ class TestSequencing(slides_common.SlidesCase): self.assertEqual(self.category.sequence, 4) self.assertEqual(self.slide_2.sequence, 5) self.assertEqual([s.id for s in self.channel.slide_ids], [self.slide.id, new_category.id, self.slide_3.id, self.category.id, self.slide_2.id]) + + @users('user_officer') + def test_channel_enroll_policy(self): + channel = self.env['slide.channel'].create({ + 'name': 'Test Course 2', + 'slide_ids': [(0, 0, { + 'name': 'Test Slide 1' + })], + }) + + self.assertEqual(channel.visibility, 'public') + self.assertEqual(channel.enroll, 'public') + + channel.write({'visibility': 'members'}) + + self.assertEqual(channel.visibility, 'members') + self.assertEqual(channel.enroll, 'invite') diff --git a/addons/website_slides/views/slide_channel_views.xml b/addons/website_slides/views/slide_channel_views.xml index 0a8d8f43f62..b6d71d86624 100644 --- a/addons/website_slides/views/slide_channel_views.xml +++ b/addons/website_slides/views/slide_channel_views.xml @@ -100,7 +100,8 @@ - + + @@ -116,7 +117,6 @@ - - - + + diff --git a/addons/website_slides_forum/security/website_slides_forum_security.xml b/addons/website_slides_forum/security/website_slides_forum_security.xml index 487d1bb6cea..9b1dc50fc01 100644 --- a/addons/website_slides_forum/security/website_slides_forum_security.xml +++ b/addons/website_slides_forum/security/website_slides_forum_security.xml @@ -1,10 +1,23 @@ - Website forum: User can only access to forum related to followed courses + Website forum: User can only access to forum related to public courses - ['&', ('slide_channel_ids.website_published', '=', True), '|', ('slide_channel_ids.visibility', '=', 'public'), ('slide_channel_ids.partner_ids', 'in', user.partner_id.id)] - + [('slide_channel_ids.website_published', '=', True), ('slide_channel_ids.visibility', '=', 'public')] + + + + Website forum: Signed In user can only access to forum related to courses + + [ + '&', + ('slide_channel_ids.website_published', '=', True), + '|', + ('slide_channel_ids.visibility', 'in', ('public','connected')), + ('slide_channel_ids.partner_ids', 'in', user.partner_id.id) + ] + + Website forum: website slides officer can access all forum @@ -16,8 +29,21 @@ Website forum post: User can only access to post linked to forum related to followed courses - ['&', ('forum_id.slide_channel_ids.website_published', '=', True), '|', ('forum_id.slide_channel_ids.visibility', '=', 'public'), ('forum_id.slide_channel_ids.partner_ids', 'in', user.partner_id.id)] - + [('forum_id.slide_channel_ids.website_published', '=', True), ('forum_id.slide_channel_ids.visibility', '=', 'public')] + + + + Website forum: Signed In user can only access to post linked to forum related to courses + + [ + '&', + ('forum_id.slide_channel_ids.website_published', '=', True), + '|', + ('forum_id.slide_channel_ids.visibility', 'in', ('public','connected')), + ('forum_id.slide_channel_ids.partner_ids', 'in', user.partner_id.id) + ] + + Website forum post: website slides officer can access all post @@ -27,10 +53,23 @@ - Website slides forum tag: User can only access to tag linked to forum related to followed courses + Website slides forum tag: Public User can only access to tag linked to forum related to public courses - ['&', ('forum_id.slide_channel_ids.website_published', '=', True), '|', ('forum_id.slide_channel_ids.visibility', '=', 'public'), ('forum_id.slide_channel_ids.partner_ids', 'in', user.partner_id.id)] - + [('forum_id.slide_channel_ids.website_published', '=', True), ('forum_id.slide_channel_ids.visibility', '=', 'public')] + + + + Website forum: Signed In users can access tags linked to public or connected users-visibility courses + + [ + '&', + ('forum_id.slide_channel_ids.website_published', '=', True), + '|', + ('forum_id.slide_channel_ids.visibility', 'in', ('public','connected')), + ('forum_id.slide_channel_ids.partner_ids', 'in', user.partner_id.id) + ] + + Website slides forum tag: website slides officer can access all tag