|
29 | 29 | if TYPE_CHECKING: |
30 | 30 | from pypaimon.catalog.rest.rest_token import RESTToken |
31 | 31 |
|
32 | | -from pypaimon.api.api_request import (AlterTableRequest, CreateDatabaseRequest, |
| 32 | +from pypaimon.api.api_request import (AlterDatabaseRequest, AlterTableRequest, |
| 33 | + CreateDatabaseRequest, |
33 | 34 | CreateTableRequest, RenameTableRequest) |
34 | 35 | from pypaimon.api.api_response import (ConfigResponse, GetDatabaseResponse, |
35 | 36 | GetTableResponse, ListDatabasesResponse, |
|
45 | 46 | TableAlreadyExistException) |
46 | 47 | from pypaimon.catalog.rest.table_metadata import TableMetadata |
47 | 48 | from pypaimon.common.identifier import Identifier |
| 49 | +from pypaimon.api.typedef import RESTAuthParameter |
48 | 50 | from pypaimon.common.json_util import JSON |
49 | 51 | from pypaimon import Schema |
50 | 52 | from pypaimon.schema.schema_change import Actions, SchemaChange |
@@ -258,11 +260,11 @@ def _handle_request(self, method: str): |
258 | 260 | content_length = int(self.headers.get('Content-Length', 0)) |
259 | 261 | data = self.rfile.read(content_length).decode('utf-8') if content_length > 0 else "" |
260 | 262 |
|
261 | | - # Get headers |
| 263 | + # Get headers (case-insensitive from HTTPMessage) |
| 264 | + auth_token = self.headers.get(AUTHORIZATION_HEADER_KEY) |
262 | 265 | headers = dict(self.headers) |
263 | 266 |
|
264 | 267 | # Handle authentication |
265 | | - auth_token = headers.get(AUTHORIZATION_HEADER_KEY.lower()) |
266 | 268 | if not self._authenticate(auth_token, resource_path, parameters, method, data): |
267 | 269 | self._send_response(401, "Unauthorized") |
268 | 270 | return |
@@ -292,9 +294,25 @@ def _parse_query_params(self, query: str) -> Dict[str, str]: |
292 | 294 |
|
293 | 295 | def _authenticate(self, token: str, path: str, params: Dict[str, str], |
294 | 296 | method: str, data: str) -> bool: |
295 | | - """Authenticate request""" |
296 | | - # Simplified authentication - always return True for mock |
297 | | - return True |
| 297 | + """Authenticate request by verifying Authorization header.""" |
| 298 | + if server_instance.auth_provider is None: |
| 299 | + return True |
| 300 | + if path.startswith("/ram/security-credential"): |
| 301 | + return True |
| 302 | + if not token: |
| 303 | + return False |
| 304 | + rest_auth_parameter = RESTAuthParameter( |
| 305 | + method=method, |
| 306 | + path=path, |
| 307 | + data=data or "", |
| 308 | + parameters=params or {}, |
| 309 | + ) |
| 310 | + from pypaimon.api.auth.base import RESTAuthFunction |
| 311 | + auth_fn = RESTAuthFunction({}, server_instance.auth_provider) |
| 312 | + expected_headers = auth_fn(rest_auth_parameter) |
| 313 | + expected_token = expected_headers.get( |
| 314 | + AUTHORIZATION_HEADER_KEY, "") |
| 315 | + return token == expected_token |
298 | 316 |
|
299 | 317 | def _send_response(self, status_code: int, body: str): |
300 | 318 | """Send HTTP response""" |
@@ -514,6 +532,18 @@ def _database_handle(self, method: str, data: str, database_name: str) -> Tuple[ |
514 | 532 | response = database |
515 | 533 | return self._mock_response(response, 200) |
516 | 534 |
|
| 535 | + elif method == "POST": |
| 536 | + request_body = JSON.from_json(data, AlterDatabaseRequest) |
| 537 | + removals = request_body.removals or [] |
| 538 | + updates = request_body.updates or {} |
| 539 | + options = dict(database.options) if database.options else {} |
| 540 | + options.update(updates) |
| 541 | + for key in removals: |
| 542 | + options.pop(key, None) |
| 543 | + self.database_store[database_name] = self.mock_database( |
| 544 | + database_name, options) |
| 545 | + return self._mock_response("", 200) |
| 546 | + |
517 | 547 | elif method == "DELETE": |
518 | 548 | del self.database_store[database_name] |
519 | 549 | return self._mock_response("", 200) |
|
0 commit comments