Error on startup if invalid setting types

This commit is contained in:
Simon Willison 2025-10-24 00:14:28 -07:00
commit 23715d6c00
5 changed files with 96 additions and 15 deletions

View file

@ -394,10 +394,37 @@ class Datasette:
config = config or {}
config_settings = config.get("settings") or {}
# validate "settings" keys in datasette.json
for key in config_settings:
# Validate settings from config file
for key, value in config_settings.items():
if key not in DEFAULT_SETTINGS:
raise StartupError("Invalid setting '{}' in datasette.json".format(key))
raise StartupError(f"Invalid setting '{key}' in config file")
# Validate type matches expected type from DEFAULT_SETTINGS
if value is not None: # Allow None/null values
expected_type = type(DEFAULT_SETTINGS[key])
actual_type = type(value)
if actual_type != expected_type:
raise StartupError(
f"Setting '{key}' in config file has incorrect type. "
f"Expected {expected_type.__name__}, got {actual_type.__name__}. "
f"Value: {value!r}. "
f"Hint: In YAML/JSON config files, remove quotes from boolean and integer values."
)
# Validate settings from constructor parameter
if settings:
for key, value in settings.items():
if key not in DEFAULT_SETTINGS:
raise StartupError(f"Invalid setting '{key}' in settings parameter")
if value is not None:
expected_type = type(DEFAULT_SETTINGS[key])
actual_type = type(value)
if actual_type != expected_type:
raise StartupError(
f"Setting '{key}' in settings parameter has incorrect type. "
f"Expected {expected_type.__name__}, got {actual_type.__name__}. "
f"Value: {value!r}"
)
self.config = config
# CLI settings should overwrite datasette.json settings
self._settings = dict(DEFAULT_SETTINGS, **(config_settings), **(settings or {}))

View file

@ -179,9 +179,7 @@ def permission_allowed_default_allow_sql(datasette, actor, action, resource):
This runs before other permission checks to ensure the setting is respected.
"""
if action == "execute-sql":
default_allow_sql_setting = datasette.setting("default_allow_sql")
# Handle both boolean False and string "false" (from CLI)
if default_allow_sql_setting in (False, "false"):
if not datasette.setting("default_allow_sql"):
return False
return None
@ -227,9 +225,7 @@ async def permission_resources_sql(datasette, actor, action):
rules.extend(config_rules)
# Check default_allow_sql setting for execute-sql action
default_allow_sql_setting = datasette.setting("default_allow_sql")
# Handle both boolean False and string "false" (from CLI)
if action == "execute-sql" and default_allow_sql_setting in (False, "false"):
if action == "execute-sql" and not datasette.setting("default_allow_sql"):
# Return a deny rule for all databases
sql = "SELECT NULL AS parent, NULL AS child, 0 AS allow, 'default_allow_sql is false' AS reason"
rules.append(