Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 27 additions & 4 deletions docker/scripts/odoo_website_bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,29 @@ def _canonical_host(canonical_url: str) -> str:
return urlparse(canonical_url).netloc or canonical_url


def _canonical_domain_matches(actual_value: object, canonical_url: str) -> bool:
actual_domain = str(actual_value or "").strip().rstrip("/")
return bool(actual_domain) and actual_domain in _canonical_domain_candidates(canonical_url)


def _canonical_domain_candidates(canonical_url: str) -> tuple[str, ...]:
canonical_domain = _canonical_host(canonical_url).strip().rstrip("/")
canonical_value = canonical_url.strip()
canonical_value_without_slash = canonical_value.rstrip("/")
return tuple(value for value in dict.fromkeys((canonical_domain, canonical_value_without_slash, canonical_value)) if value)


def _assert_canonical_domain(record: Any, field_name: str, canonical_url: str) -> None:
if field_name not in record._fields:
raise RuntimeError(f"Website bootstrap cannot verify canonical domain; missing field: {field_name}.")
actual_value = _field_value(record, field_name)
if not _canonical_domain_matches(actual_value, canonical_url):
raise RuntimeError(
"Website bootstrap failed to persist canonical domain: "
f"expected {_canonical_host(canonical_url)!r} or {canonical_url!r}, got {actual_value!r}."
)


def _marker_bool(value: bool) -> str:
return "true" if value else "false"

Expand Down Expand Up @@ -227,7 +250,7 @@ def _print_bootstrap_readback(

print(f"website_bootstrap_website_id={getattr(website, 'id', '')}")
print(f"website_bootstrap_domain_set={_marker_bool(bool(website_domain))}")
print(f"website_bootstrap_domain_matches_canonical={_marker_bool(bool(canonical_host) and website_domain == canonical_host)}")
print(f"website_bootstrap_domain_matches_canonical={_marker_bool(_canonical_domain_matches(website_domain, canonical_url))}")
print(f"website_bootstrap_web_base_url_matches={_marker_bool(not canonical_url or web_base_url_matches)}")
print(f"website_bootstrap_homepage_url_set={_marker_bool(bool(actual_homepage_url))}")
print(f"website_bootstrap_homepage_url_matches={_marker_bool(bool(homepage_url) and actual_homepage_url == homepage_url)}")
Expand Down Expand Up @@ -260,7 +283,7 @@ def _select_website(
return page_website.sudo()
canonical_host = _canonical_host(canonical_url)
if canonical_host and "domain" in website_model._fields:
website = website_model.search([("domain", "in", (canonical_host, canonical_url))], order="id", limit=1)
website = website_model.search([("domain", "in", _canonical_domain_candidates(canonical_url))], order="id", limit=1)
if website:
return website
if default_website:
Expand All @@ -275,7 +298,7 @@ def _clear_duplicate_canonical_domains(website_model: Any, *, website: Any, cano
duplicates = website_model.search(
[
("id", "!=", website.id),
("domain", "in", (canonical_host, canonical_url)),
("domain", "in", _canonical_domain_candidates(canonical_url)),
],
order="id",
)
Expand Down Expand Up @@ -471,7 +494,7 @@ def apply_website_bootstrap(env: Any, parsed_payload: dict[str, object] | None)
if website_name:
_assert_field_value(website, "name", website_name, label="website name")
if canonical_url:
_assert_field_value(website, "domain", _canonical_host(canonical_url), label="canonical domain")
_assert_canonical_domain(website, "domain", canonical_url)
if logo_expected:
_assert_binary_field_value(website, "logo", logo_value, label="website logo")

Expand Down
58 changes: 58 additions & 0 deletions tests/test_odoo_website_bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ def __init__(
self.truthy = truthy
self.persist_writes = True
self.ignored_write_fields: set[str] = set()
self.normalized_write_values: dict[str, object] = {}
for field_name in self._fields:
setattr(self, field_name, None)
for field_name, value in (values or {}).items():
Expand All @@ -63,6 +64,7 @@ def write(self, values: dict[str, object]) -> None:
for field_name, value in values.items():
if field_name in self.ignored_write_fields:
continue
value = self.normalized_write_values.get(field_name, value)
setattr(self, field_name, value)


Expand Down Expand Up @@ -241,6 +243,62 @@ def test_controller_homepage_route_persists_homepage_url_and_clears_stale_page_h
self.assertEqual(env.config_parameter.values["web.base.url.freeze"], "True")
self.assertIn({"name": "OPW", "domain": "opw-testing.example.com"}, env.website.writes)

def test_accepts_odoo_normalized_full_url_canonical_domain(self) -> None:
env = FakeEnv()
env.website.normalized_write_values["domain"] = "https://opw-testing.example.com"
payload = {
"website_bootstrap": {
"name": "OPW",
"canonical_url": "https://opw-testing.example.com",
}
}
output = io.StringIO()

with redirect_stdout(output):
website_bootstrap.apply_website_bootstrap(env, payload)

self.assertIn({"name": "OPW", "domain": "opw-testing.example.com"}, env.website.writes)
self.assertEqual(env.website.domain, "https://opw-testing.example.com")
self.assertIn("website_bootstrap_domain_matches_canonical=true", output.getvalue())
self.assertIn("website_bootstrap_applied=true", output.getvalue())

def test_selects_odoo_normalized_full_url_domain_when_canonical_has_trailing_slash(self) -> None:
env = FakeEnv()
existing_website = FakeRecord(
record_id=2,
fields=("name", "domain", "homepage_id", "homepage_url", "logo"),
values={"domain": "https://opw-testing.example.com/"},
)
env.website_model = FakeModel(record=existing_website, fields=("name", "domain", "homepage_id", "homepage_url", "logo"))
payload = {
"website_bootstrap": {
"name": "OPW",
"canonical_url": "https://opw-testing.example.com/",
}
}

website_bootstrap.apply_website_bootstrap(env, payload)

self.assertEqual(existing_website.name, "OPW")
self.assertIn({"name": "OPW", "domain": "opw-testing.example.com"}, existing_website.writes)
self.assertEqual(
env.website_model.searches[0][0],
(
[
(
"domain",
"in",
(
"opw-testing.example.com",
"https://opw-testing.example.com",
"https://opw-testing.example.com/",
),
)
],
),
)
self.assertEqual(env.website_model.searches[0][1], {"order": "id", "limit": 1})

def test_config_parameter_web_base_url_supplies_canonical_when_bootstrap_payload_omits_it(self) -> None:
env = FakeEnv()
payload = {
Expand Down