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 00000000000..375036f7d75 Binary files /dev/null and b/addons/website_sale_slides/static/img/channel_demo_furniture_2.jpg differ 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