diff --git a/petisco/persistence/elastic/elastic_connection.py b/petisco/persistence/elastic/elastic_connection.py index 84e6bc59..dbaff6cb 100644 --- a/petisco/persistence/elastic/elastic_connection.py +++ b/petisco/persistence/elastic/elastic_connection.py @@ -32,8 +32,8 @@ def create_local(): @staticmethod def from_environ(): return ElasticConnection.create( - os.getenv("ELASTIC_USERNAME", "document-writer"), - os.getenv("ELASTIC_PASSWORD", "document-writer"), + os.getenv("ELASTIC_USERNAME", ""), + os.getenv("ELASTIC_PASSWORD", ""), os.getenv("ELASTIC_HOST", "localhost"), - os.getenv("ELASTIC_PORT", "443"), + os.getenv("ELASTIC_PORT", "9200"), ) diff --git a/petisco/persistence/sql/mysql/mysql_database.py b/petisco/persistence/sql/mysql/mysql_database.py index 42188f1e..5c0bd055 100644 --- a/petisco/persistence/sql/mysql/mysql_database.py +++ b/petisco/persistence/sql/mysql/mysql_database.py @@ -1,5 +1,7 @@ from typing import List, Callable +from sqlalchemy.orm import scoped_session + from petisco.persistence.interface_database import IDatabase from petisco.persistence.sql.mysql.mysql_connection import MySqlConnection from petisco.persistence.persistence_models import PersistenceModels @@ -89,7 +91,7 @@ def get_model_names(self) -> List[str]: return list(self.persistence_models.get_models_names().keys()) def get_session(self): - return self.session_maker() + return scoped_session(self.session_maker)() def get_session_scope(self) -> Callable: return sql_session_scope_provider(self.get_session()) diff --git a/petisco/persistence/sql/sql_executor.py b/petisco/persistence/sql/sql_executor.py new file mode 100644 index 00000000..82089782 --- /dev/null +++ b/petisco/persistence/sql/sql_executor.py @@ -0,0 +1,28 @@ +from typing import Callable, List + +from sqlalchemy import text + + +class SqlExecutor: + def __init__(self, session_scope: Callable): + self.session_scope = session_scope + + def _get_command(self, statement: str): + command = text(statement.rstrip("\n")) + return command + + def execute_from_filename(self, filename: str): + with open(filename) as file: + statements = file.read().split(";") + self.execute_statements(statements) + + def execute_statement(self, statement: str): + with self.session_scope() as session: + command = self._get_command(statement) + session.execute(command) + + def execute_statements(self, statements: List[str]): + with self.session_scope() as session: + for statement in statements: + command = self._get_command(statement) + session.execute(command) diff --git a/petisco/persistence/sql/sqlite/sqlite_database.py b/petisco/persistence/sql/sqlite/sqlite_database.py index b6123db3..dae6a1d0 100644 --- a/petisco/persistence/sql/sqlite/sqlite_database.py +++ b/petisco/persistence/sql/sqlite/sqlite_database.py @@ -1,6 +1,8 @@ import os from typing import List, Callable +from sqlalchemy.orm import scoped_session + from petisco.persistence.interface_database import IDatabase from petisco.persistence.persistence_models import PersistenceModels from petisco.persistence.sql.sql_session_scope_provider import ( @@ -83,7 +85,7 @@ def get_model_names(self) -> List[str]: return list(self.persistence_models.get_models_names().keys()) def get_session(self): - return self.session_maker() + return scoped_session(self.session_maker)() def get_session_scope(self) -> Callable: return sql_session_scope_provider(self.get_session()) diff --git a/petisco/public_api.py b/petisco/public_api.py index a1bbb696..8b558e0d 100644 --- a/petisco/public_api.py +++ b/petisco/public_api.py @@ -276,6 +276,7 @@ from petisco.persistence.sql.mysql.mysql_connection import MySqlConnection from petisco.persistence.sql.mysql.mysql_database import MySqlDatabase from petisco.persistence.sql.sql_repository import SqlRepository + from petisco.persistence.sql.sql_executor import SqlExecutor sql = [ "SqlAlchemyPersistence", @@ -288,6 +289,7 @@ "MySqlConnection", "MySqlDatabase", "SqlRepository", + "SqlExecutor", ] except (RuntimeError, ImportError): sql = [] diff --git a/petisco/security/token_manager/jwt_token_builder.py b/petisco/security/token_manager/jwt_token_builder.py index aa821fef..0b93abf4 100644 --- a/petisco/security/token_manager/jwt_token_builder.py +++ b/petisco/security/token_manager/jwt_token_builder.py @@ -21,5 +21,5 @@ def build( "cli": client_id.value, "sub": user_id.value if user_id else None, } - token = jwt.encode(payload, key, algorithm="RS256").decode("utf-8") + token = jwt.encode(payload, key, algorithm="RS256") return token diff --git a/requirements/requirements.txt b/requirements/requirements.txt index eaa61b9c..c374c224 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -3,7 +3,7 @@ requests==2.24.0 dataclasses==0.7;python_version<"3.7" dataclasses-json==0.5.2 backports-datetime-fromisoformat>=1.0.0;python_version<"3.7" -pyjwt>=1.7.1 +pyjwt==2.0.0 cryptography>=2.1.4 py-healthcheck==1.7.2 APScheduler==3.6.3 diff --git a/tests/modules/persistence/integration/test_sql_executor.py b/tests/modules/persistence/integration/test_sql_executor.py new file mode 100644 index 00000000..ee75b11e --- /dev/null +++ b/tests/modules/persistence/integration/test_sql_executor.py @@ -0,0 +1,62 @@ +import pytest + +from petisco import SqliteDatabase, SqliteConnection, Persistence, SqlExecutor +from tests.modules.persistence.mother.model_filename_mother import ModelFilenameMother + + +@pytest.mark.integration +def test_should_sql_executor_insert_statement(): + filename = ModelFilenameMother.get("sql/persistence.sql.models.yml") + connection = SqliteConnection.create( + server_name="sqlite", database_name="petisco.db" + ) + database = SqliteDatabase( + name="sqlite_test", connection=connection, model_filename=filename + ) + + persistence = Persistence() + persistence.add(database) + persistence.create() + + session_scope = Persistence.get_session_scope("sqlite_test") + sql_executor = SqlExecutor(session_scope) + + sql_executor.execute_statement( + 'INSERT INTO Client (client_id,name) VALUES ("65dd83ef-d315-417d-bfa8-1ab398e16f02","myclient")' + ) + sql_executor.execute_statement( + 'DELETE FROM Client WHERE client_id=="65dd83ef-d315-417d-bfa8-1ab398e16f02";' + ) + + persistence.clear_data() + persistence.delete() + Persistence.clear() + + +@pytest.mark.integration +def test_should_sql_executor_from_filename_with_statement(): + filename = ModelFilenameMother.get("sql/persistence.sql.models.yml") + connection = SqliteConnection.create( + server_name="sqlite", database_name="petisco.db" + ) + database = SqliteDatabase( + name="sqlite_test", connection=connection, model_filename=filename + ) + + persistence = Persistence() + persistence.add(database) + persistence.create() + + session_scope = Persistence.get_session_scope("sqlite_test") + sql_executor = SqlExecutor(session_scope) + + sql_executor.execute_from_filename( + "tests/modules/persistence/sql/client_create.sql" + ) + sql_executor.execute_from_filename( + "tests/modules/persistence/sql/client_delete.sql" + ) + + persistence.clear_data() + persistence.delete() + Persistence.clear() diff --git a/tests/modules/persistence/sql/client_create.sql b/tests/modules/persistence/sql/client_create.sql new file mode 100644 index 00000000..ed3bc572 --- /dev/null +++ b/tests/modules/persistence/sql/client_create.sql @@ -0,0 +1,2 @@ +INSERT INTO Client (client_id,name) VALUES ("65dd83ef-d315-417d-bfa8-1ab398e16f02","myclient-bad"); +UPDATE Client SET name="myclient" WHERE client_id="65dd83ef-d315-417d-bfa8-1ab398e16f02" \ No newline at end of file diff --git a/tests/modules/persistence/sql/client_delete.sql b/tests/modules/persistence/sql/client_delete.sql new file mode 100644 index 00000000..e978c034 --- /dev/null +++ b/tests/modules/persistence/sql/client_delete.sql @@ -0,0 +1 @@ +DELETE FROM Client WHERE name=="myclient" \ No newline at end of file