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