fix(security_settings): enabled track_changes and convert expires to UTC timezone (#38675)

* fix(security_settings): convert expires timestamp from system timezone to UTC

* fix(security_settings): enabled `track_changes` on `Security Settings` DocType
This commit is contained in:
diptanilsaha 2026-04-17 14:29:28 +05:30 committed by GitHub
parent 3418b221da
commit 37b05961c7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 20 additions and 11 deletions

View file

@ -18,7 +18,7 @@
"label": "Security.txt" "label": "Security.txt"
}, },
{ {
"description": "Date after which this security.txt should be considered stale.", "description": "Date after which this security.txt should be considered stale. Expires timestamp is converted to UTC.",
"fieldname": "public_expires", "fieldname": "public_expires",
"fieldtype": "Datetime", "fieldtype": "Datetime",
"label": "Expires" "label": "Expires"
@ -56,7 +56,7 @@
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"issingle": 1, "issingle": 1,
"links": [], "links": [],
"modified": "2026-04-14 12:50:57.138749", "modified": "2026-04-17 13:07:45.259146",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Core", "module": "Core",
"name": "Security Settings", "name": "Security Settings",
@ -77,5 +77,6 @@
"rows_threshold_for_grid_search": 20, "rows_threshold_for_grid_search": 20,
"sort_field": "creation", "sort_field": "creation",
"sort_order": "DESC", "sort_order": "DESC",
"states": [] "states": [],
"track_changes": 1
} }

View file

@ -2,12 +2,19 @@
# For license information, please see license.txt # For license information, please see license.txt
from datetime import UTC, datetime from datetime import UTC, datetime
from zoneinfo import ZoneInfo
import frappe import frappe
import frappe.utils import frappe.utils
from frappe import _ from frappe import _
from frappe.model.document import Document from frappe.model.document import Document
from frappe.utils import validate_email_address, validate_phone_number, validate_url from frappe.utils import (
get_system_timezone,
now_datetime,
validate_email_address,
validate_phone_number,
validate_url,
)
class SecuritySettings(Document): class SecuritySettings(Document):
@ -69,8 +76,7 @@ class SecuritySettings(Document):
expires = self.public_expires or frappe.utils.add_years(frappe.utils.now_datetime(), 1) expires = self.public_expires or frappe.utils.add_years(frappe.utils.now_datetime(), 1)
if isinstance(expires, str): if isinstance(expires, str):
expires = datetime.fromisoformat(expires) expires = datetime.fromisoformat(expires)
expires = expires.replace(microsecond=0) expires = expires.replace(microsecond=0, tzinfo=ZoneInfo(get_system_timezone())).astimezone(UTC)
expires = expires.astimezone(UTC)
value = expires.strftime("%Y-%m-%dT%H:%M:%SZ") value = expires.strftime("%Y-%m-%dT%H:%M:%SZ")
return f"Expires: {value}" return f"Expires: {value}"
@ -112,5 +118,5 @@ class SecuritySettings(Document):
expires = self.public_expires expires = self.public_expires
if isinstance(expires, str): if isinstance(expires, str):
expires = datetime.fromisoformat(expires) expires = datetime.fromisoformat(expires)
if expires <= datetime.now(): if expires <= now_datetime():
frappe.throw(_("Expiration date must be in the future")) frappe.throw(_("Expiration date must be in the future"))

View file

@ -4,10 +4,10 @@
from datetime import UTC, datetime, timedelta from datetime import UTC, datetime, timedelta
import frappe import frappe
from frappe.tests import UnitTestCase from frappe.tests import IntegrationTestCase
class TestSecuritySettings(UnitTestCase): class TestSecuritySettings(IntegrationTestCase):
def test_public_policy_section_default(self): def test_public_policy_section_default(self):
doc = frappe.get_doc( doc = frappe.get_doc(
{ {
@ -239,10 +239,11 @@ class TestSecuritySettings(UnitTestCase):
# Should not raise # Should not raise
doc.validate_expires() doc.validate_expires()
@IntegrationTestCase.change_settings("System Settings", {"time_zone": "Etc/UTC"})
def test_public_expires_section_future_date(self): def test_public_expires_section_future_date(self):
from datetime import timezone from datetime import timezone
future_date = datetime(2027, 12, 31, 23, 59, 59, tzinfo=UTC) future_date = datetime(2027, 12, 31, 23, 59, 59)
doc = frappe.get_doc( doc = frappe.get_doc(
{ {
"doctype": "Security Settings", "doctype": "Security Settings",
@ -252,11 +253,12 @@ class TestSecuritySettings(UnitTestCase):
section = doc.public_expires_section section = doc.public_expires_section
self.assertIn("2027-12-31T23:59:59Z", section) self.assertIn("2027-12-31T23:59:59Z", section)
@IntegrationTestCase.change_settings("System Settings", {"time_zone": "Asia/Kolkata"})
def test_public_expires_section_string(self): def test_public_expires_section_string(self):
doc = frappe.get_doc( doc = frappe.get_doc(
{ {
"doctype": "Security Settings", "doctype": "Security Settings",
"public_expires": "2027-12-31T23:59:59+00:00", "public_expires": "2028-01-01T05:29:59",
} }
) )
section = doc.public_expires_section section = doc.public_expires_section