async def startup(): """ MongoDB is connected on the bot trainer startup """ config: dict = Utility.mongoengine_connection( Utility.environment['database']["url"]) connect(**config) await AccountProcessor.default_account_setup() AccountProcessor.load_system_properties()
async def get_current_user_and_bot(security_scopes: SecurityScopes, request: Request, token: str = Depends(DataUtility.oauth2_scheme)): if security_scopes.scopes: authenticate_value = f'Bearer scope="{security_scopes.scope_str}"' else: authenticate_value = "Bearer" user = await Authentication.get_current_user(request, token) bot_id = request.path_params.get('bot') if Utility.check_empty_string(bot_id): raise HTTPException( status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail='Bot is required', ) if user.is_integration_user: user_role = user.role else: user_role = AccountProcessor.fetch_role_for_user(user.email, bot_id) user_role = user_role['role'] if security_scopes.scopes and user_role not in security_scopes.scopes: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail=f"{security_scopes.scopes} access is required to perform this operation on the bot", headers={"WWW-Authenticate": authenticate_value}, ) AccountProcessor.get_bot_and_validate_status(bot_id) user.active_bot = bot_id return user
async def delete_account(current_user: User = Depends( Authentication.get_current_user)): """ Deletes user account. """ AccountProcessor.delete_account(current_user.account) return {"message": "Account deleted"}
async def verify_and_process(request, sso_type: str): """ Fetches user details and returns a login token. If user does not have an account, it will be created. :param request: starlette request object :param sso_type: one of supported types - google/facebook/linkedin. """ sso_client = LoginSSOFactory.get_client(sso_type) user_details = await sso_client.verify(request) try: AccountProcessor.get_user(user_details['email']) existing_user = True except DoesNotExist: existing_user = False user_details['password'] = SecretStr(Utility.generate_password()) user_details['account'] = user_details['email'] if existing_user: AccountProcessor.get_user_details(user_details['email']) else: await AccountProcessor.account_setup(user_details) tmp_token = Utility.generate_token(user_details['email']) await AccountProcessor.confirm_email(tmp_token) access_token = Authentication.create_access_token(data={"sub": user_details["email"]}) return existing_user, user_details, access_token
async def add_bot(request: TextData, current_user: User = Depends( Authentication.get_current_user)): """ Add new bot in a account. """ AccountProcessor.add_bot(request.data, current_user.account, current_user.get_user()) return {'message': 'Bot created'}
async def delete_bot(bot: str, current_user: User = Security( Authentication.get_current_user_and_bot, scopes=OWNER_ACCESS)): """ Deletes bot. """ AccountProcessor.delete_bot(bot) return {'message': 'Bot removed'}
async def feedback(request_data: FeedbackRequest, current_user: User = Depends( Authentication.get_current_user)): """ Receive feedback from user. """ AccountProcessor.add_feedback(request_data.rating, current_user.get_user(), request_data.scale, request_data.feedback) return {"message": "Thanks for your feedback!"}
async def update_ui_config(request_data: DictData, current_user: User = Depends( Authentication.get_current_user)): """ Add/update ui configuration for user. """ AccountProcessor.update_ui_config(request_data.data, current_user.get_user()) return {"message": "Config saved!"}
async def update_bot(bot: str, request: TextData, current_user: User = Security( Authentication.get_current_user_and_bot, scopes=OWNER_ACCESS)): """ Update name of the bot. """ AccountProcessor.update_bot(request.data, bot) return {'message': 'Name updated'}
async def remove_member_from_bot( user: str = Path(default=None, description="user mail id", example="*****@*****.**"), bot: str = Path(default=None, description="bot id", example="613f63e87a1d435607c3c183"), current_user: User = Security(Authentication.get_current_user_and_bot, scopes=ADMIN_ACCESS)): """ Removes user from accessing the bot. """ AccountProcessor.remove_member(bot, accessor_email=user) return Response(message='User removed')
async def update_bot_access_for_user( allow_bot: BotAccessRequest, bot: str = Path(default=None, description="bot id", example="613f63e87a1d435607c3c183"), current_user: User = Security(Authentication.get_current_user_and_bot, scopes=ADMIN_ACCESS)): """ Updates user's role or status. """ AccountProcessor.update_bot_access(bot, allow_bot.email, current_user.get_user(), allow_bot.role, allow_bot.activity_status) return Response(message='User access updated')
async def transfer_ownership( request_data: TextData, bot: str = Path(default=None, description="bot id", example="613f63e87a1d435607c3c183"), current_user: User = Security(Authentication.get_current_user_and_bot, scopes=OWNER_ACCESS)): """ Transfers ownership to provided user. """ AccountProcessor.transfer_ownership(current_user.account, bot, current_user.get_user(), request_data.data) return Response(message='Ownership transferred')
def get_current_user_and_bot_for_channel(token: Text, bot: Text, request: HTTPServerRequest): user = TornadoAuthenticate.get_user_from_token(token, request) if Utility.check_empty_string(bot): raise ServiceHandlerException("Bot is required", 422, {"WWW-Authenticate": "Bearer"}) AccountProcessor.fetch_role_for_user(user.email, bot) bot = AccountProcessor.get_bot(bot) if not bot["status"]: raise ServiceHandlerException( "Inactive Bot Please contact system admin!", 422, {"WWW-Authenticate": "Bearer"}) user.active_bot = bot return user
def get_current_user_and_bot(request: HTTPServerRequest, **kwargs): user = TornadoAuthenticate.get_current_user(request, **kwargs) bot_id = kwargs.get('bot') if Utility.check_empty_string(bot_id): raise ServiceHandlerException("Bot is required", 422, {"WWW-Authenticate": "Bearer"}) if not user.is_integration_user: AccountProcessor.fetch_role_for_user(user.email, bot_id) bot = AccountProcessor.get_bot(bot_id) if not bot["status"]: raise ServiceHandlerException( "Inactive Bot Please contact system admin!", 422, {"WWW-Authenticate": "Bearer"}) user.active_bot = bot_id return user
async def allow_bot_for_user( allow_bot: BotAccessRequest, background_tasks: BackgroundTasks, bot: str = Path(default=None, description="bot id", example="613f63e87a1d435607c3c183"), current_user: User = Security(Authentication.get_current_user_and_bot, scopes=ADMIN_ACCESS)): """ Allows user to access a bot. """ bot_name, url = AccountProcessor.allow_bot_and_generate_invite_url( bot, allow_bot.email, current_user.get_user(), current_user.account, allow_bot.role) if Utility.email_conf["email"]["enable"]: background_tasks.add_task( Utility.format_and_send_mail, mail_type='add_member', email=allow_bot.email, url=url, first_name=f'{current_user.first_name} {current_user.last_name}', bot_name=bot_name, role=allow_bot.role) return Response(message='An invitation has been sent to the user') else: return {"message": "User added"}
def __authenticate_user(username: str, password: str): user = AccountProcessor.get_user_details(username) if not user: return False if not Utility.verify_password(password, user["password"]): return False return user
async def get_users_details(current_user: User = Depends( Authentication.get_current_user)): """ returns the details of the current logged-in user """ user_details = AccountProcessor.get_user_details_and_filter_bot_info_for_integration_user( current_user.email, current_user.is_integration_user, current_user.get_bot()) return {"data": {"user": user_details}}
async def list_users_for_bot( bot: str = Path(default=None, description="bot id", example="613f63e87a1d435607c3c183"), current_user: User = Security(Authentication.get_current_user_and_bot, scopes=TESTER_ACCESS)): """ Lists active/inactive/invited users of a bot. """ return Response(data=list(AccountProcessor.list_bot_accessors(bot)))
async def list_active_bot_invites(current_user: User = Security( Authentication.get_current_user)): """ Lists active bot invites. """ return Response( data={ 'active_invites': list(AccountProcessor.list_active_invites(current_user.get_user())) })
async def search_user(request_data: TextData, current_user: User = Security( Authentication.get_current_user)): """ Lists active bot invites. """ return Response(data={ 'matching_users': list(AccountProcessor.search_user(request_data.data)) })
async def list_bots(current_user: User = Depends( Authentication.get_current_user)): """ List bots for account. """ bots = AccountProcessor.get_accessible_bot_details(current_user.account, current_user.email) if current_user.is_integration_user: bots = Utility.filter_bot_details_for_integration_user( current_user.get_bot(), bots) return Response(data=bots)
async def get_current_user( request: Request, token: str = Depends(DataUtility.oauth2_scheme) ): """ validates jwt token :param token: jwt token, default extracted by fastapi :param request: http request object :return: dict of user details """ credentials_exception = HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Could not validate credentials", headers={"WWW-Authenticate": "Bearer"}, ) try: payload = Utility.decode_limited_access_token(token) username: str = payload.get("sub") Authentication.validate_limited_access_token(request, payload.get("access-limit")) if username is None: raise credentials_exception token_data = TokenData(username=username) user = AccountProcessor.get_user_details(token_data.username) if user is None: raise credentials_exception user_model = User(**user) if payload.get("type") != TOKEN_TYPE.LOGIN.value: Authentication.validate_bot_request(request.path_params.get('bot'), payload.get('bot')) if payload.get("type") == TOKEN_TYPE.INTEGRATION.value: Authentication.validate_integration_token(payload) alias_user = request.headers.get("X-USER") if Utility.check_empty_string(alias_user) and payload.get("type") == TOKEN_TYPE.INTEGRATION.value: raise HTTPException( status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="Alias user missing for integration", headers={"WWW-Authenticate": "Bearer"}, ) user_model.active_bot = payload.get('bot') user_model.is_integration_user = True user_model.alias_user = alias_user or username user_model.role = payload.get('role') return user_model except PyJWTError: raise credentials_exception
async def accept_bot_collaboration_invite( background_tasks: BackgroundTasks, token: TextData, bot: str = Path(default=None, description="bot id", example="613f63e87a1d435607c3c183")): """ Accepts a bot collaboration invitation. """ bot_admin, bot_name, accessor_email, role = AccountProcessor.accept_bot_access_invite( token.data, bot) if Utility.email_conf["email"]["enable"]: background_tasks.add_task(Utility.format_and_send_mail, mail_type='add_member_confirmation', email=bot_admin, first_name=bot_admin, accessor_email=accessor_email, bot_name=bot_name, role=role) return {"message": "Invitation accepted"}
def get_user_from_token(token: Text, request: HTTPServerRequest, **kwargs): """ validates jwt token :param token: jwt token :param request: http request object :return: dict of user details """ credentials_exception = ServiceHandlerException( "Could not validate credentials", 401, {"WWW-Authenticate": "Bearer"}) try: payload = Utility.decode_limited_access_token(token) username: str = payload.get("sub") TornadoAuthenticate.validate_limited_access_token( request, payload.get("access-limit")) if username is None: raise credentials_exception except PyJWTError: raise credentials_exception user = AccountProcessor.get_user_details(username) if user is None: raise credentials_exception user_model = User(**user) if payload.get("type") != TOKEN_TYPE.LOGIN.value: TornadoAuthenticate.validate_bot_request(kwargs.get('bot'), payload.get('bot')) if payload.get("type") == TOKEN_TYPE.INTEGRATION.value: TornadoAuthenticate.validate_integration_token(payload) alias_user = request.headers.get("X-USER") if Utility.check_empty_string(alias_user) and payload.get( "type") == TOKEN_TYPE.INTEGRATION.value: raise ServiceHandlerException( "Alias user missing for integration", 401) alias_user = alias_user or username user_model.alias_user = alias_user user_model.is_integration_user = True user_model.role = payload.get('role') return user_model
async def download_conversations( month: int = Query(default=1, ge=1, le=6), current_user: User = Security(Authentication.get_current_user_and_bot, scopes=TESTER_ACCESS), ): """ Downloads conversation history of the bot, for the specified months """ response = Utility.trigger_history_server_request( current_user.get_bot(), f'/api/history/{current_user.get_bot()}/conversations/download', {'month': month}, return_json=False) bot_name = [ bot['name'] for bot in AccountProcessor.list_bots(current_user.account) if bot['_id'] == current_user.get_bot() ][0] response.headers[ "Content-Disposition"] = f"attachment; filename=conversation_history_{bot_name}{datetime.date.today().strftime('_%d_%m_%y.csv')}" return StreamingResponse(BytesIO(response.content), headers=response.headers)
async def get_ui_config(current_user: User = Depends( Authentication.get_current_user)): """ Get ui configuration for user. """ return {'data': AccountProcessor.get_ui_config(current_user.get_user())}
from kairon.shared.utils import Utility from kairon.train import start_training import responses os.environ["system_file"] = "./tests/testing_data/system.yaml" os.environ['ASYNC_TEST_TIMEOUT'] = "3600" Utility.load_environment() connect(**Utility.mongoengine_connection()) loop = asyncio.new_event_loop() loop.run_until_complete( AccountProcessor.account_setup( RegisterAccount( **{ "email": "*****@*****.**", "first_name": "Test", "last_name": "Chat", "password": "******", "confirm_password": "******", "account": "ChatTesting" }).dict())) token = Authentication.authenticate("*****@*****.**", "testChat@12") token_type = "Bearer" user = AccountProcessor.get_complete_user_details("*****@*****.**") bot = user['bots']['account_owned'][0]['_id'] start_training(bot, "*****@*****.**") bot2 = AccountProcessor.add_bot("testChat2", user['account'], "*****@*****.**")['_id'].__str__() loop.run_until_complete(MongoProcessor().save_from_path( "template/use-cases/Hi-Hello", bot2, user="******")) start_training(bot2, "*****@*****.**")