[OND211-2329]: Added API to update team settings.
This commit is contained in:
parent
060ec782fc
commit
3870f50ea5
1 changed files with 267 additions and 22 deletions
|
|
@ -61,6 +61,34 @@ def is_team_admin_or_owner(tenant_id: str, user_id: str) -> bool:
|
||||||
return user_tenant.role in [UserTenantRole.OWNER, UserTenantRole.ADMIN]
|
return user_tenant.role in [UserTenantRole.OWNER, UserTenantRole.ADMIN]
|
||||||
|
|
||||||
|
|
||||||
|
def validate_model_id(user_id: str, model_id: Optional[str], model_type: str, context: str = "team") -> Optional[str]:
|
||||||
|
"""
|
||||||
|
Validate that a model ID has been added by the user. Returns error message if invalid, None if valid.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user_id: The user ID to check models for
|
||||||
|
model_id: The model ID to validate (optional)
|
||||||
|
model_type: The type of model (e.g., "LLM", "Embedding", "ASR")
|
||||||
|
context: The context for the error message (e.g., "team", "creating a team", "updating the team")
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Error message string if invalid, None if valid
|
||||||
|
"""
|
||||||
|
if model_id is None:
|
||||||
|
return None # Optional parameter, skip validation if not provided
|
||||||
|
|
||||||
|
# Check if the model exists in TenantLLM for this user
|
||||||
|
model_config = TenantLLMService.get_api_key(user_id, model_id)
|
||||||
|
if not model_config:
|
||||||
|
return f"{model_type} model '{model_id}' has not been added. Please add the model first before {context}."
|
||||||
|
|
||||||
|
# Check if the model is valid (status = "1")
|
||||||
|
if model_config.status != StatusEnum.VALID.value:
|
||||||
|
return f"{model_type} model '{model_id}' is not active. Please enable the model first."
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
@manager.route("/<tenant_id>/user/list", methods=["GET"]) # noqa: F821
|
@manager.route("/<tenant_id>/user/list", methods=["GET"]) # noqa: F821
|
||||||
@login_required
|
@login_required
|
||||||
def user_list(tenant_id):
|
def user_list(tenant_id):
|
||||||
|
|
@ -285,47 +313,30 @@ def create_team() -> Response:
|
||||||
|
|
||||||
# Validate that provided LLM models have been added by the user
|
# Validate that provided LLM models have been added by the user
|
||||||
# Models are stored in TenantLLM with tenant_id = user_id
|
# Models are stored in TenantLLM with tenant_id = user_id
|
||||||
def validate_model_id(user_id: str, model_id: Optional[str], model_type: str) -> Optional[str]:
|
|
||||||
"""Validate that a model ID has been added by the user. Returns error message if invalid, None if valid."""
|
|
||||||
if model_id is None:
|
|
||||||
return None # Optional parameter, skip validation if not provided
|
|
||||||
|
|
||||||
# Check if the model exists in TenantLLM for this user
|
|
||||||
model_config = TenantLLMService.get_api_key(user_id, model_id)
|
|
||||||
if not model_config:
|
|
||||||
return f"{model_type} model '{model_id}' has not been added. Please add the model first before creating a team."
|
|
||||||
|
|
||||||
# Check if the model is valid (status = "1")
|
|
||||||
if model_config.status != StatusEnum.VALID.value:
|
|
||||||
return f"{model_type} model '{model_id}' is not active. Please enable the model first."
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
# Validate all provided model IDs
|
|
||||||
validation_errors = []
|
validation_errors = []
|
||||||
|
|
||||||
if llm_id is not None:
|
if llm_id is not None:
|
||||||
error = validate_model_id(owner_user_id, llm_id, "LLM")
|
error = validate_model_id(owner_user_id, llm_id, "LLM", "creating a team")
|
||||||
if error:
|
if error:
|
||||||
validation_errors.append(error)
|
validation_errors.append(error)
|
||||||
|
|
||||||
if embd_id is not None:
|
if embd_id is not None:
|
||||||
error = validate_model_id(owner_user_id, embd_id, "Embedding")
|
error = validate_model_id(owner_user_id, embd_id, "Embedding", "creating a team")
|
||||||
if error:
|
if error:
|
||||||
validation_errors.append(error)
|
validation_errors.append(error)
|
||||||
|
|
||||||
if asr_id is not None:
|
if asr_id is not None:
|
||||||
error = validate_model_id(owner_user_id, asr_id, "ASR")
|
error = validate_model_id(owner_user_id, asr_id, "ASR", "creating a team")
|
||||||
if error:
|
if error:
|
||||||
validation_errors.append(error)
|
validation_errors.append(error)
|
||||||
|
|
||||||
if img2txt_id is not None:
|
if img2txt_id is not None:
|
||||||
error = validate_model_id(owner_user_id, img2txt_id, "Image-to-text")
|
error = validate_model_id(owner_user_id, img2txt_id, "Image-to-text", "creating a team")
|
||||||
if error:
|
if error:
|
||||||
validation_errors.append(error)
|
validation_errors.append(error)
|
||||||
|
|
||||||
if rerank_id is not None:
|
if rerank_id is not None:
|
||||||
error = validate_model_id(owner_user_id, rerank_id, "Rerank")
|
error = validate_model_id(owner_user_id, rerank_id, "Rerank", "creating a team")
|
||||||
if error:
|
if error:
|
||||||
validation_errors.append(error)
|
validation_errors.append(error)
|
||||||
|
|
||||||
|
|
@ -443,6 +454,240 @@ def tenant_list():
|
||||||
return server_error_response(e)
|
return server_error_response(e)
|
||||||
|
|
||||||
|
|
||||||
|
@manager.route("/<tenant_id>", methods=["PUT"]) # noqa: F821
|
||||||
|
@login_required
|
||||||
|
def update_team(tenant_id: str) -> Response:
|
||||||
|
"""
|
||||||
|
Update team details. Only OWNER or ADMIN can update team information.
|
||||||
|
|
||||||
|
---
|
||||||
|
tags:
|
||||||
|
- Team
|
||||||
|
security:
|
||||||
|
- ApiKeyAuth: []
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: tenant_id
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
description: Team ID
|
||||||
|
- in: body
|
||||||
|
name: body
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: Team name (optional, max 100 characters).
|
||||||
|
llm_id:
|
||||||
|
type: string
|
||||||
|
description: LLM model ID (optional, must be added by the user).
|
||||||
|
embd_id:
|
||||||
|
type: string
|
||||||
|
description: Embedding model ID (optional, must be added by the user).
|
||||||
|
asr_id:
|
||||||
|
type: string
|
||||||
|
description: ASR model ID (optional, must be added by the user).
|
||||||
|
img2txt_id:
|
||||||
|
type: string
|
||||||
|
description: Image-to-text model ID (optional, must be added by the user).
|
||||||
|
rerank_id:
|
||||||
|
type: string
|
||||||
|
description: Rerank model ID (optional, must be added by the user).
|
||||||
|
tts_id:
|
||||||
|
type: string
|
||||||
|
description: TTS model ID (optional, must be added by the user).
|
||||||
|
parser_ids:
|
||||||
|
type: string
|
||||||
|
description: Document parser IDs (optional).
|
||||||
|
credit:
|
||||||
|
type: integer
|
||||||
|
description: Credit amount (optional).
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: Team updated successfully.
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
data:
|
||||||
|
type: object
|
||||||
|
description: Updated team information.
|
||||||
|
message:
|
||||||
|
type: string
|
||||||
|
description: Success message.
|
||||||
|
400:
|
||||||
|
description: Invalid request.
|
||||||
|
401:
|
||||||
|
description: Unauthorized.
|
||||||
|
403:
|
||||||
|
description: Forbidden - not owner or admin.
|
||||||
|
404:
|
||||||
|
description: Team not found.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# Check if current user is OWNER or ADMIN of the team
|
||||||
|
if not is_team_admin_or_owner(tenant_id, current_user.id):
|
||||||
|
return get_json_result(
|
||||||
|
data=False,
|
||||||
|
message='Only team owners or admins can update team details.',
|
||||||
|
code=RetCode.PERMISSION_ERROR
|
||||||
|
)
|
||||||
|
|
||||||
|
# Verify tenant exists
|
||||||
|
success, tenant = TenantService.get_by_id(tenant_id)
|
||||||
|
if not success or not tenant:
|
||||||
|
return get_json_result(
|
||||||
|
data=False,
|
||||||
|
message=f"Team with ID '{tenant_id}' not found.",
|
||||||
|
code=RetCode.DATA_ERROR
|
||||||
|
)
|
||||||
|
|
||||||
|
if request.json is None:
|
||||||
|
return get_json_result(
|
||||||
|
data=False,
|
||||||
|
message="Request body is required!",
|
||||||
|
code=RetCode.ARGUMENT_ERROR,
|
||||||
|
)
|
||||||
|
|
||||||
|
req: Dict[str, Any] = request.json
|
||||||
|
|
||||||
|
# Extract update fields (all optional)
|
||||||
|
update_data: Dict[str, Any] = {}
|
||||||
|
|
||||||
|
# Update team name if provided
|
||||||
|
if "name" in req:
|
||||||
|
team_name: str = req.get("name", "").strip()
|
||||||
|
if team_name:
|
||||||
|
if len(team_name) > 100:
|
||||||
|
return get_json_result(
|
||||||
|
data=False,
|
||||||
|
message="Team name must be 100 characters or less!",
|
||||||
|
code=RetCode.ARGUMENT_ERROR,
|
||||||
|
)
|
||||||
|
update_data["name"] = team_name
|
||||||
|
else:
|
||||||
|
return get_json_result(
|
||||||
|
data=False,
|
||||||
|
message="Team name cannot be empty!",
|
||||||
|
code=RetCode.ARGUMENT_ERROR,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Validate model IDs if provided (reuse validate_model_id function)
|
||||||
|
validation_errors: List[str] = []
|
||||||
|
|
||||||
|
llm_id: Optional[str] = req.get("llm_id")
|
||||||
|
if llm_id is not None:
|
||||||
|
error = validate_model_id(current_user.id, llm_id, "LLM", "updating the team")
|
||||||
|
if error:
|
||||||
|
validation_errors.append(error)
|
||||||
|
else:
|
||||||
|
update_data["llm_id"] = llm_id
|
||||||
|
|
||||||
|
embd_id: Optional[str] = req.get("embd_id")
|
||||||
|
if embd_id is not None:
|
||||||
|
error = validate_model_id(current_user.id, embd_id, "Embedding", "updating the team")
|
||||||
|
if error:
|
||||||
|
validation_errors.append(error)
|
||||||
|
else:
|
||||||
|
update_data["embd_id"] = embd_id
|
||||||
|
|
||||||
|
asr_id: Optional[str] = req.get("asr_id")
|
||||||
|
if asr_id is not None:
|
||||||
|
error = validate_model_id(current_user.id, asr_id, "ASR", "updating the team")
|
||||||
|
if error:
|
||||||
|
validation_errors.append(error)
|
||||||
|
else:
|
||||||
|
update_data["asr_id"] = asr_id
|
||||||
|
|
||||||
|
img2txt_id: Optional[str] = req.get("img2txt_id")
|
||||||
|
if img2txt_id is not None:
|
||||||
|
error = validate_model_id(current_user.id, img2txt_id, "Image-to-text", "updating the team")
|
||||||
|
if error:
|
||||||
|
validation_errors.append(error)
|
||||||
|
else:
|
||||||
|
update_data["img2txt_id"] = img2txt_id
|
||||||
|
|
||||||
|
rerank_id: Optional[str] = req.get("rerank_id")
|
||||||
|
if rerank_id is not None:
|
||||||
|
error = validate_model_id(current_user.id, rerank_id, "Rerank", "updating the team")
|
||||||
|
if error:
|
||||||
|
validation_errors.append(error)
|
||||||
|
else:
|
||||||
|
update_data["rerank_id"] = rerank_id
|
||||||
|
|
||||||
|
tts_id: Optional[str] = req.get("tts_id")
|
||||||
|
if tts_id is not None:
|
||||||
|
error = validate_model_id(current_user.id, tts_id, "TTS", "updating the team")
|
||||||
|
if error:
|
||||||
|
validation_errors.append(error)
|
||||||
|
else:
|
||||||
|
update_data["tts_id"] = tts_id
|
||||||
|
|
||||||
|
parser_ids: Optional[str] = req.get("parser_ids")
|
||||||
|
if parser_ids is not None:
|
||||||
|
update_data["parser_ids"] = parser_ids
|
||||||
|
|
||||||
|
credit: Optional[int] = req.get("credit")
|
||||||
|
if credit is not None:
|
||||||
|
if not isinstance(credit, int) or credit < 0:
|
||||||
|
return get_json_result(
|
||||||
|
data=False,
|
||||||
|
message="Credit must be a non-negative integer!",
|
||||||
|
code=RetCode.ARGUMENT_ERROR,
|
||||||
|
)
|
||||||
|
update_data["credit"] = credit
|
||||||
|
|
||||||
|
if validation_errors:
|
||||||
|
return get_json_result(
|
||||||
|
data=False,
|
||||||
|
message="; ".join(validation_errors),
|
||||||
|
code=RetCode.DATA_ERROR,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check if there's anything to update
|
||||||
|
if not update_data:
|
||||||
|
return get_json_result(
|
||||||
|
data=False,
|
||||||
|
message="No fields provided to update.",
|
||||||
|
code=RetCode.ARGUMENT_ERROR,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Update the tenant
|
||||||
|
TenantService.update_by_id(tenant_id, update_data)
|
||||||
|
|
||||||
|
# Get updated tenant info
|
||||||
|
success, updated_tenant = TenantService.get_by_id(tenant_id)
|
||||||
|
if not success or not updated_tenant:
|
||||||
|
return get_json_result(
|
||||||
|
data=False,
|
||||||
|
message="Failed to retrieve updated team information.",
|
||||||
|
code=RetCode.EXCEPTION_ERROR,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Return updated team info
|
||||||
|
team_data: Dict[str, Any] = {
|
||||||
|
"id": updated_tenant.id,
|
||||||
|
"name": updated_tenant.name,
|
||||||
|
"llm_id": updated_tenant.llm_id,
|
||||||
|
"embd_id": updated_tenant.embd_id,
|
||||||
|
"asr_id": updated_tenant.asr_id,
|
||||||
|
"img2txt_id": updated_tenant.img2txt_id,
|
||||||
|
"rerank_id": updated_tenant.rerank_id,
|
||||||
|
"tts_id": updated_tenant.tts_id,
|
||||||
|
"parser_ids": updated_tenant.parser_ids,
|
||||||
|
"credit": updated_tenant.credit,
|
||||||
|
}
|
||||||
|
|
||||||
|
return get_json_result(
|
||||||
|
data=team_data,
|
||||||
|
message="Team updated successfully!",
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logging.exception(e)
|
||||||
|
return server_error_response(e)
|
||||||
|
|
||||||
|
|
||||||
@manager.route("/update-request/<tenant_id>", methods=["PUT"]) # noqa: F821
|
@manager.route("/update-request/<tenant_id>", methods=["PUT"]) # noqa: F821
|
||||||
@login_required
|
@login_required
|
||||||
def update_request(tenant_id: str) -> Response:
|
def update_request(tenant_id: str) -> Response:
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue