diff --git a/addons/website_slides/controllers/main.py b/addons/website_slides/controllers/main.py index 839343434024144602f9fdfe63853bbdee3aaf4d..da9fe1a7b814390d095e02b8ba186178b52cf34f 100644 --- a/addons/website_slides/controllers/main.py +++ b/addons/website_slides/controllers/main.py @@ -45,10 +45,7 @@ class WebsiteSlides(WebsiteProfile): slide = request.env['slide.slide'].browse(int(slide_id)).exists() if not slide: return {'error': 'slide_wrong'} - try: - slide.check_access_rights('read') - slide.check_access_rule('read') - except: + if not slide._check_read_access(): return {'error': 'slide_access'} return {'slide': slide} @@ -370,7 +367,6 @@ class WebsiteSlides(WebsiteProfile): 'user': request.env.user, 'pager': pager, 'is_public_user': request.website.is_public_user(), - 'is_slides_publisher': request.env.user.has_group('website.group_website_publisher'), } if not request.env.user._is_public(): last_message_values = request.env['mail.message'].search([ @@ -402,10 +398,11 @@ class WebsiteSlides(WebsiteProfile): force_void=True, limit=self._slides_per_category if channel.channel_type == 'documentation' else False, offset=pager['offset']) + + values['slide_promoted_access'] = values['slide_promoted'].sudo(request.env.user)._get_slide_action_access()[values['slide_promoted'].id] values['channel_progress'] = self._get_channel_progress(channel, include_quiz=True) values = self._prepare_additional_channel_values(values, **kw) - return request.render('website_slides.course_main', values) # SLIDE.CHANNEL UTILS @@ -494,6 +491,8 @@ class WebsiteSlides(WebsiteProfile): if 'fullscreen' in kwargs: return request.render("website_slides.slide_fullscreen", values) + else: + values['slide_access'] = slide.sudo(request.env.user)._get_slide_action_access()[slide.id] return request.render("website_slides.slide_main", values) @http.route('''/slides/slide/<model("slide.slide"):slide>/pdf_content''', @@ -576,7 +575,12 @@ class WebsiteSlides(WebsiteProfile): ]) if (upvote and slide_partners.vote == 1) or (not upvote and slide_partners.vote == -1): return {'error': 'vote_done'} - slide = request.env['slide.slide'].browse(int(slide_id)) + # check slide access + fetch_res = self._fetch_slide(slide_id) + if fetch_res.get('error'): + return fetch_res + # check slide operation + slide = fetch_res['slide'] if not slide.channel_id.allow_comment: return {'error': 'comment_disabled'} if not slide.can_vote: diff --git a/addons/website_slides/models/slide_channel.py b/addons/website_slides/models/slide_channel.py index cd7565bd41a7fa884d7a522dcce5b7c959daafea..e0af206ff80391847390713f27c1677cb24f9ac6 100644 --- a/addons/website_slides/models/slide_channel.py +++ b/addons/website_slides/models/slide_channel.py @@ -453,22 +453,24 @@ class Channel(models.Model): if uncategorized_slides or force_void: category_data.append({ 'category': False, 'id': False, - 'name': _('Uncategorized'), 'slug_name': _('Uncategorized'), + 'name': _('Uncategorized'), 'slug_name': _('Uncategorized'), 'total_slides': len(uncategorized_slides), 'slides': uncategorized_slides[(offset or 0):(limit or len(uncategorized_slides))], + 'slides_access': uncategorized_slides.sudo(self.env.user)._get_slide_action_access() }) # Then all categories by natural order for category in all_categories: category_slides = all_slides.filtered(lambda slide: slide.category_id == category) if not category_slides and not force_void: continue + slides = category_slides[(offset or 0):(limit or len(category_slides))] category_data.append({ 'category': category, 'id': category.id, 'name': category.name, 'slug_name': slug(category), 'total_slides': len(category_slides), - 'slides': category_slides[(offset or 0):(limit or len(category_slides))], + 'slides': slides, + 'slides_access': slides.sudo(self.env.user)._get_slide_action_access() }) - return category_data diff --git a/addons/website_slides/models/slide_slide.py b/addons/website_slides/models/slide_slide.py index a4a9600167384db8755a9b578824e120db912523..dfd7cc29a46d9003fb3f1b542d3121392384e125 100644 --- a/addons/website_slides/models/slide_slide.py +++ b/addons/website_slides/models/slide_slide.py @@ -14,7 +14,7 @@ from werkzeug import urls from odoo import api, fields, models, _ from odoo.addons.http_routing.models.ir_http import slug from odoo.addons.gamification.models.gamification_karma_rank import KarmaError -from odoo.exceptions import Warning, UserError +from odoo.exceptions import Warning, UserError, AccessError from odoo.http import request from odoo.addons.http_routing.models.ir_http import url_for @@ -273,6 +273,7 @@ class Slide(models.Model): @api.multi def _compute_karma_rights(self): + """ This method supposed current user have access to the slide. If not, I will crash, meaning he can not execute the action """ for slide in self: slide.can_comment = self.env.user.karma >= slide.channel_id.karma_slide_comment slide.can_vote = self.env.user.karma >= slide.channel_id.karma_slide_vote @@ -356,6 +357,28 @@ class Slide(models.Model): return groups + # --------------------------------------------------------- + # Access Rights Methods + # --------------------------------------------------------- + + def _check_read_access(self): + try: + self.check_access_rights('read') + self.check_access_rule('read') + except AccessError: + return False + return True + + def _get_slide_action_access(self): + result = dict((slide_id, dict(can_access=False, can_vote=False, can_comment=False)) for slide_id in self.ids) + for slide in self: + can_access = slide._check_read_access() + if can_access and (slide.channel_id.is_member or slide.is_preview or slide.can_publish): + result[slide.id]['can_access'] = True + result[slide.id]['can_vote'] = slide.can_vote + result[slide.id]['can_comment'] = slide.can_comment + return result + # --------------------------------------------------------- # Business Methods # --------------------------------------------------------- diff --git a/addons/website_slides/static/src/js/slides_slide_like.js b/addons/website_slides/static/src/js/slides_slide_like.js index bb0542a5f7eda66fb8b2308ad98ba78ec39b31fc..6609cc0ca927f013456d44d340c01da70d1af941 100644 --- a/addons/website_slides/static/src/js/slides_slide_like.js +++ b/addons/website_slides/static/src/js/slides_slide_like.js @@ -56,9 +56,11 @@ var SlideLikeWidget = Widget.extend({ self.$el.find('span.o_wslides_js_slide_like_down span').text(data.dislikes); } else { if (data.error === 'public_user') { - self._popoverAlert(self.$el, _.str.sprintf(_t('Please <a href="/web/login?redirect=%s">login</a> to vote this slide'), (document.URL))); + self._popoverAlert(self.$el, _.str.sprintf(_t('Please <a href="/web/login?redirect=%s">login</a> to vote this lesson'), (document.URL))); } else if (data.error === 'vote_done') { - self._popoverAlert(self.$el, _t('You have already voted for this slide')); + self._popoverAlert(self.$el, _t('You have already voted for this lesson')); + } else if (data.error === 'slide_access') { + self._popoverAlert(self.$el, _t('You don\'t have access to this lesson')); } else if (data.error === 'comment_disabled') { self._popoverAlert(self.$el, _t('Votes and comments are disabled for this channel')); } else if (data.error === 'missing_karma') { diff --git a/addons/website_slides/static/src/scss/website_slides.scss b/addons/website_slides/static/src/scss/website_slides.scss index 4e83de3b44de1deb1c8adabd9ad1870f3e9cc4a8..bbe635a89fab4234fd7391aa3a883ac3523df346 100644 --- a/addons/website_slides/static/src/scss/website_slides.scss +++ b/addons/website_slides/static/src/scss/website_slides.scss @@ -32,8 +32,10 @@ $o-enterprise-radient-color: #62495B !default; .o_wslides_js_slide_like_up, .o_wslides_js_slide_like_down { - cursor: pointer; - color: $link-color; + &:not(.disabled) { + cursor: pointer; + color: $link-color; + } } .o_wslides_js_lesson_quiz_question { diff --git a/addons/website_slides/views/website_slides_templates_course.xml b/addons/website_slides/views/website_slides_templates_course.xml index e3a6583ca8b082e46782971d9a577efbf7d1f101..50f118f71eb8a892bb20b46ec833aabf3ba2159e 100644 --- a/addons/website_slides/views/website_slides_templates_course.xml +++ b/addons/website_slides/views/website_slides_templates_course.xml @@ -387,7 +387,7 @@ </div> <div class="col-8"> <h3 class="w-100" t-att-title="slide_promoted.name"> - <t t-if="slide_promoted.is_preview or channel.is_member or is_slides_publisher"> + <t t-if="slide_promoted_access['can_access']"> <a t-attf-href="/slides/slide/#{slug(slide_promoted)}" class="font-weight-bold text-muted" t-field="slide_promoted.name"/> </t> <t t-else=""> @@ -420,7 +420,9 @@ </div> <div class="row mx-n2 mt8"> <t t-foreach="category['slides']" t-as="slide"> - <div class="col-md-3 col-sm-6 px-2 col-xs-12 d-flex flex-grow-1" t-call="website_slides.lesson_card"/> + <div class="col-md-3 col-sm-6 px-2 col-xs-12 d-flex flex-grow-1" t-call="website_slides.lesson_card"> + <t t-set="slide_access" t-value="category['slides_access'][slide.id]"/> + </div> </t> </div> </div> @@ -438,15 +440,14 @@ <template id='lesson_card' name="Lesson Card"> <div class="card w-100 o_wslides_lesson_card mb-4"> <t t-set="lesson_image" t-value="'/slides/slide/%s/get_image?field=image_large' % slide.id"/> - <t t-set="can_access" t-value="slide.is_preview or channel.is_member or is_slides_publisher"/> - <a t-if="can_access" t-attf-href="/slides/slide/#{slug(slide)}" t-title="slide.name"> + <a t-if="slide_access['can_access']" t-attf-href="/slides/slide/#{slug(slide)}" t-title="slide.name"> <div class="card-img-top" t-attf-style="padding-top: 50%; background-image: url(#{lesson_image}); background-size: cover; background-position:center"/> </a> <t t-else=""> <div class="card-img-top" t-attf-style="padding-top: 50%; background-image: url(#{lesson_image}); background-size: cover; background-position:center"/> </t> <div class="card-body"> - <a t-if="can_access" class="card-title h5" t-attf-href="/slides/slide/#{slug(slide)}" t-esc="slide.name"/> + <a t-if="slide_access['can_access']" class="card-title h5" t-attf-href="/slides/slide/#{slug(slide)}" t-esc="slide.name"/> <span t-else="" class="card-title h5 text-muted" t-esc="slide.name"/> <div class="card-subtitle mb-2 text-muted"> <t t-if="slide.is_preview"> @@ -469,11 +470,11 @@ <div class="d-flex align-items-center small"> <span class="font-weight-bold mr-auto" t-field="slide.completion_time" t-options='{"widget": "float_time"}'/> <div class="o_wslides_js_slide_like mr-2"> - <span class="o_wslides_js_slide_like_up" tabindex="0" data-toggle="popover" t-att-data-slide-id="slide.id"> + <span t-att-class="('o_wslides_js_slide_like_up %s') % ('disabled' if not (slide_access['can_access'] and slide_access['can_vote']) else '')" tabindex="0" data-toggle="popover" t-att-data-slide-id="slide.id"> <i class="fa fa-thumbs-up fa-1x" role="img" aria-label="Likes" title="Likes"></i> <span t-esc="slide.likes"/> </span> - <span class="o_wslides_js_slide_like_down" tabindex="0" data-toggle="popover" t-att-data-slide-id="slide.id"> + <span t-att-class="('o_wslides_js_slide_like_down %s') % ('disabled' if not (slide_access['can_access'] and slide_access['can_vote']) else '')" tabindex="0" data-toggle="popover" t-att-data-slide-id="slide.id"> <i class="fa fa-thumbs-down fa-1x" role="img" aria-label="Dislikes" title="Dislikes"></i> <span t-esc="slide.dislikes"/> </span> diff --git a/addons/website_slides/views/website_slides_templates_lesson.xml b/addons/website_slides/views/website_slides_templates_lesson.xml index c589092aaa4c3e76410f56c35df334f923106341..c7f1cd8a7e19d9f4426d58c3c1b85c7dec9b3628 100644 --- a/addons/website_slides/views/website_slides_templates_lesson.xml +++ b/addons/website_slides/views/website_slides_templates_lesson.xml @@ -241,11 +241,11 @@ <span class="text-muted font-weight-bold mr-3">Rating</span> <div class="text-muted border-left pl-3"> <div class="o_wslides_js_slide_like mr-2"> - <span class="o_wslides_js_slide_like_up" tabindex="0" data-toggle="popover" t-att-data-slide-id="slide.id"> + <span t-att-class="('o_wslides_js_slide_like_up %s') % ('disabled' if not (slide_access['can_access'] and slide_access['can_vote']) else '')" tabindex="0" data-toggle="popover" t-att-data-slide-id="slide.id"> <i class="fa fa-thumbs-up fa-1x" role="img" aria-label="Likes" title="Likes"></i> <span t-esc="slide.likes"/> </span> - <span class="o_wslides_js_slide_like_down ml-3" tabindex="0" data-toggle="popover" t-att-data-slide-id="slide.id"> + <span t-att-class="('o_wslides_js_slide_like_down ml-3 %s') % ('disabled' if not (slide_access['can_access'] and slide_access['can_vote']) else '')" tabindex="0" data-toggle="popover" t-att-data-slide-id="slide.id"> <i class="fa fa-thumbs-down fa-1x" role="img" aria-label="Dislikes" title="Dislikes"></i> <span t-esc="slide.dislikes"/> </span> @@ -289,7 +289,7 @@ <div role="tabpanel" t-att-class="comments and 'tab-pane fade in show active' or 'tab-pane fade'" id="discuss"> <t t-call="portal.message_thread"> <t t-set="object" t-value="slide"/> - <t t-set="disable_composer" t-value="not (slide.can_comment and slide.channel_id.allow_comment and slide.channel_id.channel_type == 'training')"/> + <t t-set="disable_composer" t-value="not (slide_access['can_comment'] and slide.channel_id.allow_comment and slide.channel_id.channel_type == 'training')"/> <t t-set="display_rating" t-value="False"/> </t> </div>