diff --git a/addons/website_slides/controllers/main.py b/addons/website_slides/controllers/main.py index c93777839bfa8e48896671ac83ffbfe96c1b0860..7c8593c48e7f6527465ec1e61afccd1a5f1e38f2 100644 --- a/addons/website_slides/controllers/main.py +++ b/addons/website_slides/controllers/main.py @@ -66,20 +66,20 @@ class website_slides(http.Controller): }) @http.route([ - '/slides/<model("slide.channel"):channel>', - '/slides/<model("slide.channel"):channel>/page/<int:page>', + '''/slides/<model("slide.channel", "[('can_see', '=', True)]"):channel>''', + '''/slides/<model("slide.channel", "[('can_see', '=', True)]"):channel>/page/<int:page>''', - '/slides/<model("slide.channel"):channel>/<string:slide_type>', - '/slides/<model("slide.channel"):channel>/<string:slide_type>/page/<int:page>', + '''/slides/<model("slide.channel", "[('can_see', '=', True)]"):channel>/<string:slide_type>''', + '''/slides/<model("slide.channel", "[('can_see', '=', True)]"):channel>/<string:slide_type>/page/<int:page>''', - '/slides/<model("slide.channel"):channel>/tag/<model("slide.tag"):tag>', - '/slides/<model("slide.channel"):channel>/tag/<model("slide.tag"):tag>/page/<int:page>', + '''/slides/<model("slide.channel", "[('can_see', '=', True)]"):channel>/tag/<model("slide.tag"):tag>''', + '''/slides/<model("slide.channel", "[('can_see', '=', True)]"):channel>/tag/<model("slide.tag"):tag>/page/<int:page>''', - '/slides/<model("slide.channel"):channel>/category/<model("slide.category"):category>', - '/slides/<model("slide.channel"):channel>/category/<model("slide.category"):category>/page/<int:page>', + '''/slides/<model("slide.channel", "[('can_see', '=', True)]"):channel>/category/<model("slide.category"):category>''', + '''/slides/<model("slide.channel", "[('can_see', '=', True)]"):channel>/category/<model("slide.category"):category>/page/<int:page>''', - '/slides/<model("slide.channel"):channel>/category/<model("slide.category"):category>/<string:slide_type>', - '/slides/<model("slide.channel"):channel>/category/<model("slide.category"):category>/<string:slide_type>/page/<int:page>'], + '''/slides/<model("slide.channel", "[('can_see', '=', True)]"):channel>/category/<model("slide.category"):category>/<string:slide_type>''', + '''/slides/<model("slide.channel", "[('can_see', '=', True)]"):channel>/category/<model("slide.category"):category>/<string:slide_type>/page/<int:page>'''], type='http', auth="public", website=True) def channel(self, channel, category=None, tag=None, page=1, slide_type=None, sorting='creation', search=None, **kw): user = request.env.user @@ -153,21 +153,21 @@ class website_slides(http.Controller): # SLIDE.SLIDE CONTOLLERS # -------------------------------------------------- - @http.route('/slides/slide/<model("slide.slide"):slide>', type='http', auth="public", website=True) + @http.route('''/slides/slide/<model("slide.slide", "[('channel_id.can_see', '=', True)]"):slide>''', type='http', auth="public", website=True) def slide_view(self, slide, **kwargs): values = self._get_slide_detail(slide) if not values.get('private'): self._set_viewed_slide(slide, 'slide') return request.website.render('website_slides.slide_detail_view', values) - @http.route('''/slides/slide/<model("slide.slide", "[('datas', '!=', False), ('slide_type', '=', 'presentation')]"):slide>/pdf_content''', type='http', auth="public", website=True) + @http.route('''/slides/slide/<model("slide.slide", "[('channel_id.can_see', '=', True), ('datas', '!=', False), ('slide_type', '=', 'presentation')]"):slide>/pdf_content''', type='http', auth="public", website=True) def slide_get_pdf_content(self, slide): response = werkzeug.wrappers.Response() response.data = slide.datas and slide.datas.decode('base64') or '' response.mimetype = 'application/pdf' return response - @http.route('/slides/slide/<model("slide.slide"):slide>/comment', type='http', auth="public", methods=['POST'], website=True) + @http.route('''/slides/slide/<model("slide.slide", "[('channel_id.can_see', '=', True)]"):slide>/comment''', type='http', auth="public", methods=['POST'], website=True) def slide_comment(self, slide, **post): """ Controller for message_post. Public user can post; their name and email is used to find or create a partner and post as admin with the @@ -213,7 +213,7 @@ class website_slides(http.Controller): ) return werkzeug.utils.redirect(request.httprequest.referrer + "#discuss") - @http.route('/slides/slide/<model("slide.slide"):slide>/download', type='http', auth="public", website=True) + @http.route('''/slides/slide/<model("slide.slide", "[('channel_id.can_see', '=', True), ('download_security', '=', 'public')]"):slide>/download''', type='http', auth="public", website=True) def slide_download(self, slide): if slide.download_security == 'public' or (slide.download_security == 'user' and request.session.uid): filecontent = base64.b64decode(slide.datas) @@ -227,7 +227,7 @@ class website_slides(http.Controller): return werkzeug.utils.redirect('/web?redirect=/slides/slide/%s' % (slide.id)) return request.website.render("website.403") - @http.route('/slides/slide/<model("slide.slide"):slide>/promote', type='http', auth='user', website=True) + @http.route('''/slides/slide/<model("slide.slide"):slide>/promote''', type='http', auth='user', website=True) def slide_set_promoted(self, slide): slide.channel_id.promoted_slide_id = slide.id return request.redirect("/slides/%s" % slide.channel_id.id) @@ -348,4 +348,4 @@ class website_slides(http.Controller): except AccessError: # TODO : please, make it clean one day, or find another secure way to detect # if the slide can be embedded, and properly display the error message. slide = request.env['slide.slide'].sudo().browse(slide_id) - return request.website.render('website_slides.embed_slide_forbidden', {'slide' : slide}) + return request.website.render('website_slides.embed_slide_forbidden', {'slide': slide}) diff --git a/addons/website_slides/models/slides.py b/addons/website_slides/models/slides.py index 0bdc7b8b71e32259bef3e1778a1a178208599eae..57a3e4f15ae286758284f9cf914e2810f95b34c4 100644 --- a/addons/website_slides/models/slides.py +++ b/addons/website_slides/models/slides.py @@ -103,10 +103,34 @@ class Channel(models.Model): 'res.groups', 'rel_upload_groups', 'channel_id', 'group_id', string='Upload Groups', help="Groups allowed to upload presentations in this channel. If void, every user can upload.") # not stored access fields, depending on each user - can_see = fields.Boolean('Can See', compute='_compute_access') + can_see = fields.Boolean('Can See', compute='_compute_access', search='_search_can_see') can_see_full = fields.Boolean('Full Access', compute='_compute_access') can_upload = fields.Boolean('Can Upload', compute='_compute_access') + def _search_can_see(self, operator, value): + if operator not in ('=', '!=', '<>'): + raise ValueError('Invalid operator: %s' % (operator,)) + + if not value: + operator = operator == "=" and '!=' or '=' + + if self._uid == SUPERUSER_ID: + return [(1, '=', 1)] + + # Better perfs to split request and use inner join that left join + req = """ + SELECT id FROM slide_channel WHERE visibility='public' + UNION + SELECT c.id + FROM slide_channel c + INNER JOIN rel_channel_groups rg on c.id = rg.channel_id + INNER JOIN res_groups g on g.id = rg.group_id + INNER JOIN res_groups_users_rel u on g.id = u.gid and uid = %s + """ + op = operator == "=" and "inselect" or "not inselect" + # don't use param named because orm will add other param (test_active, ...) + return [('id', op, (req, (self._uid)))] + @api.one @api.depends('visibility', 'group_ids', 'upload_group_ids') def _compute_access(self):