diff --git a/env_secrets/local_daniel.env b/env_secrets/local_daniel.env index 2a0d57f3..9a1c2df5 100644 Binary files a/env_secrets/local_daniel.env and b/env_secrets/local_daniel.env differ diff --git a/env_secrets/prod-azure.json b/env_secrets/prod-azure.json index 453296ed..edb6cff1 100644 Binary files a/env_secrets/prod-azure.json and b/env_secrets/prod-azure.json differ diff --git a/server/requirements/requirements-dev.txt b/server/requirements/requirements-dev.txt index a66e01e8..cfec2bd4 100644 --- a/server/requirements/requirements-dev.txt +++ b/server/requirements/requirements-dev.txt @@ -43,6 +43,8 @@ azure-storage-blob==12.17.0 # django-storages backcall==0.2.0 # via ipython +bcrypt==4.0.1 + # via paramiko beautifulsoup4==4.11.2 # via wagtail black==23.7.0 @@ -69,6 +71,7 @@ cffi==1.15.1 # via # argon2-cffi-bindings # cryptography + # pynacl cfgv==3.3.1 # via pre-commit charset-normalizer==3.2.0 @@ -95,6 +98,7 @@ cryptography==41.0.3 # azure-identity # azure-storage-blob # msal + # paramiko # pyjwt decorator==5.1.1 # via @@ -336,6 +340,8 @@ packaging==23.1 # marshmallow # pytest # pytest-sugar +paramiko==3.3.1 + # via -r requirements.in parso==0.8.3 # via jedi pathspec==0.11.2 @@ -400,6 +406,8 @@ pylint-django==2.5.3 # via -r requirements-dev.in pylint-plugin-utils==0.8.2 # via pylint-django +pynacl==1.5.0 + # via paramiko pyproject-hooks==1.0.0 # via build pytest==7.4.0 diff --git a/server/requirements/requirements.in b/server/requirements/requirements.in index ae9264d7..76388ad2 100644 --- a/server/requirements/requirements.in +++ b/server/requirements/requirements.in @@ -40,6 +40,7 @@ python-json-logger concurrent-log-handler python-dateutil pycryptodome +paramiko wagtail>=4 wagtail-factories>=4 diff --git a/server/requirements/requirements.txt b/server/requirements/requirements.txt index 1261d7d5..a0818296 100644 --- a/server/requirements/requirements.txt +++ b/server/requirements/requirements.txt @@ -34,6 +34,8 @@ azure-storage-blob==12.17.0 # via # -r requirements.in # django-storages +bcrypt==4.0.1 + # via paramiko beautifulsoup4==4.11.2 # via wagtail boto3==1.28.23 @@ -52,6 +54,7 @@ cffi==1.15.1 # via # argon2-cffi-bindings # cryptography + # pynacl charset-normalizer==3.2.0 # via requests click==8.1.6 @@ -67,6 +70,7 @@ cryptography==41.0.3 # azure-identity # azure-storage-blob # msal + # paramiko # pyjwt defusedxml==0.7.1 # via willow @@ -211,6 +215,8 @@ packaging==23.1 # via # gunicorn # marshmallow +paramiko==3.3.1 + # via -r requirements.in pillow==10.0.0 # via # -r requirements.in @@ -234,6 +240,8 @@ pycryptodome==3.18.0 # via -r requirements.in pyjwt[crypto]==2.8.0 # via msal +pynacl==1.5.0 + # via paramiko python-dateutil==2.8.2 # via # -r requirements.in diff --git a/server/vbv_lernwelt/edoniq_test/result_import/__init__.py b/server/vbv_lernwelt/edoniq_test/result_import/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/server/vbv_lernwelt/edoniq_test/result_import/edoniq_sftp_connection.py b/server/vbv_lernwelt/edoniq_test/result_import/edoniq_sftp_connection.py new file mode 100644 index 00000000..8bc6ae72 --- /dev/null +++ b/server/vbv_lernwelt/edoniq_test/result_import/edoniq_sftp_connection.py @@ -0,0 +1,63 @@ +import csv +import os +from io import StringIO + +import paramiko +import structlog + +logger = structlog.get_logger(__name__) + + +def _create_edoniq_sftp_client(): + client = paramiko.SSHClient() + client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + + # Get the private key from the environment variable and convert it to a key object + private_key_env_var_name = "IT_EDONIQ_SFTP_PRIVATE_KEY" + private_key_str = os.environ.get(private_key_env_var_name).replace("\\n", "\n") + if not private_key_str: + logger.warn( + "Environment variable not set or empty", + env_var=private_key_env_var_name, + label="edoniq_import", + ) + raise ValueError( + f"Environment variable {private_key_env_var_name} not set or empty." + ) + + private_key_file = StringIO(private_key_str) + private_key = paramiko.Ed25519Key.from_private_key(private_key_file) + + client.connect( + hostname="217.20.192.94", + port=20041, + username="sftpuser", + pkey=private_key, + ) + + return client.open_sftp(), client + + +class EdoniqSftpClient: + def __enter__(self): + (self.sftp_client, self.ssh_client) = _create_edoniq_sftp_client() + return self.sftp_client + + def __exit__(self, exc_type, exc_value, exc_traceback): + # self.sftp_client.close() + self.ssh_client.close() + + +def load_edoniq_test_results_csv_data(): + with EdoniqSftpClient() as sftp_client: + with sftp_client.file("/upload/PruefungResultate.csv", "r") as file: + data = file.read().decode("utf-8") + return data + + +if __name__ == "__main__": + csv_data = load_edoniq_test_results_csv_data() + csv_reader = csv.reader(StringIO(csv_data), delimiter=";") + for i, row in enumerate(csv_reader): + if len(row) > 4 and row[4] == "AG 2023 A" and row[5] == "de_üK1_BA_KN": + print(row) diff --git a/server/vbv_lernwelt/edoniq_test/tests/edoniq_pruefung_resultate.csv b/server/vbv_lernwelt/edoniq_test/tests/edoniq_pruefung_resultate.csv new file mode 100644 index 00000000..ab14dc4d --- /dev/null +++ b/server/vbv_lernwelt/edoniq_test/tests/edoniq_pruefung_resultate.csv @@ -0,0 +1,6 @@ +Benutzer Login;Benutzer Name;Benutzer Vorname;Korrespondenzsprache;OE;Sequenztitel;Sequenz ID;letztes Datum der Durchführung des Kandidaten;Zeitstempel Beginn;Bearbeitungsdauer;erreichte Punkte absolut ; erreichbares Punktetotal absolut;erreichte Punkte;Bestehensgrenze prozentual;Bestanden-/Nicht-Bestanden Status;Note;prozentualer Durchschnitt der Versuche dieses Kandidaten;prozentualer Durchschnitt aller Kandidaten + ; +cc36ad95-d09c-4187-b1d4-689ada3ef497;Sommer;Diego;de;AG 2023 A;de_üK1_BA_KN;1688059890497;06.09.2023;06.09.2023 18:48;00:17:10.4650;21.25 ; 29;73.28;60;Bestanden;;73.28;65.91 +58fdb8e2-881d-48fd-8df9-05f31586e909;Demirel;Beyzanur;de;AG 2023 A;de_üK1_BA_KN;1688059890497;07.09.2023;07.09.2023 19:00;00:17:49.8550;12.23 ; 29;42.16;60;Nicht bestanden;;42.16;65.91 +19d4e374-7300-45cc-a420-bebe184c5c4e;Appert;Mascha;de;AG 2023 A;de_üK1_BA_KN;1688059890497;10.09.2023;10.09.2023 10:48;00:18:22.9710;17.62 ; 29;60.76;60;Bestanden;;60.76;65.91 +29610d7c-ed48-43b8-ab71-ce0e726aada4;Gianformaggio;Ylaria;de;AG 2023 A;de_üK1_KO_Testlauf;1686325621487;10.09.2023;10.09.2023 16:32;00:00:00.0000;0.00 ; 15;0.00;60;Begonnen;;38.11;55.30 \ No newline at end of file