From 884fc8d5b02bd84ab96efe5f8591653d6d211507 Mon Sep 17 00:00:00 2001 From: Daniel Egger Date: Tue, 19 Sep 2023 13:45:41 +0200 Subject: [PATCH] VBV-488: create edoniq sftp client --- env_secrets/local_daniel.env | Bin 539 -> 971 bytes env_secrets/prod-azure.json | Bin 4698 -> 5192 bytes server/requirements/requirements-dev.txt | 8 +++ server/requirements/requirements.in | 1 + server/requirements/requirements.txt | 8 +++ .../edoniq_test/result_import/__init__.py | 0 .../result_import/edoniq_sftp_connection.py | 63 ++++++++++++++++++ .../tests/edoniq_pruefung_resultate.csv | 6 ++ 8 files changed, 86 insertions(+) create mode 100644 server/vbv_lernwelt/edoniq_test/result_import/__init__.py create mode 100644 server/vbv_lernwelt/edoniq_test/result_import/edoniq_sftp_connection.py create mode 100644 server/vbv_lernwelt/edoniq_test/tests/edoniq_pruefung_resultate.csv diff --git a/env_secrets/local_daniel.env b/env_secrets/local_daniel.env index 2a0d57f30ff79c98c92fdc9e2bb20822e31df6f4..9a1c2df5cf987af71f5c5ecdc61ca75f7e7eadf9 100644 GIT binary patch literal 971 zcmV;+12p^qM@dveQdv+`08Z*`Y>&>Vgm1R%VO{i^*z)Z0dLk(`U1m&U{Cr5w8DyYo z_HeQ{eB%sS-kKDa{a_f$xf(~M7dzN}d*O;cgTsG3E+1#`qkCRv{%Q@)P17l5{Y0qU zWh@`Bbd8lXIQgAze&TCjgw%vhaP(x^l7(pDG5p8lb}6y7-WO_CF7XXhuL^dmOq)~_ z1hznpR?3Hg(^zL{Dq$qTDqE36s?yaC=JaQ1&ipPr%+Y^T9GZi1^zi7$YNgL1)m_*? zO6QvRDxdKzDx@zoUU`|v(g)2Vy?OfTkSX+h;f>Vm`*TrVfmj_3GI zM+keLa1x}m`|?V2FNW)glhs$-%a_hD)W&95>5W0KuGg>$ekiOTkr69C8vm#@@kd%? z1lhgrsv`bh(ELAb$xe-hok|T5(0;(^ntDZQh?F#)f zi0n%o6yd97>MWiqJqY!rE~3g!;t(O7a*nWi0h1{=9vb2W8^Gs~_IpRp$*sirn$NFN zL8#ME>xzalEYgA1nFQ_gx@Ob5kC3=eITw1w3JNOS$H8{QYsGWS+Gtb{><3?kAsx$t z^*`3MN=_{S;z{`sg8^7$J&o>J{zsOk}5RB!fZ;mb!1K_45G_f3u+;+ zP&K~Lc)+IS_NuuqkyFOFcA{BrB=6e9s(DwTJptvLCns79DnA;+kT%98S(8_F%0{s0 zkv#>2o>dt$7kp{!LViE(q)C(6roUR7Frh} zXLvk{KduZOhLb93rRHqg9PI-0 z1dBXDjv^e?2RT#kw6QN#5-bx@$mU&w?=Tt_%#0GC+I(s!mu>(NDL}MweEI=)x9n+2h^4pFUp2 z#(ta46n!d|-pIJG+~O^*4>Y8|4)v1_0v2Z)U>+Un=xyuRkb!Qp@ zc&wh=Ebl>ZvbSmDPx96krot0hq&|X77o=paVI^?TN4e=BO9B&dpb{njS)XX%S!@^A zn)L)Xj?b@A<$sv-c_?a1$Y8g(hfQLR;+?;K<(xn#_>7G`N4Uh@FL2x^Af5}_a9;;n d!XV|ESBRJ9<^l0|8hLlJT1gG+eV=PM7{B*y2?GEC diff --git a/env_secrets/prod-azure.json b/env_secrets/prod-azure.json index 453296ed5ffb3b4d60dc2971cb4f872fcac0b7ae..edb6cff1c1b1691c018f1f29008214e2a71ee035 100644 GIT binary patch literal 5192 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 Cq8Gvd literal 4698 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 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