# # Copyright 2024 The InfiniFlow Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import logging from api.apps import current_user, login_required from api.db.services.chat_channel_service import ChatChannelService from api.db.services.dialog_service import DialogService from api.utils.api_utils import get_data_error_result, get_json_result, get_request_json, validate_request from common.constants import RetCode from common.misc_utils import get_uuid LOGGER = logging.getLogger(__name__) def _chat_channel_auth_error(channel_id: str, user_id: str): """Return the chat channel authorization failure response and log the denial.""" LOGGER.warning("chat channel access denied: channel_id=%s user_id=%s", channel_id, user_id) return get_json_result(data=False, message="No authorization.", code=RetCode.AUTHENTICATION_ERROR) @manager.route("/chat_channels", methods=["POST"]) # noqa: F821 @login_required @validate_request("name", "channel", "config") async def create_chat_channel(): """Create a chat channel bot owned by the current tenant.""" req = await get_request_json() channel = { "id": get_uuid(), "tenant_id": current_user.id, "name": req["name"], "channel": req["channel"], "config": req["config"], "dialog_id": req.get("dialog_id") or None, "status": "1", } ChatChannelService.insert(**channel) e, conn = ChatChannelService.get_by_id(channel["id"]) if not e: return get_data_error_result(message="Failed to create chat channel!") return get_json_result(data=conn.to_dict()) @manager.route("/chat_channels", methods=["GET"]) # noqa: F821 @login_required def list_chat_channel(): """List chat channel bots owned by the current tenant.""" return get_json_result(data=ChatChannelService.list(current_user.id)) @manager.route("/chat_channels/", methods=["GET"]) # noqa: F821 @login_required def get_chat_channel(channel_id): """Return a chat channel bot's details when the current user can access it.""" if not ChatChannelService.accessible(channel_id, current_user.id): return _chat_channel_auth_error(channel_id, current_user.id) e, conn = ChatChannelService.get_by_id(channel_id) if not e: return get_data_error_result(message="Can't find this chat channel!") return get_json_result(data=conn.to_dict()) @manager.route("/chat_channels/", methods=["PATCH"]) # noqa: F821 @login_required async def update_chat_channel(channel_id): """Update an accessible chat channel bot's name/config/status.""" if not ChatChannelService.accessible(channel_id, current_user.id): return _chat_channel_auth_error(channel_id, current_user.id) e, conn = ChatChannelService.get_by_id(channel_id) if not e: return get_data_error_result(message="Can't find this chat channel!") req = await get_request_json() if isinstance(req, dict) and isinstance(req.get("data"), dict): req = req["data"] # Validate the connected dialog (if provided) belongs to the channel's tenant. if req.get("dialog_id"): e, dia = DialogService.get_by_id(req["dialog_id"]) if not e: return get_data_error_result(message="Can't find this chat assistant!") if dia.tenant_id != conn.tenant_id: return _chat_channel_auth_error(channel_id, current_user.id) update_fields = {fld: req[fld] for fld in ["name", "config", "dialog_id", "status"] if fld in req} if update_fields: ChatChannelService.update_by_id(channel_id, update_fields) e, conn = ChatChannelService.get_by_id(channel_id) if not e: return get_data_error_result(message="Can't find this chat channel!") return get_json_result(data=conn.to_dict()) @manager.route("/chat_channels/", methods=["DELETE"]) # noqa: F821 @login_required def rm_chat_channel(channel_id): """Delete an accessible chat channel bot.""" if not ChatChannelService.accessible(channel_id, current_user.id): return _chat_channel_auth_error(channel_id, current_user.id) ChatChannelService.delete_by_id(channel_id) return get_json_result(data=True)