| 131 | |
| 132 | |
| 133 | def validate_config(config): |
| 134 | if not isinstance(config, dict): |
| 135 | raise ApiError(400, "config must be a JSON object") |
| 136 | config = dict(config) |
| 137 | for key, meta in COLLECTIONS.items(): |
| 138 | items = config.get(key, []) |
| 139 | if not isinstance(items, list): |
| 140 | raise ApiError(400, f"{key} must be an array") |
| 141 | normalized = [] |
| 142 | seen = set() |
| 143 | for index, item in enumerate(items): |
| 144 | entry = meta["validator"](item, index=index) |
| 145 | if key == "servers": |
| 146 | username = entry["username"] |
| 147 | if username in seen: |
| 148 | raise ApiError(409, "duplicate server username", {"username": username}) |
| 149 | seen.add(username) |
| 150 | normalized.append(entry) |
| 151 | config[key] = normalized |
| 152 | return config |
| 153 | |
| 154 | |
| 155 | def write_config(config): |