From 51fd5d3c059f583fbd86686e4e76f4619945c50b Mon Sep 17 00:00:00 2001
From: Ivan Yelizariev <iel@odoo.com>
Date: Tue, 14 Feb 2023 11:37:43 +0000
Subject: [PATCH] [FIX] website_sale_digital: let salesman download digital via
 portal

Portal shows all Sale Orders available for current user. For example, salesman
can see his sales. If such a user can download digital files via product form in
backend, it makes sense to let user download them via SO page on portal.
However, it wasn't the case because /my/download requires product be purchased
by current user [1]. Fix it by checking read access first.

STEPS

* in backend create SO with digital product (customer must be different from
current user)
* create invoice and register a payment
* navigate to portal  (without using customer's token),
* open SO, click download on digital product

[1]: https://github.com/odoo/odoo/blob/1a24477fab4dd323cf94c010321d8942fb2c1a01/addons/website_sale_digital/models/account_invoice.py#L14-L22

opw-3144600

closes odoo/odoo#112639

Signed-off-by: Morgane Demesmaeker <edm@odoo.com>
---
 .../website_sale_digital/controllers/main.py  | 37 ++++++++++---------
 1 file changed, 19 insertions(+), 18 deletions(-)

diff --git a/addons/website_sale_digital/controllers/main.py b/addons/website_sale_digital/controllers/main.py
index cac2a1de0610..acbca1e70b67 100644
--- a/addons/website_sale_digital/controllers/main.py
+++ b/addons/website_sale_digital/controllers/main.py
@@ -8,6 +8,7 @@ import mimetypes
 from werkzeug.utils import redirect
 
 from odoo import http
+from odoo.exceptions import AccessError
 from odoo.http import request
 from odoo.addons.sale.controllers.portal import CustomerPortal
 from odoo.addons.website_sale.controllers.main import WebsiteSale
@@ -81,25 +82,25 @@ class WebsiteSaleDigital(CustomerPortal):
         else:
             return redirect(self.orders_page)
 
-        # Check if the user has bought the associated product
-        res_model = attachment['res_model']
-        res_id = attachment['res_id']
-        purchased_products = request.env['account.move.line'].get_digital_purchases()
-
-        if res_model == 'product.product':
-            if res_id not in purchased_products:
-                return redirect(self.orders_page)
-
-        # Also check for attachments in the product templates
-        elif res_model == 'product.template':
-            template_ids = request.env['product.product'].sudo().browse(purchased_products).mapped('product_tmpl_id').ids
-            if res_id not in template_ids:
-                return redirect(self.orders_page)
-
-        else:
-            return redirect(self.orders_page)
+        try:
+            self.env['ir.attachment'].browse(attachment_id).check('read')
+        except AccessError:  # The user does not have read access on the attachment.
+            # Check if access can be granted through their purchases.
+            res_model = attachment['res_model']
+            res_id = attachment['res_id']
+            digital_purchases = request.env['account.move.line'].get_digital_purchases()
+            if res_model == 'product.product':
+                purchased_product_ids = digital_purchases
+            elif res_model == 'product.template':
+                purchased_product_ids = request.env['product.product'].sudo().browse(
+                    digital_purchases
+                ).mapped('product_tmpl_id').ids
+            else:
+                purchased_product_ids = []  # The purchases must be related to products.
+            if res_id not in purchased_product_ids:  # No related purchase was found.
+                return redirect(self.orders_page)  # Prevent the user from downloading.
 
-        # The client has bought the product, otherwise it would have been blocked by now
+        # The user has bought the product, or has the rights to the attachment
         if attachment["type"] == "url":
             if attachment["url"]:
                 return redirect(attachment["url"])
-- 
GitLab