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
def cli(): parser = create_argument_parser() arguments = parser.parse_args() Utility.load_environment() connect(**Utility.mongoengine_connection(Utility.environment['database'] ["url"])) arguments.func(arguments)
def validate_channel_config_model(cls, v, values, **kwargs): if 'connector_type' in values: Utility.validate_channel_config(values['connector_type'], v, ValueError, encrypt=False) return v
async def from_training_files(cls, training_data_paths: str, domain_path: str, config_path: str, root_dir): """ Create validator from training files. @param training_data_paths: nlu.yml file path. @param domain_path: domain.yml file path. @param config_path: config.yml file path. @param root_dir: training data root directory. @return: """ if not (os.path.exists(training_data_paths) and os.path.exists(domain_path) and os.path.exists(config_path)): raise AppException("Some training files are absent!") try: file_importer = RasaFileImporter( domain_path=domain_path, training_data_paths=training_data_paths, config_file=config_path, ) cls.actions = Utility.read_yaml(os.path.join(root_dir, 'actions.yml')) return await TrainingDataValidator.from_importer(file_importer) except YamlValidationException as e: exc = Utility.replace_file_name(str(e), root_dir) raise AppException(exc) except YamlSyntaxException as e: exc = Utility.replace_file_name(str(e), root_dir) raise AppException(exc) except Exception as e: raise AppException(e)
def setup(self): os.environ["system_file"] = "./tests/testing_data/system.yaml" Utility.load_environment() db_url = Utility.environment['database']["url"] pytest.db_url = db_url connect(**Utility.mongoengine_connection(Utility.environment['database']["url"]))
def validate(self, clean=True): if clean: self.clean() if Utility.check_empty_string( self.value) or Utility.check_empty_string(self.entity): raise ValidationError( "Entity name and value cannot be empty or blank spaces")
def __allow_access_to_bot( bot: Text, accessor_email: Text, user: Text, bot_account: int, role: ACCESS_ROLES = ACCESS_ROLES.TESTER.value, activity_status: ACTIVITY_STATUS = ACTIVITY_STATUS.INVITE_NOT_ACCEPTED. value): """ Adds bot to a user account. :param bot: bot id :param accessor_email: email id of the new member :param user: user adding the new member :param bot_account: account where bot exists :param activity_status: can be one of active, inactive or deleted. :param role: can be one of admin, designer or tester. """ bot_details = AccountProcessor.get_bot_and_validate_status(bot) Utility.is_exist(BotAccess, 'User is already a collaborator', accessor_email=accessor_email, bot=bot, status__ne=ACTIVITY_STATUS.DELETED.value) BotAccess(accessor_email=accessor_email, bot=bot, role=role, user=user, bot_account=bot_account, status=activity_status).save() return bot_details
def setup(): os.environ["system_file"] = "./tests/testing_data/tracker.yaml" Utility.load_environment() connect(**Utility.mongoengine_connection( Utility.environment['tracker']['url']), alias="history") pytest.bot = '542872407658659274'
def validate(self, clean=True): if clean: self.clean() if Utility.check_empty_string(self.name) or Utility.check_empty_string( self.type): raise ValueError( "Slot name and type cannot be empty or blank spaces") error = "" if self.type == FloatSlot.type_name: if not self.min_value and not self.max_value: self.min_value = 0.0 self.max_value = 1.0 if self.min_value < self.max_value: error = "FloatSlot must have min_value < max_value" if not isinstance(self.initial_value, int): if error: error += "\n" error = "FloatSlot initial_value must be numeric value" ValidationError(error) elif self.type == CategoricalSlot.type_name: if not self.values: raise ValidationError( "CategoricalSlot must have list of categories in values field" )
async def send_confirmation_link(mail: str): """ Sends a link to the user's mail id for account verification :param mail: the mail id of the user :return: mail id, mail subject and mail body """ email_enabled = Utility.email_conf["email"]["enable"] if email_enabled: if isinstance(mail_check(mail), ValidationFailure): raise AppException("Please enter valid email id") Utility.is_exist(UserEmailConfirmation, exp_message="Email already confirmed!", email__iexact=mail.strip()) if not Utility.is_exist(User, email__iexact=mail.strip(), status=True, raise_error=False): raise AppException( "Error! There is no user with the following mail id") user = AccountProcessor.get_user(mail) token = Utility.generate_token(mail) link = Utility.email_conf["app"]["url"] + '/verify/' + token return mail, user['first_name'], link else: raise AppException("Error! Email verification is not enabled")
def add_account(name: str, user: str): """ adds a new account :param name: account name :param user: user id :return: account id """ if Utility.check_empty_string(name): raise AppException("Account Name cannot be empty or blank spaces") Utility.is_exist( Account, exp_message="Account name already exists!", name__iexact=name, status=True, ) license = { "bots": 2, "intents": 3, "examples": 20, "training": 3, "augmentation": 5 } return Account(name=name.strip(), user=user, license=license).save().to_mongo().to_dict()
def get_connection_delete_history(): os.environ["system_file"] = "./tests/testing_data/system.yaml" Utility.load_environment() connect(**Utility.mongoengine_connection(Utility.environment['database'] ["url"])) os.environ["system_file"] = "./tests/testing_data/tracker.yaml" Utility.load_environment()
def add_integration(name: Text, bot: Text, user: Text, role: ACCESS_ROLES, iat: datetime = datetime.utcnow(), expiry: datetime = None, access_list: list = None): integration_limit = Utility.environment['security'].get( 'integrations_per_user') or 2 current_integrations_count = Integration.objects( bot=bot, status__ne=INTEGRATION_STATUS.DELETED.value).count() if current_integrations_count >= integration_limit: raise AppException('Integrations limit reached!') Utility.is_exist( Integration, 'Integration token with this name has already been initiated', name=name, bot=bot, status__ne=INTEGRATION_STATUS.DELETED.value) Integration(name=name, bot=bot, user=user, role=role, iat=iat, expiry=expiry, access_list=access_list, status=INTEGRATION_STATUS.ACTIVE.value).save()
def test_initiate_apm_client_with_url_present(self, monkeypatch): monkeypatch.setitem(Utility.environment["elasticsearch"], 'enable', True) monkeypatch.setitem(Utility.environment["elasticsearch"], 'service_name', "kairon") monkeypatch.setitem(Utility.environment["elasticsearch"], 'apm_server_url', "http://localhost:8082") client = Utility.initiate_apm_client_config() assert client == { "SERVER_URL": "http://localhost:8082", "SERVICE_NAME": "kairon", 'ENVIRONMENT': "development" } monkeypatch.setitem(Utility.environment["elasticsearch"], 'secret_token', "12345") client = Utility.initiate_apm_client_config() assert client == { "SERVER_URL": "http://localhost:8082", "SERVICE_NAME": "kairon", 'ENVIRONMENT': "development", "SECRET_TOKEN": "12345" }
def validate(self, clean=True): if not self.title or not self.payload: raise ValidationError("title and payload must be present!") elif Utility.check_empty_string( self.title) or Utility.check_empty_string( self.payload.strip()): raise ValidationError( "Response title and payload cannot be empty or blank spaces")
def remove_member(bot: Text, accessor_email: Text): Utility.is_exist(BotAccess, 'Bot owner cannot be removed', accessor_email=accessor_email, bot=bot, status__ne=ACTIVITY_STATUS.DELETED.value, role=ACCESS_ROLES.OWNER.value) AccountProcessor.remove_bot_access(bot, accessor_email=accessor_email)
def validate_password(cls, v, values, **kwargs): from kairon.shared.utils import Utility try: Utility.valid_password(v.get_secret_value()) except AppException as e: raise ValueError(str(e)) return v
def validate(self, clean=True): if clean: self.clean() if not Utility.check_empty_string(self.value) and self.type != 'slot': raise ValidationError("Value is allowed only for slot") if Utility.check_empty_string( self.name) and self.type != 'active_loop': raise ValidationError("Empty name is allowed only for active_loop")
def init_connection(self): os.environ["system_file"] = "./tests/testing_data/system.yaml" Utility.load_environment() Utility.load_email_configuration() connect(**Utility.mongoengine_connection( Utility.environment['database']["url"])) pytest.bot = 'test' yield None shutil.rmtree(os.path.join('training_data', pytest.bot))
def validate(self, clean=True): from kairon.shared.data.utils import DataUtility Utility.validate_channel_config(self.connector_type, self.config, ValidationError) if self.connector_type == "telegram": webhook_url = DataUtility.get_channel_endpoint({ 'bot': self.bot, 'user': self.user, 'connector_type': self.connector_type }) Utility.register_telegram_webhook(Utility.decrypt_message(self.config['access_token']), webhook_url)
def validate(self, clean=True): if (Utility.check_empty_string(self.email) or Utility.check_empty_string(self.first_name) or Utility.check_empty_string(self.last_name) or Utility.check_empty_string(self.password)): raise ValidationError( "Email, FirstName, LastName and password cannot be empty or blank space" ) elif isinstance(email(self.email), ValidationFailure): raise ValidationError("Please enter valid email address")
def delete_channel_config(connector_type: Text, bot: Text): """ Delete a particular channel configuration for bot :param connector_type: channel name :param bot: bot id :return: None """ Utility.hard_delete_document([Channels], bot=bot, connector_type=connector_type)
def test_get_action_url(self, monkeypatch): actual = Utility.get_action_url({}) assert actual.url == "http://localhost:5055/webhook" actual = Utility.get_action_url( {"action_endpoint": { "url": "http://action-server:5055/webhook" }}) assert actual.url == "http://action-server:5055/webhook" monkeypatch.setitem(Utility.environment['action'], "url", None) actual = Utility.get_action_url({}) assert actual is None
def check(cls, values): from kairon.shared.utils import Utility if Utility.check_empty_string(values.get('key')): raise ValueError("key cannot be empty") if values.get('parameter_type' ) == ParameterChoice.slot and Utility.check_empty_string( values.get('value')): raise ValueError("Provide name of the slot as value") return values
def validate(self, clean=True): if clean: self.clean() if Utility.check_empty_string(self.name) or Utility.check_empty_string( self.pattern): raise ValidationError( "Regex name and pattern cannot be empty or blank spaces") else: try: re.compile(self.pattern) except Exception: raise AppException("invalid regular expression " + self.pattern)
def start_training(bot: str, user: str, token: str = None): """ prevents training of the bot, if the training session is in progress otherwise start training :param reload: whether to reload model in the cache :param bot: bot id :param token: JWT token for remote model reload :param user: user id :return: model path """ exception = None model_file = None training_status = None apm_client = None if Utility.environment.get('model') and Utility.environment['model'][ 'train'].get('event_url'): Utility.train_model_event(bot, user, token) else: try: apm_client = Utility.initiate_fastapi_apm_client() if apm_client: elasticapm.instrument() apm_client.begin_transaction(transaction_type="script") model_file = train_model_for_bot(bot) training_status = MODEL_TRAINING_STATUS.DONE.value agent_url = Utility.environment['model']['agent'].get('url') if agent_url: if token: Utility.http_request( 'get', urljoin(agent_url, f"/api/bot/{bot}/model/reload"), token, user) except Exception as e: logging.exception(e) training_status = MODEL_TRAINING_STATUS.FAIL.value exception = str(e) finally: if apm_client: apm_client.end_transaction(name=__name__, result="success") ModelProcessor.set_training_status( bot=bot, user=user, status=training_status, model_path=model_file, exception=exception, ) return model_file
def test_initiate_apm_client_env_not_present(self, monkeypatch): monkeypatch.setitem(Utility.environment["elasticsearch"], 'enable', True) monkeypatch.setitem(Utility.environment["elasticsearch"], 'env_type', None) assert Utility.initiate_apm_client_config() is None
def test_download_csv(self): file_path, temp_path = Utility.download_csv( {"conversation_data": [{ "test": "test_val" }]}, None) assert file_path.endswith(".csv") assert "tmp" in str(temp_path).lower()
def validate(self, clean=True): if clean: self.clean() if Utility.check_empty_string(self.name): raise ValidationError( "Utterance Name cannot be empty or blank spaces")
def test_extract_db_config_without_login(self): config = Utility.extract_db_config("mongodb://localhost/test") assert config['db'] == "test" assert config['username'] is None assert config['password'] is None assert config['host'] == "mongodb://localhost" assert len(config["options"]) == 0