Skip to content

Commit 3ba9659

Browse files
committed
edit server and resource
Signed-off-by: RAKHI DUTTA <[email protected]>
1 parent 27fbed4 commit 3ba9659

File tree

3 files changed

+80
-38
lines changed

3 files changed

+80
-38
lines changed

mcpgateway/admin.py

Lines changed: 70 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
from mcpgateway.services.prompt_service import PromptNotFoundError, PromptService
6363
from mcpgateway.services.resource_service import ResourceNotFoundError, ResourceService
6464
from mcpgateway.services.root_service import RootService
65-
from mcpgateway.services.server_service import ServerError, ServerNotFoundError, ServerService
65+
from mcpgateway.services.server_service import ServerError, ServerNotFoundError, ServerService, ServerNameConflictError
6666
from mcpgateway.services.tool_service import ToolError, ToolNotFoundError, ToolService
6767
from mcpgateway.utils.create_jwt_token import get_jwt_token
6868
from mcpgateway.utils.error_formatter import ErrorFormatter
@@ -294,7 +294,7 @@ async def admin_get_server(server_id: str, db: Session = Depends(get_db), user:
294294

295295

296296
@admin_router.post("/servers", response_model=ServerRead)
297-
async def admin_add_server(request: Request, db: Session = Depends(get_db), user: str = Depends(require_auth)) -> RedirectResponse:
297+
async def admin_add_server(request: Request, db: Session = Depends(get_db), user: str = Depends(require_auth)) -> JSONResponse:
298298
"""
299299
Add a new server via the admin UI.
300300
@@ -316,7 +316,7 @@ async def admin_add_server(request: Request, db: Session = Depends(get_db), user
316316
user (str): Authenticated user dependency
317317
318318
Returns:
319-
RedirectResponse: A redirect to the admin dashboard catalog section
319+
JSONResponse: A JSON response indicating success or failure of the server creation operation.
320320
321321
Examples:
322322
>>> import asyncio
@@ -436,7 +436,6 @@ async def admin_add_server(request: Request, db: Session = Depends(get_db), user
436436
return JSONResponse(content={"message": str(ex), "success": False}, status_code=422)
437437

438438
except Exception as ex:
439-
logger.info(f"error,{ex}")
440439
if isinstance(ex, ServerError):
441440
# Custom server logic error — 500 Internal Server Error makes sense
442441
return JSONResponse(content={"message": str(ex), "success": False}, status_code=500)
@@ -467,7 +466,7 @@ async def admin_edit_server(
467466
request: Request,
468467
db: Session = Depends(get_db),
469468
user: str = Depends(require_auth),
470-
) -> RedirectResponse:
469+
) -> JSONResponse:
471470
"""
472471
Edit an existing server via the admin UI.
473472
@@ -490,7 +489,7 @@ async def admin_edit_server(
490489
user (str): Authenticated user dependency
491490
492491
Returns:
493-
RedirectResponse: A redirect to the admin dashboard catalog section with a status code of 303
492+
JSONResponse: A JSON response indicating success or failure of the server update operation.
494493
495494
Examples:
496495
>>> import asyncio
@@ -546,7 +545,7 @@ async def admin_edit_server(
546545
>>> server_service.update_server = original_update_server
547546
"""
548547
form = await request.form()
549-
is_inactive_checked = form.get("is_inactive_checked", "false")
548+
# is_inactive_checked = form.get("is_inactive_checked", "false")
550549
try:
551550
logger.debug(f"User {user} is editing server ID {server_id} with name: {form.get('name')}")
552551
server = ServerUpdate(
@@ -559,18 +558,42 @@ async def admin_edit_server(
559558
)
560559
await server_service.update_server(db, server_id, server)
561560

562-
root_path = request.scope.get("root_path", "")
561+
# root_path = request.scope.get("root_path", "")
563562

564-
if is_inactive_checked.lower() == "true":
565-
return RedirectResponse(f"{root_path}/admin/?include_inactive=true#catalog", status_code=303)
566-
return RedirectResponse(f"{root_path}/admin#catalog", status_code=303)
567-
except Exception as e:
568-
logger.error(f"Error editing server: {e}")
563+
# if is_inactive_checked.lower() == "true":
564+
# return RedirectResponse(f"{root_path}/admin/?include_inactive=true#catalog", status_code=303)
565+
# return RedirectResponse(f"{root_path}/admin#catalog", status_code=303)
566+
return JSONResponse(
567+
content={"message": "Server update successfully!", "success": True},
568+
status_code=200,
569+
)
570+
except Exception as ex:
571+
if isinstance(ex, ServerNameConflictError):
572+
# Custom server name conflict error — 409 Conflict is appropriate
573+
return JSONResponse(content={"message": str(ex), "success": False}, status_code=409)
569574

570-
root_path = request.scope.get("root_path", "")
571-
if is_inactive_checked.lower() == "true":
572-
return RedirectResponse(f"{root_path}/admin/?include_inactive=true#catalog", status_code=303)
573-
return RedirectResponse(f"{root_path}/admin#catalog", status_code=303)
575+
if isinstance(ex, ServerError):
576+
# Custom server logic error — 500 Internal Server Error makes sense
577+
return JSONResponse(content={"message": str(ex), "success": False}, status_code=500)
578+
579+
if isinstance(ex, ValueError):
580+
# Invalid input — 400 Bad Request is appropriate
581+
return JSONResponse(content={"message": str(ex), "success": False}, status_code=400)
582+
583+
if isinstance(ex, RuntimeError):
584+
# Unexpected error during runtime — 500 is suitable
585+
return JSONResponse(content={"message": str(ex), "success": False}, status_code=500)
586+
587+
if isinstance(ex, ValidationError):
588+
# Pydantic or input validation failure — 422 Unprocessable Entity is correct
589+
return JSONResponse(content=ErrorFormatter.format_validation_error(ex), status_code=422)
590+
591+
if isinstance(ex, IntegrityError):
592+
# DB constraint violation — 409 Conflict is appropriate
593+
return JSONResponse(content=ErrorFormatter.format_database_error(ex), status_code=409)
594+
595+
# For any other unhandled error, default to 500
596+
return JSONResponse(content={"message": str(ex), "success": False}, status_code=500)
574597

575598

576599
@admin_router.post("/servers/{server_id}/toggle")
@@ -1935,7 +1958,7 @@ async def admin_edit_tool(
19351958
return JSONResponse(content={"message": "Edit tool successfully", "success": True}, status_code=200)
19361959
except IntegrityError as ex:
19371960
error_message = ErrorFormatter.format_database_error(ex)
1938-
logger.error(f"IntegrityError in admin_edit_resource: {error_message}")
1961+
logger.error(f"IntegrityError in admin_tool_resource: {error_message}")
19391962
return JSONResponse(status_code=409, content=error_message)
19401963
except ToolError as ex:
19411964
logger.error(f"ToolError in admin_edit_tool: {str(ex)}")
@@ -2686,7 +2709,7 @@ async def admin_get_resource(uri: str, db: Session = Depends(get_db), user: str
26862709

26872710

26882711
@admin_router.post("/resources")
2689-
async def admin_add_resource(request: Request, db: Session = Depends(get_db), user: str = Depends(require_auth)) -> RedirectResponse:
2712+
async def admin_add_resource(request: Request, db: Session = Depends(get_db), user: str = Depends(require_auth)) -> JSONResponse:
26902713
"""
26912714
Add a resource via the admin UI.
26922715
@@ -2771,7 +2794,7 @@ async def admin_edit_resource(
27712794
request: Request,
27722795
db: Session = Depends(get_db),
27732796
user: str = Depends(require_auth),
2774-
) -> RedirectResponse:
2797+
) -> JSONResponse:
27752798
"""
27762799
Edit a resource via the admin UI.
27772800
@@ -2788,7 +2811,7 @@ async def admin_edit_resource(
27882811
user: Authenticated user.
27892812
27902813
Returns:
2791-
RedirectResponse: A redirect response to the admin dashboard.
2814+
JSONResponse: A JSON response indicating success or failure of the resource update operation.
27922815
27932816
Examples:
27942817
>>> import asyncio
@@ -2839,18 +2862,28 @@ async def admin_edit_resource(
28392862
"""
28402863
logger.debug(f"User {user} is editing resource URI {uri}")
28412864
form = await request.form()
2842-
resource = ResourceUpdate(
2843-
name=form["name"],
2844-
description=form.get("description"),
2845-
mime_type=form.get("mimeType"),
2846-
content=form["content"],
2847-
)
2848-
await resource_service.update_resource(db, uri, resource)
2849-
root_path = request.scope.get("root_path", "")
2850-
is_inactive_checked = form.get("is_inactive_checked", "false")
2851-
if is_inactive_checked.lower() == "true":
2852-
return RedirectResponse(f"{root_path}/admin/?include_inactive=true#resources", status_code=303)
2853-
return RedirectResponse(f"{root_path}/admin#resources", status_code=303)
2865+
try:
2866+
resource = ResourceUpdate(
2867+
name=form["name"],
2868+
description=form.get("description"),
2869+
mime_type=form.get("mimeType"),
2870+
content=form["content"],
2871+
)
2872+
await resource_service.update_resource(db, uri, resource)
2873+
return JSONResponse(
2874+
content={"message": "Resource updated successfully!", "success": True},
2875+
status_code=200,
2876+
)
2877+
except Exception as ex:
2878+
if isinstance(ex, ValidationError):
2879+
logger.error(f"ValidationError in admin_edit_resource: {ErrorFormatter.format_validation_error(ex)}")
2880+
return JSONResponse(content=ErrorFormatter.format_validation_error(ex), status_code=422)
2881+
if isinstance(ex, IntegrityError):
2882+
error_message = ErrorFormatter.format_database_error(ex)
2883+
logger.error(f"IntegrityError in admin_edit_resource: {error_message}")
2884+
return JSONResponse(status_code=409, content=error_message)
2885+
logger.error(f"Error in admin_edit_resource: {ex}")
2886+
return JSONResponse(content={"message": str(ex), "success": False}, status_code=500)
28542887

28552888

28562889
@admin_router.post("/resources/{uri:path}/delete")
@@ -3211,7 +3244,7 @@ async def admin_edit_prompt(
32113244
request: Request,
32123245
db: Session = Depends(get_db),
32133246
user: str = Depends(require_auth),
3214-
) -> RedirectResponse:
3247+
) -> JSONResponse:
32153248
"""Edit a prompt via the admin UI.
32163249
32173250
Expects form fields:
@@ -3302,13 +3335,13 @@ async def admin_edit_prompt(
33023335
)
33033336
except Exception as ex:
33043337
if isinstance(ex, ValidationError):
3305-
logger.error(f"ValidationError in admin_add_prompt: {ErrorFormatter.format_validation_error(ex)}")
3338+
logger.error(f"ValidationError in admin_edit_prompt: {ErrorFormatter.format_validation_error(ex)}")
33063339
return JSONResponse(content=ErrorFormatter.format_validation_error(ex), status_code=422)
33073340
if isinstance(ex, IntegrityError):
33083341
error_message = ErrorFormatter.format_database_error(ex)
3309-
logger.error(f"IntegrityError in admin_add_prompt: {error_message}")
3342+
logger.error(f"IntegrityError in admin_edit_prompt: {error_message}")
33103343
return JSONResponse(status_code=409, content=error_message)
3311-
logger.error(f"Error in admin_add_prompt: {ex}")
3344+
logger.error(f"Error in admin_edit_prompt: {ex}")
33123345
return JSONResponse(content={"message": str(ex), "success": False}, status_code=500)
33133346

33143347

mcpgateway/services/resource_service.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,7 @@ async def update_resource(self, db: Session, uri: str, resource_update: Resource
498498
Raises:
499499
ResourceNotFoundError: If the resource is not found
500500
ResourceError: For other update errors
501+
IntegrityError: If a database integrity error occurs.
501502
Exception: For unexpected errors
502503
503504
Examples:
@@ -560,7 +561,10 @@ async def update_resource(self, db: Session, uri: str, resource_update: Resource
560561

561562
logger.info(f"Updated resource: {uri}")
562563
return self._convert_resource_to_read(resource)
563-
564+
except IntegrityError as ie:
565+
db.rollback()
566+
logger.error(f"IntegrityErrors in group: {ie}")
567+
raise ie
564568
except Exception as e:
565569
db.rollback()
566570
if isinstance(e, ResourceNotFoundError):

mcpgateway/services/server_service.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,7 @@ async def update_server(self, db: Session, server_id: str, server_update: Server
409409
ServerNotFoundError: If the server is not found.
410410
ServerNameConflictError: If a new name conflicts with an existing server.
411411
ServerError: For other update errors.
412+
IntegrityError: If a database integrity error occurs.
412413
413414
Examples:
414415
>>> from mcpgateway.services.server_service import ServerService
@@ -498,6 +499,10 @@ async def update_server(self, db: Session, server_id: str, server_update: Server
498499
}
499500
logger.debug(f"Server Data: {server_data}")
500501
return self._convert_server_to_read(server)
502+
except IntegrityError as ie:
503+
db.rollback()
504+
logger.error(f"IntegrityErrors in group: {ie}")
505+
raise ie
501506
except Exception as e:
502507
db.rollback()
503508
raise ServerError(f"Failed to update server: {str(e)}")

0 commit comments

Comments
 (0)