From e8069e1c073e26003956533d3900d83687cc1095 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Sun, 9 Mar 2025 15:15:27 +0100 Subject: [PATCH] Add template functions: md5, sha1, sha256, sha512 (#140192) --- homeassistant/helpers/template.py | 29 +++++++++++++++++ tests/helpers/test_template.py | 52 +++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/homeassistant/helpers/template.py b/homeassistant/helpers/template.py index 357fe15f3be..20531596fdd 100644 --- a/homeassistant/helpers/template.py +++ b/homeassistant/helpers/template.py @@ -12,6 +12,7 @@ from contextvars import ContextVar from copy import deepcopy from datetime import date, datetime, time, timedelta from functools import cache, lru_cache, partial, wraps +import hashlib import json import logging import math @@ -2784,6 +2785,26 @@ def flatten(value: Iterable[Any], levels: int | None = None) -> list[Any]: return flattened +def md5(value: str) -> str: + """Generate md5 hash from a string.""" + return hashlib.md5(value.encode()).hexdigest() + + +def sha1(value: str) -> str: + """Generate sha1 hash from a string.""" + return hashlib.sha1(value.encode()).hexdigest() + + +def sha256(value: str) -> str: + """Generate sha256 hash from a string.""" + return hashlib.sha256(value.encode()).hexdigest() + + +def sha512(value: str) -> str: + """Generate sha512 hash from a string.""" + return hashlib.sha512(value.encode()).hexdigest() + + class TemplateContextManager(AbstractContextManager): """Context manager to store template being parsed or rendered in a ContextVar.""" @@ -2987,6 +3008,10 @@ class TemplateEnvironment(ImmutableSandboxedEnvironment): self.filters["shuffle"] = shuffle self.filters["typeof"] = typeof self.filters["flatten"] = flatten + self.filters["md5"] = md5 + self.filters["sha1"] = sha1 + self.filters["sha256"] = sha256 + self.filters["sha512"] = sha512 self.globals["log"] = logarithm self.globals["sin"] = sine self.globals["cos"] = cosine @@ -3027,6 +3052,10 @@ class TemplateEnvironment(ImmutableSandboxedEnvironment): self.globals["shuffle"] = shuffle self.globals["typeof"] = typeof self.globals["flatten"] = flatten + self.globals["md5"] = md5 + self.globals["sha1"] = sha1 + self.globals["sha256"] = sha256 + self.globals["sha512"] = sha512 self.tests["is_number"] = is_number self.tests["list"] = _is_list self.tests["set"] = _is_set diff --git a/tests/helpers/test_template.py b/tests/helpers/test_template.py index f9154b23bad..bdf400ce357 100644 --- a/tests/helpers/test_template.py +++ b/tests/helpers/test_template.py @@ -6788,3 +6788,55 @@ def test_flatten(hass: HomeAssistant) -> None: with pytest.raises(TemplateError): template.Template("{{ flatten() }}", hass).async_render() + + +def test_md5(hass: HomeAssistant) -> None: + """Test the md5 function and filter.""" + assert ( + template.Template("{{ md5('Home Assistant') }}", hass).async_render() + == "3d15e5c102c3413d0337393c3287e006" + ) + + assert ( + template.Template("{{ 'Home Assistant' | md5 }}", hass).async_render() + == "3d15e5c102c3413d0337393c3287e006" + ) + + +def test_sha1(hass: HomeAssistant) -> None: + """Test the sha1 function and filter.""" + assert ( + template.Template("{{ sha1('Home Assistant') }}", hass).async_render() + == "c8fd3bb19b94312664faa619af7729bdbf6e9f8a" + ) + + assert ( + template.Template("{{ 'Home Assistant' | sha1 }}", hass).async_render() + == "c8fd3bb19b94312664faa619af7729bdbf6e9f8a" + ) + + +def test_sha256(hass: HomeAssistant) -> None: + """Test the sha256 function and filter.""" + assert ( + template.Template("{{ sha256('Home Assistant') }}", hass).async_render() + == "2a366abb0cd47f51f3725bf0fb7ebcb4fefa6e20f4971e25fe2bb8da8145ce2b" + ) + + assert ( + template.Template("{{ 'Home Assistant' | sha256 }}", hass).async_render() + == "2a366abb0cd47f51f3725bf0fb7ebcb4fefa6e20f4971e25fe2bb8da8145ce2b" + ) + + +def test_sha512(hass: HomeAssistant) -> None: + """Test the sha512 function and filter.""" + assert ( + template.Template("{{ sha512('Home Assistant') }}", hass).async_render() + == "9e3c2cdd1fbab0037378d37e1baf8a3a4bf92c54b56ad1d459deee30ccbb2acbebd7a3614552ea08992ad27dedeb7b4c5473525ba90cb73dbe8b9ec5f69295bb" + ) + + assert ( + template.Template("{{ 'Home Assistant' | sha512 }}", hass).async_render() + == "9e3c2cdd1fbab0037378d37e1baf8a3a4bf92c54b56ad1d459deee30ccbb2acbebd7a3614552ea08992ad27dedeb7b4c5473525ba90cb73dbe8b9ec5f69295bb" + )