From 1b7abb22dc2b831522973cdc1e29c20a5ff0ac22 Mon Sep 17 00:00:00 2001 From: Hitesh Ghuge <41512916+hiteshghuge@users.noreply.github.com> Date: Tue, 17 Sep 2024 10:34:07 +0530 Subject: [PATCH] - Auditlog delete case (#1398) * - Auditlog delete case * - Auditlog delete case * - test cases fix for auditlog --------- Co-authored-by: hghuge --- kairon/api/app/routers/account.py | 6 +- kairon/api/app/routers/bot/action.py | 2 +- kairon/api/app/routers/bot/agents.py | 2 +- kairon/api/app/routers/bot/bot.py | 14 +- kairon/api/app/routers/bot/channels.py | 2 +- kairon/api/app/routers/bot/custom_widgets.py | 2 +- kairon/api/app/routers/bot/data.py | 4 +- kairon/api/app/routers/bot/secrets.py | 2 +- kairon/api/app/routers/idp.py | 2 +- kairon/idp/processor.py | 5 +- kairon/shared/account/processor.py | 8 +- kairon/shared/cognition/processor.py | 8 +- kairon/shared/custom_widgets/processor.py | 4 +- kairon/shared/data/processor.py | 138 ++++++++++-------- kairon/shared/live_agent/live_agent.py | 2 +- kairon/shared/live_agent/processor.py | 4 +- kairon/shared/organization/processor.py | 6 +- kairon/shared/utils.py | 16 +- tests/unit_test/api/api_processor_test.py | 2 +- .../custom_widgets_processor_test.py | 4 +- .../data_processor/data_processor_test.py | 99 ++++++------- tests/unit_test/idp/test_idp_helper.py | 2 +- .../live_agent/live_agent_processor_test.py | 2 +- 23 files changed, 187 insertions(+), 149 deletions(-) diff --git a/kairon/api/app/routers/account.py b/kairon/api/app/routers/account.py index 388aebadf..90ff10224 100644 --- a/kairon/api/app/routers/account.py +++ b/kairon/api/app/routers/account.py @@ -174,7 +174,7 @@ async def delete_bot( """ Deletes bot. """ - AccountProcessor.delete_bot(bot) + AccountProcessor.delete_bot(bot, current_user.get_user()) return {'message': 'Bot removed'} @@ -209,7 +209,7 @@ async def delete_account(current_user: User = Depends(Authentication.get_current """ Deletes user account. """ - AccountProcessor.delete_account(current_user.account) + AccountProcessor.delete_account(current_user.account, current_user.get_user()) return {"message": "Account deleted"} @@ -238,5 +238,5 @@ async def delete_organization(org_id: str, current_user: User = Depends(Authenti """ Delete organization. """ - OrgProcessor.delete_org(current_user.account, org_id) + OrgProcessor.delete_org(current_user.account, org_id, user=current_user.get_user()) return Response(message="Organization deleted") diff --git a/kairon/api/app/routers/bot/action.py b/kairon/api/app/routers/bot/action.py index 5a2edaf68..c979c572f 100644 --- a/kairon/api/app/routers/bot/action.py +++ b/kairon/api/app/routers/bot/action.py @@ -601,7 +601,7 @@ async def update_live_agent( async def disable_live_agent( current_user: User = Security(Authentication.get_current_user_and_bot, scopes=DESIGNER_ACCESS) ): - mongo_processor.disable_live_agent(current_user.get_bot()) + mongo_processor.disable_live_agent(current_user.get_bot(), current_user.get_user()) return Response(message="Live Agent Action disabled!") diff --git a/kairon/api/app/routers/bot/agents.py b/kairon/api/app/routers/bot/agents.py index 33830d40e..5c1334575 100644 --- a/kairon/api/app/routers/bot/agents.py +++ b/kairon/api/app/routers/bot/agents.py @@ -55,5 +55,5 @@ async def delete_live_agent_config( """ Deletes the live agent config. """ - LiveAgentsProcessor.delete_config(current_user.get_bot()) + LiveAgentsProcessor.delete_config(current_user.get_bot(), user=current_user.get_user()) return Response(message='Live agent system deleted') diff --git a/kairon/api/app/routers/bot/bot.py b/kairon/api/app/routers/bot/bot.py index 8f6434ef1..de908796c 100644 --- a/kairon/api/app/routers/bot/bot.py +++ b/kairon/api/app/routers/bot/bot.py @@ -328,7 +328,7 @@ async def remove_response( Deletes existing utterance example. """ mongo_processor.delete_response( - response_id, current_user.get_bot() + response_id, current_user.get_bot(), user=current_user.get_user() ) return { "message": "Response removed!", @@ -344,7 +344,7 @@ async def remove_responses( Deletes existing utterance completely along with its examples. """ mongo_processor.delete_utterance( - utterance, current_user.get_bot() + utterance, current_user.get_bot(), user=current_user.get_user() ) return { "message": "Utterance removed!", @@ -1130,7 +1130,7 @@ async def delete_synonym_value( Deletes existing synonym with value. """ mongo_processor.delete_synonym( - id=id, bot=current_user.get_bot() + id=id, bot=current_user.get_bot(), user=current_user.get_user() ) return { "message": "Synonym removed!" @@ -1147,7 +1147,7 @@ async def delete_synonym_value( Deletes existing synonym value. """ mongo_processor.delete_synonym_value( - synonym_name=name, value_id=id, bot=current_user.get_bot() + synonym_name=name, value_id=id, bot=current_user.get_bot(), user=current_user.get_user() ) return { "message": "Synonym value removed!" @@ -1388,7 +1388,7 @@ async def delete_lookup_value( Deletes existing lookup value. """ mongo_processor.delete_lookup_value( - id, name, current_user.get_bot() + id, name, current_user.get_bot(), user=current_user.get_user() ) return { "message": "Lookup value removed!" @@ -1404,7 +1404,7 @@ async def delete_lookup( Deletes existing lookup. """ mongo_processor.delete_lookup( - id, current_user.get_bot() + id, current_user.get_bot(), user=current_user.get_user() ) return { "message": "Lookup removed!" @@ -1453,7 +1453,7 @@ async def delete_slot_mapping(mapping_id: str = Path(description="Slot Mapping i """ Deletes a slot mapping. """ - mongo_processor.delete_single_slot_mapping(mapping_id) + mongo_processor.delete_single_slot_mapping(mapping_id, user=current_user.get_user()) return Response(message='Slot mapping deleted') diff --git a/kairon/api/app/routers/bot/channels.py b/kairon/api/app/routers/bot/channels.py index 169a76abc..abf708d9e 100644 --- a/kairon/api/app/routers/bot/channels.py +++ b/kairon/api/app/routers/bot/channels.py @@ -73,7 +73,7 @@ async def delete_channel_config( """ Deletes the channel config. """ - ChatDataProcessor.delete_channel_config(current_user.get_bot(), id=channel_id) + ChatDataProcessor.delete_channel_config(current_user.get_bot(), user=current_user.get_user(), id=channel_id) return Response(message='Channel deleted') diff --git a/kairon/api/app/routers/bot/custom_widgets.py b/kairon/api/app/routers/bot/custom_widgets.py index 21a01687a..af74c0994 100644 --- a/kairon/api/app/routers/bot/custom_widgets.py +++ b/kairon/api/app/routers/bot/custom_widgets.py @@ -70,7 +70,7 @@ async def delete_custom_widget( """ Delete a particular custom widget. """ - CustomWidgetsProcessor.delete_config(widget_id, current_user.get_bot()) + CustomWidgetsProcessor.delete_config(widget_id, current_user.get_bot(), user=current_user.get_user()) return Response(message='Widget config removed!') diff --git a/kairon/api/app/routers/bot/data.py b/kairon/api/app/routers/bot/data.py index a546f46f9..528410a55 100644 --- a/kairon/api/app/routers/bot/data.py +++ b/kairon/api/app/routers/bot/data.py @@ -81,7 +81,7 @@ async def delete_cognition_schema( """ Deletes cognition content of the bot """ - cognition_processor.delete_cognition_schema(schema_id, current_user.get_bot()) + cognition_processor.delete_cognition_schema(schema_id, current_user.get_bot(), user=current_user.get_user()) return { "message": "Schema deleted!" } @@ -147,7 +147,7 @@ async def delete_cognition_data( """ Deletes cognition content of the bot """ - cognition_processor.delete_cognition_data(row_id, current_user.get_bot()) + cognition_processor.delete_cognition_data(row_id, current_user.get_bot(), user=current_user.get_user()) return { "message": "Record deleted!" } diff --git a/kairon/api/app/routers/bot/secrets.py b/kairon/api/app/routers/bot/secrets.py index e9da62518..c31efa5b7 100644 --- a/kairon/api/app/routers/bot/secrets.py +++ b/kairon/api/app/routers/bot/secrets.py @@ -64,5 +64,5 @@ async def delete_key_value( """ Deletes key value. """ - mongo_processor.delete_secret(key, current_user.get_bot()) + mongo_processor.delete_secret(key, current_user.get_bot(), user=current_user.get_user()) return Response(data=None, message="Secret deleted!") diff --git a/kairon/api/app/routers/idp.py b/kairon/api/app/routers/idp.py index 0cd254ef5..4cea05cf6 100644 --- a/kairon/api/app/routers/idp.py +++ b/kairon/api/app/routers/idp.py @@ -44,6 +44,6 @@ async def delete_idp_config(current_user: User = Depends(Authentication.get_curr """ Disable the idp config """ - IDPProcessor.delete_idp(realm_name) + IDPProcessor.delete_idp(realm_name, user=current_user.get_user()) return Response(message="IDP config deleted") diff --git a/kairon/idp/processor.py b/kairon/idp/processor.py index cef36d752..d6915e2a9 100644 --- a/kairon/idp/processor.py +++ b/kairon/idp/processor.py @@ -151,11 +151,12 @@ def get_supported_provider_list(): return KEYCLOAK_SUPPORTED_PROVIDER @staticmethod - def delete_idp(realm_name): + def delete_idp(realm_name, user: str = None): try: helper = IDPFactory.get_supported_idp(Utility.environment["idp"]["type"]) helper.delete_realm(realm_name) idp_config_data = IdpConfig.objects(realm_name=realm_name, status=True).get() - idp_config_data.delete() + Utility.delete_documents(idp_config_data, user) + except DoesNotExist: raise AppException("IDP config not found") diff --git a/kairon/shared/account/processor.py b/kairon/shared/account/processor.py index 298b3db22..8a827301e 100644 --- a/kairon/shared/account/processor.py +++ b/kairon/shared/account/processor.py @@ -231,7 +231,7 @@ def update_bot(name: Text, bot: Text): raise AppException("Bot not found") @staticmethod - def delete_bot(bot: Text): + def delete_bot(bot: Text, user: Text = None): from kairon.shared.data.data_objects import ( Intents, Responses, @@ -296,6 +296,7 @@ def delete_bot(bot: Text): ValidationLogs, ], bot, + user=user ) AccountProcessor.remove_bot_access(bot) except DoesNotExist: @@ -1182,7 +1183,7 @@ def get_ui_config(user: str): return config @staticmethod - def delete_account(account_id: int): + def delete_account(account_id: int, email: str = None): """ Delete User Account @@ -1192,6 +1193,7 @@ def delete_account(account_id: int): """ try: account_obj = Account.objects(id=account_id, status=True).get() + except DoesNotExist: raise AppException("Account does not exist!") @@ -1199,7 +1201,7 @@ def delete_account(account_id: int): account_bots = list(AccountProcessor.list_bots(account_id)) # Delete all account_owned bots for bot in account_bots: - AccountProcessor.delete_bot(bot["_id"]) + AccountProcessor.delete_bot(bot["_id"], email) UserActivityLogger.add_log( a_type=UserActivityType.delete_bot.value, diff --git a/kairon/shared/cognition/processor.py b/kairon/shared/cognition/processor.py index 860d50eb6..df2c7b394 100644 --- a/kairon/shared/cognition/processor.py +++ b/kairon/shared/cognition/processor.py @@ -82,7 +82,7 @@ def save_cognition_schema(self, schema: Dict, user: Text, bot: Text): metadata_id = metadata_obj.save().to_mongo().to_dict()["_id"].__str__() return metadata_id - def delete_cognition_schema(self, schema_id: str, bot: Text): + def delete_cognition_schema(self, schema_id: str, bot: Text, user: str = None): try: metadata = CognitionSchema.objects(bot=bot, id=schema_id).get() CognitionDataProcessor.validate_collection_name(bot, metadata['collection_name']) @@ -91,7 +91,7 @@ def delete_cognition_schema(self, schema_id: str, bot: Text): if cognition_data: for data in cognition_data: data.delete() - metadata.delete() + Utility.delete_documents(metadata, user) except DoesNotExist: raise AppException("Schema does not exists!") @@ -300,10 +300,10 @@ def update_cognition_data(self, row_id: str, payload: Dict, user: Text, bot: Tex except DoesNotExist: raise AppException("Payload with given id not found!") - def delete_cognition_data(self, row_id: str, bot: Text): + def delete_cognition_data(self, row_id: str, bot: Text, user: str = None): try: payload = CognitionData.objects(bot=bot, id=row_id).get() - payload.delete() + Utility.delete_documents(payload, user) except DoesNotExist: raise AppException("Payload does not exists!") diff --git a/kairon/shared/custom_widgets/processor.py b/kairon/shared/custom_widgets/processor.py index 8aeedd75f..a0f05de8f 100644 --- a/kairon/shared/custom_widgets/processor.py +++ b/kairon/shared/custom_widgets/processor.py @@ -51,10 +51,10 @@ def list_widgets(bot: Text): return [w_id.__str__() for w_id in CustomWidgets.objects(bot=bot).values_list('id')] @staticmethod - def delete_config(widget_id: Text, bot: Text): + def delete_config(widget_id: Text, bot: Text, user: str = None): try: widget = CustomWidgets.objects(id=widget_id, bot=bot).get() - widget.delete() + Utility.delete_documents(widget, user) except DoesNotExist as e: logger.exception(e) raise AppException("Widget does not exists!") diff --git a/kairon/shared/data/processor.py b/kairon/shared/data/processor.py index 3ac83afc9..175d2fa37 100644 --- a/kairon/shared/data/processor.py +++ b/kairon/shared/data/processor.py @@ -508,7 +508,7 @@ def delete_nlu(self, bot: Text, user: Text): :return: None """ Utility.hard_delete_document( - [TrainingExamples, EntitySynonyms, LookupTables, RegexFeatures], bot=bot + [TrainingExamples, EntitySynonyms, LookupTables, RegexFeatures], bot=bot, user=user ) def load_nlu(self, bot: Text) -> TrainingData: @@ -573,8 +573,9 @@ def delete_domain(self, bot: Text, user: Text): Utterances, ], bot=bot, + user=user ) - Utility.hard_delete_document([Actions], bot=bot, type=None) + Utility.hard_delete_document([Actions], bot=bot, type=None, user=user) def load_domain(self, bot: Text) -> Domain: """ @@ -615,7 +616,7 @@ def delete_stories(self, bot: Text, user: Text): :param user: user id :return: None """ - Utility.hard_delete_document([Stories], bot=bot) + Utility.hard_delete_document([Stories], bot=bot, user=user) def load_stories(self, bot: Text) -> StoryGraph: """ @@ -634,7 +635,7 @@ def delete_multiflow_stories(self, bot: Text, user: Text): :param user: user id :return: None """ - Utility.hard_delete_document([MultiflowStories], bot=bot) + Utility.hard_delete_document([MultiflowStories], bot=bot, user=user) def delete_bot_content(self, bot: Text, user: Text): """ @@ -643,8 +644,8 @@ def delete_bot_content(self, bot: Text, user: Text): :param user: user id :return: None """ - Utility.hard_delete_document([CognitionSchema], bot=bot) - Utility.hard_delete_document([CognitionData], bot=bot) + Utility.hard_delete_document([CognitionSchema], bot=bot, user=user) + Utility.hard_delete_document([CognitionData], bot=bot, user=user) def save_multiflow_stories(self, multiflow_stories: dict, bot: Text, user: Text): """ @@ -1157,8 +1158,16 @@ def fetch_actions(self, bot: Text, status=True): actions = Actions.objects(bot=bot, status=status).values_list("name") actions_list = list(actions) - if Stories.objects(bot=bot, status=status, events__name='action_listen').count() > 0: - actions_list.append('action_listen') + for story in Stories.objects(bot=bot, status=status): + for event in story.events: + if event.name == 'action_listen': + if 'action_listen' not in actions_list: + actions_list.append('action_listen') + + for story in MultiflowStories.objects(bot=bot, status=status): + for event in story.events: + if event.step.name == 'stop_flow_action' and 'stop_flow_action' not in actions_list: + actions_list.append('stop_flow_action') return actions_list @@ -2071,7 +2080,7 @@ def delete_config(self, bot: Text, user: Text): :param user: user id :return: None """ - Utility.hard_delete_document([Configs], bot=bot) + Utility.hard_delete_document([Configs], bot=bot, user=user) def fetch_configs(self, bot: Text): """ @@ -2629,7 +2638,7 @@ def delete_entity( """ try: entity = Entities.objects(name=name, bot=bot, status=True).get() - entity.delete() + Utility.delete_documents(entity, user) except DoesNotExist: if raise_exc_if_not_exists: raise AppException("Entity not found") @@ -3287,7 +3296,7 @@ def delete_complex_story(self, story_id: str, type: Text, bot: Text, user: Text) raise AppException("Invalid type") try: document = data_class.objects(bot=bot, status=True).get(id=story_id) - document.delete() + Utility.delete_documents(document, user) except DoesNotExist: raise AppException("Flow does not exists") @@ -3749,16 +3758,15 @@ def delete_intent( ) try: - intent_obj.user = user Utility.hard_delete_document( - [TrainingExamples], bot=bot, intent__iexact=intent + [TrainingExamples], bot=bot, intent__iexact=intent, user=user ) - intent_obj.delete() + Utility.delete_documents(intent_obj, user) except Exception as ex: logging.info(ex) raise AppException("Unable to remove document" + str(ex)) - def delete_utterance(self, utterance: str, bot: str, validate_form: bool = True): + def delete_utterance(self, utterance: str, bot: str, validate_form: bool = True, user: str = None): if not (utterance and utterance.strip()): raise AppException("Utterance cannot be empty or spaces") try: @@ -3775,13 +3783,13 @@ def delete_utterance(self, utterance: str, bot: str, validate_form: bool = True) ) MongoProcessor.get_attached_flows(bot, utterance_name, "action") - Utility.hard_delete_document([Responses], bot=bot, name=utterance_name) - utterance.delete() + Utility.hard_delete_document([Responses], bot=bot, name=utterance_name, user=user) + Utility.delete_documents(utterance, user) except DoesNotExist as e: logging.info(e) raise AppException("Utterance does not exists") - def delete_response(self, utterance_id: str, bot: str): + def delete_response(self, utterance_id: str, bot: str, user: str = None): if not (utterance_id and utterance_id.strip()): raise AppException("Response Id cannot be empty or spaces") try: @@ -3799,8 +3807,8 @@ def delete_response(self, utterance_id: str, bot: str): "At least one response is required for utterance linked to story" ) if len(responses) <= 1: - self.delete_utterance_name(name=utterance_name, bot=bot, raise_exc=True) - response.delete() + self.delete_utterance_name(name=utterance_name, bot=bot, raise_exc=True, user=user) + Utility.delete_documents(response, user) except DoesNotExist as e: raise AppException(e) @@ -4497,8 +4505,7 @@ def delete_slot(self, slot_name: Text, bot: Text, user: Text): raise AppException( f'Slot is attached to multi-flow story: {[story["block_name"] for story in multi_stories]}' ) - - slot.delete() + Utility.delete_documents(slot, user) self.delete_entity(slot_name, bot, user, False) except DoesNotExist as custEx: logging.info(custEx) @@ -4628,7 +4635,7 @@ def delete_rules(self, bot: Text, user: Text): :param user: user id :return: None """ - Utility.hard_delete_document([Rules], bot=bot) + Utility.hard_delete_document([Rules], bot=bot, user=user) def delete_bot_actions(self, bot: Text, user: Text): """ @@ -4642,8 +4649,8 @@ def delete_bot_actions(self, bot: Text, user: Text): HttpActionConfig, SlotSetAction, FormValidationAction, EmailActionConfig, GoogleSearchAction, JiraAction, ZendeskAction, PipedriveLeadsAction, HubspotFormsAction, KaironTwoStageFallbackAction, PromptAction, PyscriptActionConfig, RazorpayAction, DatabaseAction - ], bot=bot) - Utility.hard_delete_document([Actions], bot=bot, type__ne=None) + ], bot=bot, user=user) + Utility.hard_delete_document([Actions], bot=bot, type__ne=None, user=user) def __get_rules(self, bot: Text): for rule in Rules.objects(bot=bot, status=True): @@ -5362,22 +5369,23 @@ def edit_synonym( except DoesNotExist: raise AppException("Synonym value does not exist!") - def delete_synonym(self, id: str, bot: str): + def delete_synonym(self, id: str, bot: str, user: str = None): """ delete the synonym and its values :param id: synonym id :param bot: bot id + :param user: user id """ try: synonym = Synonyms.objects(bot=bot, status=True).get(id=id) Utility.hard_delete_document( - [EntitySynonyms], bot=bot, status=True, name__iexact=synonym.name + [EntitySynonyms], bot=bot, status=True, name__iexact=synonym.name, user=user ) - synonym.delete() + Utility.delete_documents(synonym, user) except DoesNotExist as e: raise AppException(e) - def delete_synonym_value(self, synonym_name: str, value_id: str, bot: str): + def delete_synonym_value(self, synonym_name: str, value_id: str, bot: str, user: str = None): """ delete particular synonym value :param synonym_name: name of synonym @@ -5390,7 +5398,7 @@ def delete_synonym_value(self, synonym_name: str, value_id: str, bot: str): synonym_value = EntitySynonyms.objects( bot=bot, status=True, name__exact=synonym_name ).get(id=value_id) - synonym_value.delete() + Utility.delete_documents(synonym_value, user) except DoesNotExist as e: raise AppException(e) @@ -5442,7 +5450,7 @@ def get_utterances(self, bot: Text): utterance.pop("user") yield utterance - def delete_utterance_name(self, name: Text, bot: Text, raise_exc: bool = False): + def delete_utterance_name(self, name: Text, bot: Text, raise_exc: bool = False, user: str = None): try: utterance = Utterances.objects( name__iexact=name, bot=bot, status=True @@ -5453,7 +5461,7 @@ def delete_utterance_name(self, name: Text, bot: Text, raise_exc: bool = False): f"Utterance cannot be deleted as it is linked to form: {utterance.form_attached}" ) else: - utterance.delete() + Utility.delete_documents(utterance, user) except DoesNotExist as e: logging.info(e) if raise_exc: @@ -5796,7 +5804,7 @@ def delete_regex(self, regex_name: Text, bot: Text, user: Text): regex = RegexFeatures.objects( name__iexact=regex_name, bot=bot, status=True ).get() - regex.delete() + Utility.delete_documents(regex, user) except DoesNotExist: raise AppException("Regex name does not exist.") @@ -5959,7 +5967,7 @@ def edit_lookup_value( except DoesNotExist: raise AppException("Lookup value does not exist!") - def delete_lookup(self, lookup_id: str, bot: str): + def delete_lookup(self, lookup_id: str, bot: str, user: str = None): """ delete lookup and its value :param lookup_id: lookup ID @@ -5972,11 +5980,11 @@ def delete_lookup(self, lookup_id: str, bot: str): Utility.hard_delete_document( [LookupTables], bot=bot, name__exact=lookup.name ) - lookup.delete() + Utility.delete_documents(lookup, user) except DoesNotExist: raise AppException("Invalid lookup!") - def delete_lookup_value(self, lookup_value_id: str, lookup_name: str, bot: str): + def delete_lookup_value(self, lookup_value_id: str, lookup_name: str, bot: str, user: str = None): """ delete a lookup value :param lookup_value_id: value ID @@ -5989,7 +5997,7 @@ def delete_lookup_value(self, lookup_value_id: str, lookup_name: str, bot: str): lookup_value = LookupTables.objects( bot=bot, status=True, name__iexact=lookup_name ).get(id=lookup_value_id) - lookup_value.delete() + Utility.delete_documents(lookup_value, user) except DoesNotExist as e: raise AppException(e) @@ -6192,7 +6200,7 @@ def edit_form(self, name: str, path: list, bot: Text, user: Text): for slot in slots_to_remove: try: - self.delete_utterance(f"utter_ask_{name}_{slot}", bot, False) + self.delete_utterance(f"utter_ask_{name}_{slot}", bot, False, user=user) except AppException: pass @@ -6221,10 +6229,10 @@ def delete_form(self, name: Text, bot: Text, user: Text): for slot in form.required_slots: try: utterance_name = f"utter_ask_{name}_{slot}" - self.delete_utterance(utterance_name, bot, False) + self.delete_utterance(utterance_name, bot, False, user=user) except Exception as e: logging.info(str(e)) - form.delete() + Utility.delete_documents(form, user) if Utility.is_exist( FormValidationAction, raise_error=False, @@ -6312,7 +6320,7 @@ def update_slot_mapping(self, mapping: dict, slot_mapping_id: str): except Exception as e: raise AppException(e) - def delete_single_slot_mapping(self, slot_mapping_id: str): + def delete_single_slot_mapping(self, slot_mapping_id: str, user: str = None): """ Delete slot mapping. @@ -6320,7 +6328,7 @@ def delete_single_slot_mapping(self, slot_mapping_id: str): """ try: slot_mapping = SlotMapping.objects(id=slot_mapping_id, status=True).get() - slot_mapping.delete() + Utility.delete_documents(slot_mapping, user) except Exception as e: raise AppException(e) @@ -6482,68 +6490,82 @@ def delete_action(self, name: Text, bot: Text, user: Text): [SlotSetAction], name__iexact=name, bot=bot, + user=user ) elif action.type == ActionType.form_validation_action.value: Utility.hard_delete_document( [FormValidationAction], name__iexact=name, bot=bot, + user=user ) elif action.type == ActionType.email_action.value: Utility.hard_delete_document( [EmailActionConfig], action_name__iexact=name, bot=bot, + user=user ) elif action.type == ActionType.google_search_action.value: Utility.hard_delete_document( [GoogleSearchAction], name__iexact=name, bot=bot, + user=user ) elif action.type == ActionType.jira_action.value: Utility.hard_delete_document( [JiraAction], name__iexact=name, bot=bot, + user=user ) elif action.type == ActionType.http_action.value: Utility.hard_delete_document( - [HttpActionConfig], action_name__iexact=name, bot=bot + [HttpActionConfig], action_name__iexact=name, bot=bot, + user=user ) elif action.type == ActionType.zendesk_action.value: Utility.hard_delete_document( - [ZendeskAction], name__iexact=name, bot=bot + [ZendeskAction], name__iexact=name, bot=bot, + user=user ) elif action.type == ActionType.pipedrive_leads_action.value: Utility.hard_delete_document( - [PipedriveLeadsAction], name__iexact=name, bot=bot + [PipedriveLeadsAction], name__iexact=name, bot=bot, + user=user ) elif action.type == ActionType.hubspot_forms_action.value: Utility.hard_delete_document( - [HubspotFormsAction], name__iexact=name, bot=bot + [HubspotFormsAction], name__iexact=name, bot=bot, + user=user ) elif action.type == ActionType.two_stage_fallback.value: Utility.hard_delete_document( - [KaironTwoStageFallbackAction], name__iexact=name, bot=bot + [KaironTwoStageFallbackAction], name__iexact=name, bot=bot, + user=user ) elif action.type == ActionType.razorpay_action.value: Utility.hard_delete_document( - [RazorpayAction], name__iexact=name, bot=bot + [RazorpayAction], name__iexact=name, bot=bot, + user=user ) elif action.type == ActionType.database_action.value: Utility.hard_delete_document( - [DatabaseAction], name__iexact=name, bot=bot + [DatabaseAction], name__iexact=name, bot=bot, + user=user ) elif action.type == ActionType.web_search_action.value: Utility.hard_delete_document( - [WebSearchAction], name__iexact=name, bot=bot + [WebSearchAction], name__iexact=name, bot=bot, + user=user ) elif action.type == ActionType.prompt_action.value: - Utility.hard_delete_document([PromptAction], name__iexact=name, bot=bot) + Utility.hard_delete_document([PromptAction], name__iexact=name, bot=bot, user=user) elif action.type == ActionType.pyscript_action.value: Utility.hard_delete_document( - [PyscriptActionConfig], name__iexact=name, bot=bot + [PyscriptActionConfig], name__iexact=name, bot=bot, + user=user ) elif action.type == ActionType.schedule_action.value: Utility.hard_delete_document( @@ -6998,7 +7020,7 @@ def list_secrets(bot: Text): return keys @staticmethod - def delete_secret(key: Text, bot: Text): + def delete_secret(key: Text, bot: Text, **kwargs): """ Delete secret for bot. @@ -7174,7 +7196,8 @@ def delete_secret(key: Text, bot: Text): if len(custom_widgets): raise AppException(f"Key is attached to custom widget: {custom_widgets}") - KeyVault.objects(key=key, bot=bot).delete() + kv = KeyVault.objects(key=key, bot=bot).get() + Utility.delete_documents(kv, kwargs.get("user")) def add_two_stage_fallback_action(self, request_data: dict, bot: Text, user: Text): """ @@ -7654,7 +7677,7 @@ def save_faq(self, bot: Text, user: Text, df: DataFrame): error_summary["utterances"].append(str(e)) self.delete_intent(intent, bot, user, False) if is_response_added: - self.delete_utterance(action, bot) + self.delete_utterance(action, bot, user=user) return component_count, error_summary def delete_all_faq(self, bot: Text): @@ -7877,9 +7900,9 @@ def edit_live_agent(self, request_data: dict, bot: Text, user: Text): if not live_agent: raise AppException("Live agent not enabled for the bot") - def disable_live_agent(self, bot: Text): + def disable_live_agent(self, bot: Text, user: str = None): Utility.hard_delete_document([Actions], bot, name__iexact="live_agent_action") - Utility.hard_delete_document([LiveAgentActionConfig], bot=bot) + Utility.hard_delete_document([LiveAgentActionConfig], bot=bot, user=user) def is_live_agent_enabled(self, bot: Text, check_in_utils: bool = True): bot_setting = BotSettings.objects(bot=bot).get().to_mongo().to_dict() @@ -7888,7 +7911,6 @@ def is_live_agent_enabled(self, bot: Text, check_in_utils: bool = True): if not check_in_utils: return True return Utility.is_exist(LiveAgentActionConfig, raise_error=False, bot=bot, status=True) - def add_callback(self, request_data: dict, bot: Text): """ Add callback config. diff --git a/kairon/shared/live_agent/live_agent.py b/kairon/shared/live_agent/live_agent.py index c759c4392..ac080412c 100644 --- a/kairon/shared/live_agent/live_agent.py +++ b/kairon/shared/live_agent/live_agent.py @@ -90,7 +90,7 @@ async def check_live_agent_active(bot_id, userdata: UserMessage): 'Authorization': f"Bearer {auth_token}" } res, status, _, _ = await ActionUtility.execute_request_async(url, 'GET', None, headers) - if status != 200: + if res and status != 200: return False return res['data']['status'] diff --git a/kairon/shared/live_agent/processor.py b/kairon/shared/live_agent/processor.py index 40f556fd0..c3144ec91 100644 --- a/kairon/shared/live_agent/processor.py +++ b/kairon/shared/live_agent/processor.py @@ -36,14 +36,14 @@ def save_config(configuration: Dict, bot: Text, user: Text): agent.save() @staticmethod - def delete_config(bot: Text): + def delete_config(bot: Text, user: str = None): """ Delete a particular live agent configuration for bot :param bot: bot id :return: None """ - Utility.hard_delete_document([LiveAgents], bot=bot) + Utility.hard_delete_document([LiveAgents], bot=bot, user=user) @staticmethod def get_config(bot: Text, mask_characters=True, raise_error: bool = True): diff --git a/kairon/shared/organization/processor.py b/kairon/shared/organization/processor.py index 39d9da8d7..150e8409a 100644 --- a/kairon/shared/organization/processor.py +++ b/kairon/shared/organization/processor.py @@ -131,14 +131,14 @@ def delete_org_mapping(org): logger.error(str(ex)) @staticmethod - def delete_org(account, org_id): + def delete_org(account, org_id, user:str = None): try: org = Organization.objects(name=org_id, account__contains=account).get() org_name = org.name - org.delete() + Utility.delete_documents(org, user) except DoesNotExist: raise AppException("Organization not found") - IDPProcessor.delete_idp(org_name) + IDPProcessor.delete_idp(org_name, user=user) OrgProcessor.delete_org_mapping(org_id) @staticmethod diff --git a/kairon/shared/utils.py b/kairon/shared/utils.py index f1f9326f2..6cb1895f7 100644 --- a/kairon/shared/utils.py +++ b/kairon/shared/utils.py @@ -561,9 +561,11 @@ def hard_delete_document(documents: List[Document], bot: Text, **kwargs): """ for document in documents: kwargs["bot"] = bot + user = kwargs.pop("user", "System") fetched_documents = document.objects(**kwargs) - if fetched_documents.count() > 0: - fetched_documents.delete() + for doc in fetched_documents: + doc["user"] = user + doc.delete() @staticmethod def extract_db_config(uri: str): @@ -2191,6 +2193,16 @@ def is_picklable_for_mongo(obj): logger.exception(e) return False + @staticmethod + def delete_documents(document: Document, user: str = "System"): + """ + delete the given document, main purpose of this api is set current user and maintain in auditlog. + if user is not provided 'System' user will be passed. + """ + if document: + document["user"] = user + document.delete() + class StoryValidator: @staticmethod diff --git a/tests/unit_test/api/api_processor_test.py b/tests/unit_test/api/api_processor_test.py index 363272358..676e71710 100644 --- a/tests/unit_test/api/api_processor_test.py +++ b/tests/unit_test/api/api_processor_test.py @@ -2755,7 +2755,7 @@ def _delete_idp(*args, **kwargs): account = 1234 name = "new_test" - OrgProcessor.delete_org(account=account, org_id=name) + OrgProcessor.delete_org(account=account, org_id=name, user="test") org = OrgProcessor.get_organization(org_name=name) assert org == {} diff --git a/tests/unit_test/data_processor/custom_widgets_processor_test.py b/tests/unit_test/data_processor/custom_widgets_processor_test.py index 890634b8b..884ea8554 100644 --- a/tests/unit_test/data_processor/custom_widgets_processor_test.py +++ b/tests/unit_test/data_processor/custom_widgets_processor_test.py @@ -126,13 +126,13 @@ def test_list_widgets_not_exists(self): def test_delete_widget(self): bot = "test_bot" - CustomWidgetsProcessor.delete_config(pytest.widget_id, bot) + CustomWidgetsProcessor.delete_config(pytest.widget_id, bot, "test") assert list(CustomWidgetsProcessor.get_config(bot)) == [] def test_delete_widget_not_exists(self): bot = "test_bot" with pytest.raises(AppException, match="Widget does not exists!"): - CustomWidgetsProcessor.delete_config(pytest.widget_id, bot) + CustomWidgetsProcessor.delete_config(pytest.widget_id, bot, "test") @responses.activate def test_trigger_widget(self): diff --git a/tests/unit_test/data_processor/data_processor_test.py b/tests/unit_test/data_processor/data_processor_test.py index 94f62c10e..e93caa16d 100644 --- a/tests/unit_test/data_processor/data_processor_test.py +++ b/tests/unit_test/data_processor/data_processor_test.py @@ -1145,7 +1145,7 @@ def test_disable_live_agent(self): "bot_response": "connecting to different live agent...", "dispatch_bot_response": True, } - result = processor.disable_live_agent(bot=bot) + result = processor.disable_live_agent(bot=bot, user=user) live_agent = processor.get_live_agent(bot=bot) assert live_agent == [] @@ -4276,11 +4276,11 @@ def test_delete_response(self): utter_intentA_2_id = processor.add_response({"text": "demo_response2"}, utterance, bot, user) resp = processor.get_response(utterance, bot) assert len(list(resp)) == 2 - processor.delete_response(utter_intentA_1_id, bot) + processor.delete_response(utter_intentA_1_id, bot, user=user) resp = processor.get_response(utterance, bot) assert len(list(resp)) == 1 assert Utterances.objects(name=utterance, bot=bot, status=True).get() - processor.delete_response(utter_intentA_2_id, bot) + processor.delete_response(utter_intentA_2_id, bot, user=user) resp = processor.get_response(utterance, bot) assert len(list(resp)) == 0 with pytest.raises(DoesNotExist): @@ -4303,7 +4303,7 @@ def test_delete_utterance(self): user = "testUser" processor.add_response({"text": "demo_response1"}, utterance, bot, user) Utterances.objects(name=utterance, bot=bot, status=True).get() - processor.delete_utterance(utterance, bot, user) + processor.delete_utterance(utterance, bot, user=user) with pytest.raises(DoesNotExist): Utterances.objects(name=utterance, bot=bot, status=True).get() @@ -4313,7 +4313,7 @@ def test_delete_utterance_non_existing(self): bot = "testBot" user = "testUser" with pytest.raises(AppException): - processor.delete_utterance(utterance, bot, user) + processor.delete_utterance(utterance, bot, user=user) def test_delete_utterance_empty(self): processor = MongoProcessor() @@ -4321,7 +4321,7 @@ def test_delete_utterance_empty(self): bot = "testBot" user = "testUser" with pytest.raises(AppException): - processor.delete_utterance(utterance, bot, user) + processor.delete_utterance(utterance, bot, user=user) def test_delete_utterance_name_having_no_responses(self): processor = MongoProcessor() @@ -4329,7 +4329,7 @@ def test_delete_utterance_name_having_no_responses(self): bot = "testBot" user = "testUser" processor.add_utterance_name(utterance, bot, user) - processor.delete_utterance(utterance, bot, user) + processor.delete_utterance(utterance, bot, user=user) with pytest.raises(DoesNotExist): Utterances.objects(name__iexact=utterance, bot=bot, status=True).get() @@ -6737,7 +6737,7 @@ def test_add_delete_synonym_value(self): processor.add_synonym_values({"name": "bot", "value": ["exp"]}, bot, user) response = list(processor.get_synonym_values("bot", bot)) assert len(response) == 2 - processor.delete_synonym_value("bot", response[0]["_id"], bot) + processor.delete_synonym_value("bot", response[0]["_id"], bot, user=user) response = list(processor.get_synonym_values("bot", bot)) assert len(response) == 1 @@ -6762,7 +6762,7 @@ def test_delete_synonym_name(self): response = list(processor.get_synonym_values("bot", bot)) assert len(response) == 1 - processor.delete_synonym(synonym_id, bot) + processor.delete_synonym(synonym_id, bot, user="test") response = list(processor.fetch_synonyms(bot)) assert len(response) == 0 @@ -6841,7 +6841,7 @@ def test_delete_utterance_name_does_not_exists_no_exc(self): def test_delete_utterance_name(self): processor = MongoProcessor() - processor.delete_utterance_name('test_add', 'test') + processor.delete_utterance_name('test_add', 'test', user="test") def test_get_bot_settings_not_added(self): processor = MongoProcessor() @@ -7282,19 +7282,19 @@ def test_add_delete_lookup_value(self): processor.add_lookup_values({"name": "number", "value": ["one"]}, bot, user) response = list(processor.get_lookup_values("number", bot)) assert len(response) == 2 - processor.delete_lookup_value(response[0]["_id"], "number", bot) + processor.delete_lookup_value(response[0]["_id"], "number", bot, user) response = list(processor.get_lookup_values("number", bot)) assert len(response) == 1 def test_delete_lookup_value_empty(self): processor = MongoProcessor() with pytest.raises(AppException): - processor.delete_lookup_value(" ", "df", "test") + processor.delete_lookup_value(" ", "df", "test", "test_user") def test_delete_non_existent_lookup(self): processor = MongoProcessor() with pytest.raises(AppException): - processor.delete_lookup_value("0123456789ab0123456789ab", "df", "test") + processor.delete_lookup_value("0123456789ab0123456789ab", "df", "test", "test_user") def test_delete_lookup_name(self): processor = MongoProcessor() @@ -7304,7 +7304,7 @@ def test_delete_lookup_name(self): processor.add_lookup_value("bot", "exp", bot, user) assert len(list(processor.get_lookups(bot))) == 1 assert len(list(processor.get_lookup_values("bot", bot))) == 1 - processor.delete_lookup(lookup_id, bot) + processor.delete_lookup(lookup_id, bot, user) response = list(processor.get_lookups(bot)) assert len(response) == 0 response = list(processor.get_lookup_values("bot", bot)) @@ -7313,12 +7313,12 @@ def test_delete_lookup_name(self): def test_delete_lookup_name_empty(self): processor = MongoProcessor() with pytest.raises(AppException): - processor.delete_lookup(" ", "df") + processor.delete_lookup(" ", "df", "test") def test_delete_non_existent_lookup_name(self): processor = MongoProcessor() with pytest.raises(AppException): - processor.delete_lookup("0123456789ab0123456789ab", "df") + processor.delete_lookup("0123456789ab0123456789ab", "df", "test") def test_add_empty_lookup(self): processor = MongoProcessor() @@ -7564,7 +7564,7 @@ def test_delete_utterance_from_form_2(self): assert resp[0].text.text == 'what is your occupation?' assert resp[1].text.text == 'occupation?' assert resp[2].text.text == 'your occupation?' - assert not processor.delete_response(str(resp[2].id), bot) + assert not processor.delete_response(str(resp[2].id), bot, user=user) def test_add_utterance_to_form_not_exists(self): bot = 'test' @@ -8581,7 +8581,7 @@ def test_edit_utterance_for_form(self): def test_delete_response_linked_to_form_validation_false(self): processor = MongoProcessor() bot = 'test' - processor.delete_utterance('utter_ask_restaurant_form_cuisine', bot, False) + processor.delete_utterance('utter_ask_restaurant_form_cuisine', bot, False, user="test") with pytest.raises(DoesNotExist): Utterances.objects(name='utter_ask_restaurant_form_cuisine', bot=bot, status=True).get() with pytest.raises(DoesNotExist): @@ -10454,7 +10454,7 @@ def test_add_vector_embedding_action_config_op_embedding_search(self): assert actual_vectordb_action['response']['value'] == '0' with pytest.raises(AppException, match='Cannot remove collection test_add_vector_embedding_action_config_op_embedding_search linked to action "test_vectordb_action_op_embedding_search"!'): - processor.delete_cognition_schema(pytest.delete_schema_id_db_action, bot) + processor.delete_cognition_schema(pytest.delete_schema_id_db_action, bot, user=user) def test_add_vector_embedding_action_with_story(self): processor = MongoProcessor() @@ -14972,7 +14972,7 @@ def test_delete_secret(self): processor = MongoProcessor() bot = 'test' key = "AWS_KEY" - processor.delete_secret(key, bot) + processor.delete_secret(key, bot, user="test") with pytest.raises(DoesNotExist): KeyVault.objects(key=key, bot=bot).get() @@ -14981,7 +14981,7 @@ def test_delete_secret_not_exists(self): bot = 'test' key = "GCPKEY" with pytest.raises(AppException, match=f"key '{key}' does not exists!"): - processor.delete_secret(key, bot) + processor.delete_secret(key, bot, user="test") def test_get_secret_not_found(self): processor = MongoProcessor() @@ -15021,7 +15021,7 @@ def test_delete_secret_attached_to_http_action(self): ).save() with pytest.raises(AppException, match=re.escape( "Key is attached to action: ['test_delete_secret_attached_to_http_action']")): - processor.delete_secret(key, bot) + processor.delete_secret(key, bot, user="test") action = HttpActionConfig.objects(action_name="test_delete_secret_attached_to_http_action", bot=bot).get() action.params_list = [] @@ -15029,14 +15029,14 @@ def test_delete_secret_attached_to_http_action(self): action.save() with pytest.raises(AppException, match=re.escape( "Key is attached to action: ['test_delete_secret_attached_to_http_action']")): - processor.delete_secret(key, bot) + processor.delete_secret(key, bot, user=user) action = HttpActionConfig.objects(action_name="test_delete_secret_attached_to_http_action", bot=bot).get() action.params_list = [] action.headers = [HttpActionRequestBody(key="param1", value="param1", parameter_type="key_vault"), HttpActionRequestBody(key="param2", value=key, parameter_type="value")] action.save() - processor.delete_secret(key, bot) + processor.delete_secret(key, bot, user=user) with pytest.raises(DoesNotExist): KeyVault.objects(key=key, bot=bot).get() @@ -15063,7 +15063,7 @@ def test_delete_secret_attached_to_email_action(self): processor.add_email_action(email_config, bot, user) with pytest.raises(AppException, match=re.escape( "Key is attached to action: ['test_delete_secret_attached_to_email_action']")): - processor.delete_secret(key, bot) + processor.delete_secret(key, bot, user="test") action = EmailActionConfig.objects(action_name="test_delete_secret_attached_to_email_action", bot=bot).get() action.smtp_userid = None @@ -15072,14 +15072,14 @@ def test_delete_secret_attached_to_email_action(self): action.save() with pytest.raises(AppException, match=re.escape( "Key is attached to action: ['test_delete_secret_attached_to_email_action']")): - processor.delete_secret(key, bot) + processor.delete_secret(key, bot, user=user) action = EmailActionConfig.objects(action_name="test_delete_secret_attached_to_email_action", bot=bot).get() action.smtp_userid = None action.smtp_password = CustomActionRequestParameters(key="param2", value="param2", parameter_type="key_vault") with patch("kairon.shared.utils.SMTP", autospec=True): action.save() - processor.delete_secret(key, bot) + processor.delete_secret(key, bot, user=user) with pytest.raises(DoesNotExist): KeyVault.objects(key=key, bot=bot).get() @@ -15100,12 +15100,12 @@ def test_delete_secret_attached_to_google_action(self): processor.add_google_search_action(action, bot, user) with pytest.raises(AppException, match=re.escape( "Key is attached to action: ['test_delete_secret_attached_to_google_action']")): - processor.delete_secret(key, bot) + processor.delete_secret(key, bot, user=user) action = GoogleSearchAction.objects(name="test_delete_secret_attached_to_google_action", bot=bot).get() action.api_key = CustomActionRequestParameters(key="param2", value="param2", parameter_type="key_vault") action.save() - processor.delete_secret(key, bot) + processor.delete_secret(key, bot, user=user) with pytest.raises(DoesNotExist): KeyVault.objects(key=key, bot=bot).get() @@ -15131,13 +15131,13 @@ def _mock_validation(*args, **kwargs): processor.add_jira_action(action, bot, user) with pytest.raises(AppException, match=re.escape( "Key is attached to action: ['test_delete_secret_attached_to_jira_action']")): - processor.delete_secret(key, bot) + processor.delete_secret(key, bot, user=user) action = JiraAction.objects(name="test_delete_secret_attached_to_jira_action", bot=bot).get() action.api_token = CustomActionRequestParameters(key="param2", value="param2", parameter_type="key_vault") with patch('kairon.shared.actions.data_objects.JiraAction.validate', new=_mock_validation): action.save() - processor.delete_secret(key, bot) + processor.delete_secret(key, bot, user=user) with pytest.raises(DoesNotExist): KeyVault.objects(key=key, bot=bot).get() @@ -15160,13 +15160,13 @@ def _mock_validation(*args, **kwargs): processor.add_zendesk_action(action, bot, user) with pytest.raises(AppException, match=re.escape( "Key is attached to action: ['test_delete_secret_attached_to_zendesk_action']")): - processor.delete_secret(key, bot) + processor.delete_secret(key, bot, user=user) action = ZendeskAction.objects(name="test_delete_secret_attached_to_zendesk_action", bot=bot).get() action.api_token = CustomActionRequestParameters(key="param2", value="param2", parameter_type="key_vault") with patch('kairon.shared.actions.data_objects.ZendeskAction.validate', new=_mock_validation): action.save() - processor.delete_secret(key, bot) + processor.delete_secret(key, bot, user=user) with pytest.raises(DoesNotExist): KeyVault.objects(key=key, bot=bot).get() @@ -15194,13 +15194,13 @@ def _mock_validation(*args, **kwargs): processor.add_pipedrive_action(action, bot, user) with pytest.raises(AppException, match=re.escape( "Key is attached to action: ['test_delete_secret_attached_to_pipedrivelead_action']")): - processor.delete_secret(key, bot) + processor.delete_secret(key, bot, user=user) action = PipedriveLeadsAction.objects(name="test_delete_secret_attached_to_pipedrivelead_action", bot=bot).get() action.api_token = CustomActionRequestParameters(key="param2", value="param2", parameter_type="key_vault") with patch('kairon.shared.actions.data_objects.PipedriveLeadsAction.validate', new=_mock_validation): action.save() - processor.delete_secret(key, bot) + processor.delete_secret(key, bot, user=user) with pytest.raises(DoesNotExist): KeyVault.objects(key=key, bot=bot).get() @@ -15228,14 +15228,14 @@ def _mock_validation(*args, **kwargs): processor.add_hubspot_forms_action(action, bot, user) with pytest.raises(AppException, match=re.escape( "Key is attached to action: ['test_delete_secret_attached_to_hubspot_action']")): - processor.delete_secret(key, bot) + processor.delete_secret(key, bot, user=user) action = HubspotFormsAction.objects(name="test_delete_secret_attached_to_hubspot_action", bot=bot).get() action.fields = [HttpActionRequestBody(key="param1", value="param1", parameter_type="key_vault"), HttpActionRequestBody(key="param2", value=key, parameter_type="value")] with patch('kairon.shared.actions.data_objects.HubspotFormsAction.validate', new=_mock_validation): action.save() - processor.delete_secret(key, bot) + processor.delete_secret(key, bot, user=user) with pytest.raises(DoesNotExist): KeyVault.objects(key=key, bot=bot).get() @@ -15532,8 +15532,8 @@ def test_save_payload_metadata(self): } with pytest.raises(AppException, match="Collection limit exceeded!"): processor.save_cognition_schema(schema_three, user, bot) - processor.delete_cognition_schema(pytest.schema_id_one, bot) - processor.delete_cognition_schema(pytest.schema_id_two, bot) + processor.delete_cognition_schema(pytest.schema_id_one, bot, user=user) + processor.delete_cognition_schema(pytest.schema_id_two, bot, user=user) schema_four = { "metadata": [ {"column_name": "details", "data_type": "str", "enable_search": True, "create_embeddings": True}], @@ -15559,7 +15559,7 @@ def test_save_payload_metadata(self): # Delete all schema except the last one for schema_id in schema_ids[:-1]: - processor.delete_cognition_schema(schema_id, bot) + processor.delete_cognition_schema(schema_id, bot, user=user) data = list(processor.list_cognition_schema(bot)) settings = BotSettings.objects(bot=bot).get() @@ -15644,7 +15644,7 @@ def test_delete_payload_metadata(self): processor = CognitionDataProcessor() bot = 'test' user = 'testUser' - processor.delete_cognition_schema(pytest.schema_id, bot) + processor.delete_cognition_schema(pytest.schema_id, bot, user=user) def test_save_payload_metadata_and_delete_with_no_cognition_data(self): processor = CognitionDataProcessor() @@ -15658,14 +15658,14 @@ def test_save_payload_metadata_and_delete_with_no_cognition_data(self): "user": user } pytest.schema_id_final = processor.save_cognition_schema(schema, user, bot) - processor.delete_cognition_schema(pytest.schema_id_final, bot) + processor.delete_cognition_schema(pytest.schema_id_final, bot, user=user) def test_delete_payload_metadata_does_not_exists(self): processor = CognitionDataProcessor() bot = 'test' user = 'testUser' with pytest.raises(AppException, match="Schema does not exists!"): - processor.delete_cognition_schema("507f191e050c19729de760ea", bot) + processor.delete_cognition_schema("507f191e050c19729de760ea", bot, user=user) def test_get_payload_metadata_not_exists(self): processor = CognitionDataProcessor() @@ -15710,9 +15710,9 @@ def test_delete_schema_attached_to_prompt_action(self): processor_two.add_prompt_action(request, bot, user) with pytest.raises(AppException, match='Cannot remove collection python linked to action "test_delete_schema_attached_to_prompt_action"!'): - processor.delete_cognition_schema(pytest.delete_schema_id, bot) + processor.delete_cognition_schema(pytest.delete_schema_id, bot, user=user) processor_two.delete_action('test_delete_schema_attached_to_prompt_action', bot, user) - processor.delete_cognition_schema(pytest.delete_schema_id, bot) + processor.delete_cognition_schema(pytest.delete_schema_id, bot, user=user) def test_save_content_with_gpt_feature_disabled(self): processor = CognitionDataProcessor() @@ -15872,7 +15872,7 @@ def test_delete_content(self): processor = CognitionDataProcessor() bot = 'test' user = 'testUser' - processor.delete_cognition_data(pytest.content_id, bot) + processor.delete_cognition_data(pytest.content_id, bot, user=user) def test_delete_content_does_not_exists(self): processor = CognitionDataProcessor() @@ -15956,13 +15956,14 @@ def _get_cognition_data(*args, **kwargs): def test_delete_content_for_action(self): processor = CognitionDataProcessor() bot = 'test' - processor.delete_cognition_data(pytest.content_id_unit, bot) + user = 'testUser' + processor.delete_cognition_data(pytest.content_id_unit, bot, user=user) def test_delete_payload_content_collection(self): processor = CognitionDataProcessor() bot = 'test' user = 'testUser' - processor.delete_cognition_schema(pytest.save_content_collection, bot) + processor.delete_cognition_schema(pytest.save_content_collection, bot, user=user) def test_save_payload_content_with_gpt_feature_disabled(self): processor = CognitionDataProcessor() @@ -16133,7 +16134,7 @@ def test_delete_payload_content(self): processor = CognitionDataProcessor() bot = 'test' user = 'testUser' - processor.delete_cognition_data(pytest.payload_id, bot) + processor.delete_cognition_data(pytest.payload_id, bot, user=user) def test_delete_payload_content_does_not_exists(self): processor = CognitionDataProcessor() diff --git a/tests/unit_test/idp/test_idp_helper.py b/tests/unit_test/idp/test_idp_helper.py index 0d74cc842..0fae25894 100644 --- a/tests/unit_test/idp/test_idp_helper.py +++ b/tests/unit_test/idp/test_idp_helper.py @@ -490,7 +490,7 @@ def _delete_realm(*args, **kwargs): assert fetched_idp_config["organization"] == "Test" assert fetched_idp_config["tenant"] == "fa1b21ce-4ca5-4009_new" - IDPProcessor.delete_idp(realm_name=realm_name) + IDPProcessor.delete_idp(realm_name=realm_name, user=user.email) fetched_idp_config = IDPProcessor.get_idp_config(account=user.account) assert fetched_idp_config == {} diff --git a/tests/unit_test/live_agent/live_agent_processor_test.py b/tests/unit_test/live_agent/live_agent_processor_test.py index 38b0ddf0a..37a12ea14 100644 --- a/tests/unit_test/live_agent/live_agent_processor_test.py +++ b/tests/unit_test/live_agent/live_agent_processor_test.py @@ -539,7 +539,7 @@ def test_get_live_agent_with_masked_required_fields(self): assert agent["trigger_on_actions"] == [] def test_delete_agent_config(self): - LiveAgentsProcessor.delete_config(pytest.bot.id) + LiveAgentsProcessor.delete_config(pytest.bot.id, "test_user") def test_get_agent_config_none(self): assert not LiveAgentsProcessor.get_config(pytest.bot.id, raise_error=False)