[FIX] website: handle RequestUID case in slug

Before this commit, a 308 on a route with a modelconverter for a model
that have a seo_name field will crash with an exception:
Cannot iterate on RequestUID

Another simplest solution was to use a with_user(SUPERUSER_ID) but in this case
it bypass the security set and display the name of the record even if not yet
published.

How to reproduce:

Create a 308 from /shop/<product> to /mag/<product>
Unpublish product 10
Try to access /shop/product-10

You have an unmanaged '500 internal error"
because slug_matching -> build -> to_url -> slug with a record with Requestuid
as env._uid.

X-original-commit: 4ac2cab96655a3c5e673b0a04be5599dba507850
This commit is contained in:
Jeremy Kersten
2021-02-01 14:51:19 +00:00
parent 4a88d09632
commit 2ecc538d51
2 changed files with 7 additions and 3 deletions
+1 -1
View File
@@ -257,7 +257,7 @@ class ModelConverter(ir_http.ModelConverter):
# limited support for negative IDs due to our slug pattern, assume abs() if not found
if not env[self.model].browse(record_id).exists():
record_id = abs(record_id)
return env[self.model].browse(record_id)
return env[self.model].with_context(_converter_value=value).browse(record_id)
class IrHttp(models.AbstractModel):
+6 -2
View File
@@ -20,7 +20,6 @@ from odoo.exceptions import AccessError
from odoo.http import request
from odoo.tools.safe_eval import safe_eval
from odoo.osv.expression import FALSE_DOMAIN
from odoo.addons.http_routing.models import ir_http
from odoo.addons.http_routing.models.ir_http import _guess_mimetype
from odoo.addons.portal.controllers.portal import _build_url_w_params
@@ -77,7 +76,7 @@ class Http(models.AbstractModel):
def _slug_matching(cls, adapter, endpoint, **kw):
for arg in kw:
if isinstance(kw[arg], models.BaseModel):
kw[arg] = kw[arg].with_user(request.uid)
kw[arg] = kw[arg].with_context(slug_matching=True)
qs = request.httprequest.query_string.decode('utf-8')
return adapter.build(endpoint, kw) + (qs and '?%s' % qs or '')
@@ -438,6 +437,11 @@ class Http(models.AbstractModel):
class ModelConverter(ir_http.ModelConverter):
def to_url(self, value):
if value.env.context.get('slug_matching'):
return value.env.context.get('_converter_value', str(value.id))
return super().to_url(value)
def generate(self, uid, dom=None, args=None):
Model = request.env[self.model].with_user(uid)
# Allow to current_website_id directly in route domain