|
60 | 60 | ## ## |
61 | 61 | ##————————————————————————————————————————————————————————————————————————————## |
62 | 62 |
|
| 63 | +def parse_metadata_providers_enabled(raw_value): |
| 64 | + """ |
| 65 | + Parse the metadata_providers_enabled setting from various formats into a dict. |
| 66 | + |
| 67 | + Args: |
| 68 | + raw_value: The raw value from database/settings (str, dict, bytes, or None) |
| 69 | + |
| 70 | + Returns: |
| 71 | + dict: Provider ID to enabled status mapping. Empty dict on error. |
| 72 | + """ |
| 73 | + import json |
| 74 | + |
| 75 | + try: |
| 76 | + # Handle None/null values |
| 77 | + if raw_value is None: |
| 78 | + return {} |
| 79 | + |
| 80 | + # Handle bytes (from some database drivers) |
| 81 | + if isinstance(raw_value, bytes): |
| 82 | + raw_value = raw_value.decode('utf-8', errors='ignore') |
| 83 | + |
| 84 | + # Handle string (most common case) |
| 85 | + if isinstance(raw_value, str): |
| 86 | + s = raw_value.strip() |
| 87 | + # Handle empty strings |
| 88 | + if not s: |
| 89 | + return {} |
| 90 | + # Strip surrounding single quotes if present from schema default |
| 91 | + if s.startswith("'") and s.endswith("'"): |
| 92 | + s = s[1:-1] |
| 93 | + # Handle empty string after quote stripping |
| 94 | + if not s: |
| 95 | + return {} |
| 96 | + data = json.loads(s) |
| 97 | + return data if isinstance(data, dict) else {} |
| 98 | + |
| 99 | + # Handle dict (already parsed) |
| 100 | + elif isinstance(raw_value, dict): |
| 101 | + return raw_value |
| 102 | + |
| 103 | + # Unknown type, return empty dict |
| 104 | + else: |
| 105 | + return {} |
| 106 | + |
| 107 | + except (json.JSONDecodeError, ValueError, TypeError, AttributeError): |
| 108 | + return {} |
| 109 | + |
| 110 | +def validate_and_cleanup_provider_enabled_map(enabled_map, available_provider_ids): |
| 111 | + """ |
| 112 | + Validate and cleanup the provider enabled map. |
| 113 | + |
| 114 | + Args: |
| 115 | + enabled_map (dict): Current provider enabled map |
| 116 | + available_provider_ids (list): List of valid provider IDs |
| 117 | + |
| 118 | + Returns: |
| 119 | + dict: Cleaned up enabled map with only valid providers |
| 120 | + """ |
| 121 | + if not isinstance(enabled_map, dict): |
| 122 | + return {} |
| 123 | + |
| 124 | + if not isinstance(available_provider_ids, (list, tuple, set)): |
| 125 | + return {} |
| 126 | + |
| 127 | + # Keep only valid provider IDs and boolean values |
| 128 | + cleaned_map = {} |
| 129 | + for provider_id, enabled in enabled_map.items(): |
| 130 | + if (isinstance(provider_id, str) and |
| 131 | + provider_id.strip() and # Non-empty string |
| 132 | + provider_id in available_provider_ids): |
| 133 | + # Convert to boolean, handling various truthy/falsy values |
| 134 | + cleaned_map[provider_id] = bool(enabled) |
| 135 | + |
| 136 | + return cleaned_map |
| 137 | + |
63 | 138 | @switch_theme.route("/cwa-switch-theme", methods=["GET", "POST"]) |
64 | 139 | @login_required_if_no_ano |
65 | 140 | def cwa_switch_theme(): |
@@ -313,8 +388,13 @@ def set_cwa_settings(): |
313 | 388 | result[setting] = cwa_db.cwa_settings.get(setting, '["ibdb","google","dnb"]') |
314 | 389 | elif setting == 'metadata_providers_enabled': |
315 | 390 | # Validate dict mapping provider_id -> bool |
316 | | - if isinstance(json_value, dict) and all(isinstance(k, str) and isinstance(v, bool) for k, v in json_value.items()): |
317 | | - result[setting] = json.dumps(json_value) |
| 391 | + if isinstance(json_value, dict): |
| 392 | + # Just validate the basic structure - provider validation happens at runtime |
| 393 | + cleaned_map = {} |
| 394 | + for k, v in json_value.items(): |
| 395 | + if isinstance(k, str) and isinstance(v, bool): |
| 396 | + cleaned_map[k] = v |
| 397 | + result[setting] = json.dumps(cleaned_map) |
318 | 398 | else: |
319 | 399 | result[setting] = cwa_db.cwa_settings.get(setting, '{}') |
320 | 400 | else: |
|
0 commit comments