From 40b19824cea8f913f4e4ce06ec7f4be6bb5ef820 Mon Sep 17 00:00:00 2001 From: Florian Uhlig Date: Sun, 5 Oct 2025 03:08:13 +0200 Subject: [PATCH 1/6] Test --- test.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test.txt diff --git a/test.txt b/test.txt new file mode 100644 index 0000000..e69de29 From 3072c96fb9285d5194129c675579d1260d6f83b1 Mon Sep 17 00:00:00 2001 From: Florian Uhlig Date: Tue, 7 Oct 2025 08:18:33 +0200 Subject: [PATCH 2/6] changed workflows --- .github/workflows/.code-review.yml.swp | Bin 0 -> 1024 bytes .github/workflows/linters.yml | 9 +++------ .github/workflows/unit-test.yml | 9 ++++----- 3 files changed, 7 insertions(+), 11 deletions(-) create mode 100644 .github/workflows/.code-review.yml.swp diff --git a/.github/workflows/.code-review.yml.swp b/.github/workflows/.code-review.yml.swp new file mode 100644 index 0000000000000000000000000000000000000000..e796ed6fbae13b732d795a58b2322fce464cf914 GIT binary patch literal 1024 zcmYc?$V<%2S1{KzVn6}ub}9^Mr5QPy=_tZjImJa~28MbN)p{wZSk-_8_0ls-GD?&5 q%kzt}({l35i}jQ9Q&M${Qp++^%k?UAb8zY$l^6|y(GZ|T2mk<~Sr~Ny literal 0 HcmV?d00001 diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index ec345f4..c211b2f 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -1,12 +1,9 @@ name: linters - on: - workflow_run: # ← event name must be workflow_run - workflows: ["Review"] # ← exact name of your triggering workflow - types: [completed] - branches: [Development] - + push: + branches: + - Development jobs: on-success: if: ${{ github.event.workflow_run.conclusion == 'success' }} diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 423b63b..c1e9191 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -1,10 +1,9 @@ name: Unit Test on: - workflow_run: - workflows: ["linters"] - types: [completed] #requested - + push: + branches: + - main jobs: on-success: @@ -35,4 +34,4 @@ jobs: runs-on: ubuntu-latest if: ${{ github.event.workflow_run.conclusion == 'failure' }} steps: - - run: echo 'The triggering workflow failed' \ No newline at end of file + - run: echo 'The triggering workflow failed' From 6ad98fee4c052063f052e9bd098823ae5d839d8b Mon Sep 17 00:00:00 2001 From: Florian Uhlig Date: Tue, 7 Oct 2025 08:19:09 +0200 Subject: [PATCH 3/6] Test --- .github/workflows/.code-review.yml.swp | Bin 1024 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .github/workflows/.code-review.yml.swp diff --git a/.github/workflows/.code-review.yml.swp b/.github/workflows/.code-review.yml.swp deleted file mode 100644 index e796ed6fbae13b732d795a58b2322fce464cf914..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmYc?$V<%2S1{KzVn6}ub}9^Mr5QPy=_tZjImJa~28MbN)p{wZSk-_8_0ls-GD?&5 q%kzt}({l35i}jQ9Q&M${Qp++^%k?UAb8zY$l^6|y(GZ|T2mk<~Sr~Ny From 68d4fc9a36a57b701006444553e3cd86ea14e273 Mon Sep 17 00:00:00 2001 From: Florian Uhlig Date: Tue, 7 Oct 2025 08:32:52 +0200 Subject: [PATCH 4/6] Testing --- .flake8 | 4 ++ .github/workflows/linters.yml | 8 +--- .github/workflows/unit-test.yml | 10 +---- config/__pycache__/database.cpython-312.pyc | Bin 0 -> 3097 bytes database/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 1838 bytes .../flask_integration.cpython-312.pyc | Bin 0 -> 2285 bytes .../__pycache__/interface.cpython-312.pyc | Bin 0 -> 2345 bytes .../__pycache__/sqlite_db.cpython-312.pyc | Bin 0 -> 10999 bytes database/flask_integration.py | 2 +- database/interface.py | 2 +- database/sqlite_db.py | 18 ++++----- frontend/__pycache__/app.cpython-312.pyc | Bin 0 -> 12192 bytes services/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 150 bytes .../__pycache__/auth_service.cpython-312.pyc | Bin 0 -> 2673 bytes .../__pycache__/user_service.cpython-312.pyc | Bin 0 -> 4843 bytes services/user_service.py | 37 +++++++++--------- utils/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 147 bytes .../auth_decorators.cpython-312.pyc | Bin 0 -> 2198 bytes .../password_utils.cpython-312.pyc | Bin 0 -> 2067 bytes utils/__pycache__/validation.cpython-312.pyc | Bin 0 -> 3408 bytes 20 files changed, 36 insertions(+), 45 deletions(-) create mode 100644 .flake8 create mode 100644 config/__pycache__/database.cpython-312.pyc create mode 100644 database/__pycache__/__init__.cpython-312.pyc create mode 100644 database/__pycache__/flask_integration.cpython-312.pyc create mode 100644 database/__pycache__/interface.cpython-312.pyc create mode 100644 database/__pycache__/sqlite_db.cpython-312.pyc create mode 100644 frontend/__pycache__/app.cpython-312.pyc create mode 100644 services/__pycache__/__init__.cpython-312.pyc create mode 100644 services/__pycache__/auth_service.cpython-312.pyc create mode 100644 services/__pycache__/user_service.cpython-312.pyc create mode 100644 utils/__pycache__/__init__.cpython-312.pyc create mode 100644 utils/__pycache__/auth_decorators.cpython-312.pyc create mode 100644 utils/__pycache__/password_utils.cpython-312.pyc create mode 100644 utils/__pycache__/validation.cpython-312.pyc diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..a60b3be --- /dev/null +++ b/.flake8 @@ -0,0 +1,4 @@ +[flake8] +#ignore = E226,E302,E41 +max-line-length = 130 +max-complexity = 10 diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index c211b2f..31c33e5 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -5,7 +5,7 @@ on: branches: - Development jobs: - on-success: + check: if: ${{ github.event.workflow_run.conclusion == 'success' }} runs-on: ubuntu-latest steps: @@ -27,9 +27,3 @@ jobs: - name: Run pylint run: pylint frontend services utils - - on-failure: - if: ${{ github.event.workflow_run.conclusion == 'failure' }} - runs-on: ubuntu-latest - steps: - - run: echo 'The Review workflow failed' diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index c1e9191..9d7ccd1 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -6,7 +6,7 @@ on: - main jobs: - on-success: + Unit-Test: runs-on: ubuntu-latest steps: @@ -28,10 +28,4 @@ jobs: # 6. Run unit tests - name: Run pytest - run: pytest - - on-failure: - runs-on: ubuntu-latest - if: ${{ github.event.workflow_run.conclusion == 'failure' }} - steps: - - run: echo 'The triggering workflow failed' + run: pytest \ No newline at end of file diff --git a/config/__pycache__/database.cpython-312.pyc b/config/__pycache__/database.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..760518b43a557a178e18bd628818bed8759521c8 GIT binary patch literal 3097 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 literal 0 HcmV?d00001 diff --git a/database/__pycache__/flask_integration.cpython-312.pyc b/database/__pycache__/flask_integration.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9d821a4e1b366db4063e6cbe81b68966729d2b4c GIT binary patch literal 2285 zcmah~O>ERg6rSNQDEph^X-g#@gYvS)slohLqu6br1(%ub!rD2rI&m#ZQvL;Uh>J%+x3YRS~V-67rl_O zx@A*4@knIqj`|eF(vXVUn-fU{>h(o?d_S8`H1NGHQ{@8LLk9%uP@HTGR{eY(so| zykCH?zZ=97n#c3VgkI7*=mF+O-9yp?nsB(#XC1R1dA1?NazNcWX!UOJR3ATV)0rh3F2r59n$8+;>Br zID#rJ`zy+BQjgG37oZ&p^dpTUx?khq zC;lw)m~{O)%cc5En>zL^(AaC_L1HzdM)y!oTSsidrn(KB4k^*=KGV}+Mu~CU1pnAB z=*1=5_dHlL-jz%@qku9KE~iW5qU$%{;=~G}wWwiWHV7U8r-{xq?p$op&?L3)zHNz@ z7v|~@T-FGkFzPvnoW<@*u{GFY5ySKZ`>L}X*ai`z7ot#{PxC_u(LSatoW==&g zq>W%8K&t;vnwP#mJTEns%)0U4M8#sJZEiz5QrMtVN9st199@L@IbJh1+;RHor>(pJ zGSnQ80JOT*(mw@S=!6CtXM)^cKsMbyoMWAW$LpBw`oR{k6#;f!X#4GWfH*-qn~lJp z*d7o@K|mTSlrf))=mAe2FgyWR6;V0F+t-%NydRu`lOPt*-zpl}vo!U?)V;C$*B%ca zyQQuT4lfT*tZ5^w+C)#ASkd0k;XM09JGZVNO&3VM0VLmt0P+-cc$sbHP=X?DP=~gG zbrT5Kkh)V>X~PLZ=1`U=UOYaN>B}&AA@b(LDUCgUZJaRRfwT=1>32@nrZ5|iIr z#%rw*;uSgoqeb+GeCCymm5Ic*Lf`W8n>4SX8Z>~t$YxU#gRHvB%Iu3Gh48(c?WBe!D m@d6FMKu4dI$8Np5S|00_$L^hcTt2u^{HHjME3Xg;5$j*7BMN%} literal 0 HcmV?d00001 diff --git a/database/__pycache__/interface.cpython-312.pyc b/database/__pycache__/interface.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c3b58ab48abed48d70296b2f3fe603f7b537e87f GIT binary patch literal 2345 zcmbVNy>HuA5P$p>EsL@hyB`VCHmw391d6CY(4atz0F4aP3baSJ2$<(_?%A_JGaQgrrPw#$r_tV|I$6rjd zN??8c(;wZR6+(W;AJe7f%H$R(Pl!)^DIlR_OQCGb68@G0B~)!S)NC!(ZCxTVxkG&A zG4WL@J%@O>?8;EH^gmIxWUhR9dz;tYc9JsJOGBD=W8YF>I~sCzr{|^I__m++;>Zm= zbeXP|T$!v(NQM$y@`)`|#b1Yn>hs)et71nj?Py|0EA8m8qtl9CfyaPHqDIH?S4xN# zK%iBkRk}(mwAPU?LI!*~s$VT3%{aCH+9=?LcfYq$~vw`xz1=hV9~Az6`NVun28GF2^o?@Y4;EWR}&g^5`ZM8RyZg>|*G+H7Y0J;EwR+QZ*ZV_W@!}`~=>EkyHrI2L zj=6EN9+BUS+5{BxW`3*&5N4vNgUA@Nbx?WL?S zWACECablN1BKz(ams56i$ghMfdmrtnPzV6(KIVmd+3P& zxu{liptm7JQ7iA9EUcUb)?$XmW;wyM?)zKwg;<2cdj5AV?ETkCT*BZpJ$BA&^6_FS zi_sXlAjBIHeK;G}!!DKAlCD`w(KU7z91;YcP0i+@@1M>2l**#2Ey8^SkqVOM?cjXX zR(%@K{ID$=-I950CM665p7&kr0yi8751Qlfs^f&QKL}8-InMV3H^?ju4-9Ldcnifl zAh-fwC$6^RIAE7?vw{L|E`~Q3`vApY$x>Pk21rJ|*Dzqat48?AP(mOWb@dZiY_;@Zg7$I=VY?wG2S>bm!b}u8QJW0e03@C*+xcovq1cX zWfE7nsOGL^aK&wV42M?qkL&5M-;4IL_J~G_mWc+;HszJ^MK%bx*eBqQ-@614`l%vG Z(hJgjLAFlF*57(lGM_5{5O|5i{{pWd5H$b* literal 0 HcmV?d00001 diff --git a/database/__pycache__/sqlite_db.cpython-312.pyc b/database/__pycache__/sqlite_db.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8044406fd9ca17b71756b588520e4479df63efc2 GIT binary patch literal 10999 zcmeHNTWlLwdY<9T@FI>x>SEpH9b1-cI+A5uzDkk3Bt>0diFPDv6Kfv`iZik(Q=~F8 ztRhA-j75sti!5Se7m$IXtv4_0)NP?)+eQJ3tt7t~SfHR924ZGiG(gh=`%(~*3K;fF z|1&pUG^XucKlGtT;yGu|{mlIT_kaJH`E7Z583y6$ufLnQ(}ZFFfiAQ_shOQ5WL7X1 zWAP|9sigQM4%eorX^xmAa8yP_$vJA0nln$D=PZ*JC?i=aYMrx9+HlN-aoB8)HgGQG z><@9}YLYf#gBWZ62xBdr?IEF-mM`Ki>+jKp--Sz5G#(B`U4%rqV~Y~m9|?<+_42$J ziN`|G-=mSBQDuKf3{8auZa5}#{B$VHg_XgS*s5Oa{1;?aU|nb@lO`6QBv=ziPMcWb zBXW{rNzOc5k>63tLp=rcR^}a>3 zYoAmx{?155$Za&J*aWOH%@rl?qhUIuh>(Hs+Ov%Dd z1?NNJOxToncTgTZvz_A*tzb*|5*E~}MfGW7*h94pYW3cW@X-7&g118*k6KFRpz@qe z5-D)eX}Lx~?HT6TnXZ}m9M?6Sn2AQNbVv z6MQVJN-QeFEbx=}{V%Y-6-?CYmatiUhjL3fV)2J+DPL#YVwTLc)^d07o2??6Ne;7` z1ZxG5!dS8%=M_Pg1z8r&TG=eE<#K6Wt%0m3Va~rHAF3-dUT^L>=8fgd&7kFsdmHUG zXnXxWv-`9@xs;_eY{Aj}F?bqAvm1_Neq$q9-q=Xi+(=@rw(D604n={r9P=ZNpNhm-zznG@9FN67BLR^It|<$- z@IwIX%J2*qz8(}pb6imAELp_J92ZZB63ucVbP0-!^PG^ZyE5h;9Cb6ZanQ9;G&l#- z_r2>LNj9hz!eT5u!^dOsgwW@|JT?kdwQ5y31k(hCNRsP2as2r4WW8E0a&z-RL5%ZU z->7f&^4Qhn5kI$};vSP*G7|<+6gifej`QjsUFDKxCM1MJk>|@{Lp-u#l10ImZpor{ zmN80lTyc+$`-1&G??~Y472mj2p%i#8kNDlAa7~QG7bH6$UkHL-g7qv)7VZNsoDez5 z9F1SQ#_|YNZN5?HSoocKmYOe=}TMafBZ>X$FG9F3}&1)EA(ADbMSDczWGVZq3xDaTP>&l zeqsCU=ob99jPBZ~_KI8mpIo|qDNP^TrLmLezi9frNh#T;4{p&1)AX@#X(wu-TyN7y zx9Fp(xBAnxFJn|OkfsL>E4*pC->|}$rU#zTRiBL99!WKzR^K|RKl$+Xhue;}Ek|3* z+QwJHmi+}Fjfjj4(!YVs3T8uapaV4&sX;SN%ebh6#jHkxv__D!VBBVPSj|=ZIrbN( zoT@Dnt(d4o^&yPkzii4I7g@Waz?zm!g=72#Xw|amhG_v`z&;?ZVhgy7OdcHuI~EB= zBLdiIkzpe*R>$OiucD41(qdebcg;ZdFv<3TP$a5Us)A+M&hIkw2Vu251Cc~VVxS*r z1Cq`6L70>Imqc+qALqf2Be|7GG@OKU0=n-Eqlhry2p7rPBC%B`ZihM{0MSh>OH#I~ zOm*FM_2I4R!(UaqZuO%_4q}yRJhxW!&&^*puT`Y#2fwC=o<4EZe~+1LRhmpRxz`V@ zSEm|~oMhNEjl_8{m&ZUh8FMS&%k z@Islr3aeViZ{Uk2CC!svDuEvIco?V~_vo)mi>{2b{$#5nECm=HjSB@3ojl+}qQ``x zA_Ba1PnRCXW##K(>O2IeP;0PjsPq7e+8~lF3n4xRW4KJR81qM~6Q7}$0WZaD{^X9-mMOh8-zJ9nA87u)EydD@9hvfgum*gQZ%zLWyI z3?`TGS)|@YL5EQj2)fA_KyzXTW0Vx}Jn=IU;5@*UXG7p$6twl=*dkdZ-ust{yz!01 zn^+r^9S^s4++9T zoM(eT$Yu)rm!43ib-|Fx1crf!1>B=on10`YdtxNOcqhijV7EcNrh`e$gN@|aS8UI? z_S~ps6MD`JoI}7sawl4o^g!YMyWrF9SEciCiPE1AOyUWoJj4?v*d zB0e`45f#8X1SK+H@d!})qY$}B1+fmJf@3I>v5SNpdfp0pRVqsfqGuPB7nfAgQuFhV z?P+lyMi6d8bQ1%rwe4u#arG zth^#yiuTm89 zfDmz0#M9(3Yv8Vf?e{F3^S}{#6GZ`Rzqt?`VJ8NTcy3GheFb_;mU zwS^TOD_D_{t801P6#<;fD=L8Vm#j{Qb8E83&n37RBP+Y=A#<^$ci2Df8w((Wy{w=# zb3_xx4n`Km4yHg9UCfW%BNM)H=E%hk2K~EK1W~br5fb4rCkWGtXmqiM2_z57Q_8jA zYBSRcjX%OB=A)4?V3!MUWFT2*2sA*4$`v{<;{<{i9x;|YY(a>^qZ=$$po70_d_-K7 zNf!SWDzx(PXmlzRzMcaimqo#!6R77&6m_Gh2#%1cM{oo|K_q(~-Xt4~2vuI)JJ3=1 z7NU|URH>s-#yOFxY`Ay&erL*ge3v2sjQ~N4(5UhBD!2M>s=hBxUjTO_Tccyl)7@&! zS*Q4v-(!TW0Rb3*TdL*aI=&{Pnl%4(^!Dh-mw#7XpQZJ_&v)%IrV)8g$;s6dtF5Vq zGimxP@@nN?GPqfw)$=?+d?uWRO@7+vK7nnVsP^^(S3BaxiOmkudjWfd(@^rL+~qw( zJUT<6d@q5@FI4qAiGuT3-Q^vUU744_891IL;fw%CAzlP$)B2evKp9aA%9a5(dApc9 z-yQIQ`EMkjczA>Ky4@@6( z(Vx!~;Alr72~&$oiyr1Pg(fJ*UgikaX-*8!#ABR9vhZp|<^_s|GH{P&uJD;zQBzq% zb>)-@IFeEb1G0m%erl8f9V(&y1g92*GIZ^s40~G4z!<_Eh)OD}Jx^JuGL^M=teT!y zH>`Bs?fR;!^_KS=ru7%6?h(H@|DYyCcjhU|AH*DXWae5>hMKn^3iB{0(W7riqF|F*$pfuTWZ}9)?G3 z7Y@4+H{xYert1jbhstD9U92ND`5K@NrX5}A%-X2YB8>TZn!^eC8$12zpLo@hgr@k!G?T{N%vE^>}{ZlFW@Jpsqm#jqrzJRVz%E1$Gvw|a{zP(3COc9sk(Q$vWNu7|@ z4w&TkjA$Bo71NZnP0I0;J}bC#pV^BQ7ddRm4_gSw6S4ebp`%cdbIbTMaH;ubGUR8q?wx|V00Y^L(yeP7CXRI_fH zzm}gr^tV?5*;azkn$I<*VrboAbF$ zrF<^gCwsB>BaiI$wVwp+dR^_O@-W6&`-?0s_@pHdlVt7R>&cZ|S5EsA=m2U0RF8>1 z`bR!Or}yTJ+%-atwk& zsVs;-21!Iwo(=}z2gp`yEWscf4?{5_z-JoB>L`a-WnTSj6a_!g3uwLrMaLnM$f0{QTYN9Ih9?2r*M5PgJwLwd6$LG8a! z>|l^&%POh%`*qs~y0;E=?_hAT({7=vcB-t@5WZ7WOEqPW@1vUTd$SlMtAw1aD_4*E zcTi#Wm;)LJSqzc~AFPpU-4Bv zPb(usvSwYc{<3@rgKW0B8oIS+F-X>xiE(if*lBi)deC@(7J28}P#s`HL5R1g?1oMe+?D zM>%wsBj4m_*0+_1eu2LVWq_=ha1J7Pw~6Dw!z$qa->{~C$J)2B_W#6=d~0jGRkv+x e+_E*^JNK3C&`tBMnK$80seSGLgQ1K(^8W&tSy%!zElv zci2tSmPB2$K3q@J)`TbN4SQ+YmS{*eh8toNHiz?VSlnE+>#8011w`= zL}q56KG5^wek0PgyNps`)j&r2G^+beixsXq~Hg-!8bs?U5ZiEtHxB_h)rF zy|{hmHNC9-6zWIdMew|!)JsbnUQpVIrO=Q2(^7-sPO)?5bh&jsrI&x(#4zEmFfaJt zVZz-|(<^rC;|uQ+cgxJ+5JPl2zVXdsi?E|cz0eEl@%mRn zz0Ml-247HbXGOiP8uf-=P_O&B?`#ov)u_J*>c_O1tc-;oyHuxz>5ezId$Ih|Ap+Dfuc+jNU zg{Umb@ua9aFc!pw91Yr3%b7$}npG{=;W4e+i73R07?V{G5mSOlBC?pgk${@2jfmgP zh?1<@BvF#$>6B{AkVNEqngm(3{!~bsr8BUR6G^I@xWLG)dTP8 zjBI2;85#!^W0H_Vt&iC;FQp5X@dlyAX}ao zU0TIi_+(RN5C|?rW79H^d=jGH$;VTCG?5Tf{N)n6O8iZcz(h<6c&uL-*h zKd>qYCc&)lsu@RBA-w7gIA1x2mu;JS$+p>77`LU|_Pps8>RT)7n{y1Y=2*hzOvIEk zOT3I+K!act?E3t$jEpjb2HB&h1c%O-`g4NGK`XPvxV+&{zV1lRIN6?!Yg8Vn= z<|A>Dpo9qVsSMG;A{9q@D#igDK^jbfI6>J;c0(Q2jxr+^1-*e$En+enPpI}AQAxU$ z2I1kQfI*TGJ?B~5rGyB20DnE6NbrElD3{?yOb8NGCnQZ!$ifTn=M3^MVk*ceN zqu8x##fgI_7f(Thb|?=z2x1l4gVA1$(3GNj7*&;2H&%?m4;3GR){<(aGbE7%@FL+b zc|A~+A_pOhMn{n#3d+L*^QE1!d)|Hf_S?&T#kOO^*LHX0&PdVMRq%DKoV#aIeEW;O z!v)`A#dmbkzTs`T>%QYIdijEvUujw0sdz(0@BV^!zv4Z(XsJ~jDz)$Y*~o_@#rEBW z_TBk`V-HM9`^mgL@YKq910QBSIa?Sxzu|7kHxAyjt+@|v_}YImx^hnG7*c$D^6ov4 zT)uou??YEFrRiTCU2`9(ruov!G;J^Xx(mK;#n%H}w(MLvq_hkyx&eIKdy8%R3T^xD z9lC$z!C9s4!h4=Y+mipWtC6;N^!~Lq_vnVZ@%`7|dp+MabkDMSD<2p(Mlz}Zbo)Yi zcj!^;jz2PNUC)wb!`r+hE?@nPch{yFGM-co8FZHA0)Ny1Q24%v0I?SD%dJSXf5cl>-F^~s6a0#@XZwh-%ya|xg7T* zfv=C`+pu2q7Ao*9=7 zcsR-gdRfH?+_WbXaS3(h+=wwRWvCG9^>O|f{2)Iy3ts&z0fKhwea!6AQ{|`7kYlPK z%P5@bF_K22rs~wFuiCslXD6<*a*#9D71p!Xy8HB+`V;6}dS^M?EAb7gr!)vnf!86B3U7)$swplI zoJk44gA zeitYXQ(`ToL*%BD7=?uN*R_!Dm7vVO?QY^uqUi4__oMJy&q=Sl`jN+EUoD7hXpT?v9P_fuCRe=%Uhnu-JXP(0yF#J^>}?3+_$? z+4lABz7K3`-p(iPhNbb9!>i#!*P;B*!}kGmtI)51_26o6KCo}iy&uNi%Kyy$p}QF9 zD+Kyh{YqfZ;@EFJfsK|OD-NZlKkx0=fbVssV~^t7n|JTU4tkdXJG-i90U>cjarNc7 zJ`ECW2#KKK)yBkUuxx+Iy&0hBg!8o^PQ1*h%K^3?{(|%6JrW*+L#H?d9 zofanN!~s6r*U4W?XZY#pO^^>FxHU@h02?c7!-=^;x+AjMgWPu0Y-r{G{s;QQfn#^=|u}_T{Te z!>)yM8y^4r-+S+S%SRMX&%#+?K#Tj`3%4)4bMXo1SR7lLUJB=TjOLwZf8Ddjee8|4y@S^KB?(Ca1I$Ri`oqL00vaaa5^K*qcaHw91SxySf1ehtF zQavR%ZbW?R2DnkBY)84S9krn%Ut zM~TAHd8kbxM70RwWM+!O2l+PSR&p5yIU4;PmV5^y%3|&g#kFnW)TW&YY})__TBfoAH2QhdNa?xsmU=rdN#pa6}Rve@(HfX7Yh*8=Bo-`F+6%eTnYyNu{pMu z>IB@uB6sLQ13Wlr@X;Wca;DD=pA`D~GKhzCn_tof`&F!=Etb3VS(>`Q5}eMUMOzs| zB~TmCqNO{3axS86eq?L#2O_-&==ETFYb->USHgJ#yHt}5wo*3)r|*~WlfDj7<+_0w z@U|5_e8Iyjo}CM4*PFK$n}-U`rPWcIk1dQNx*WS#zveog=ZvhFy%lhDq z)AdO}{LtJHYOP9xzOMQc%&GFKHonSi$cE7<7{(gNqNWTw|4W`bng9G_JSW^@Sv{xZ?1l>9 zD=Z!2>HC?Wfu*`r;w{5{NL^%PKjc#@3XZDift^vFZ9_kw-oRF`p(gdVoz!|Ui1@e! zc2q142Z%A5;MBu`LtSb3!WB85kh0tKS6=H+*rH`=hFSY_G+-p@=t!-z)-&K71<;h! zrDlvVWSgqKLzBtAnkHP8^+pe?40%mWI5LJ4*ObAr59*T@<@OOkJFPRPVIKFkpa;V;*%=vJr9#Uub6yl?xcbo+V^Z00=#3 zzRM}Bfzdz0PkIN$(R04b7x)=BTDITK-N_YOdJ8SRtM&IyO3Tqj_lvxek3Bm+$`y{j zUhR?0cOO(bzNYww^X}nCt`^V)9=dja6%pbVAXeuhx8d7X(>M8Odw+5JaAEuKeeV9% zf2hlkURAdLRl(j4CSb$T=wpwcHox~C*i%QTJykh||F$xY;YS_8V#l#U$Fci4rQ>|w z-U`mrqN}gq>RWAEo%&>3{?OQ(>s+as!)To9Zq9@Eg!{w4NZyO&1E<&AXEbwdiy@b9 z46WW;a}Ph)Gu4CkDz1HbZXdMWv9Z;Xs^9<*KU^5dqy+L^$o(()NsSQEGh(nATs^DieA($5 z|FU{i2Iv#0wFUHXtW`l^pR?YuJ`I&Bf2E~ZAu^34q_RK_TE??2W9artMH4(a?$H5+ zXBtQNZ0JM^lIX7cG66?wv-erzF=IX*fSg_8@-Nfd;^fJ#Q~F?9J?dv0z(o>Vb` z^?C;p+5wTE{0pQ(?Hp#2b8338<^*Wix5n+?;2e49;rqjD+)3?B_RQa0R9xM8uA8oW z3@RD{B@bQne}g{p1RJiPF-c~gf$L%BvbGDS*~@>zqB16L9<*Pw;DBpZIc5giuL>1- zYN9mAI#r=Urzl%z^g`WMLh1FKIcLg3$&6uRl_~UA1k3CxnCSx*Ur=AB(o;G$Fb4`? z8icJ{mQT+wyP<1oS#wV9uZxlWMh(N&eBIQ|kYVV>VBndT9nDrv?WIN&GhJgQm|M(S z=4;F?7OYJkMs$gM{;TUUpPu9=w2M7_bP~=1qnYdAc!0zD5@r${q2|pz1F87JH(4e- z2yO}jJAqyZ0)K_XYu03$<-yp5ZBgQS)pjdNQgF#eZLg(;(r_y?bgz{!27(U*!S&XT<+ls1p<-a95ExMc#~w6444iq=)PDEEoeLja z+-Pdex1Ia-*jm$@8|_^mkFJg?-3OHRgZZX|n+~RRl-)Elt^J!G#_ivCI+yVV8gV1h zYZ##vP}}r^LA>HN8$l5|Md-;g!L6n?qacS9SZNR)UTFR2^V)pVv-{VZ!ieJrdEJBWAcpr8>3y zY7w}vM$iI*%Q}-0?ITqmJ%28JX(^K+L~A#%P)$_r@l;%nU`q{9OQueClExEs(1E*< z!a{&owaYx(iEOb zLpo7+f!X!c4i~-@cgKQby|KO6I8*~ z9HdH9T2X9fcVQb)3@JKyMb=kfeNRmRb|02BZDMNkYYgXJ%sw=?u5-3`M{kcVbuV9A Uy?p=F!su_f6Tk#q8&!h-551-xt^fc4 literal 0 HcmV?d00001 diff --git a/services/__pycache__/__init__.cpython-312.pyc b/services/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d7639efae90e3fee62f6c5b9536b4277794d8bc7 GIT binary patch literal 150 zcmX@j%ge<81o^ukW`O9&AOanHW&w&!XQ*V*Wb|9fP{ah}eFmxdWvZW%pPQ!KtiLj_(B#I##gQ8-zh*d@_u4Sf%onDyD><;$Kin|$7 z9z2jkDslqKq(X8?usq~yRW2m)mdg^X0y|p4iaF#)#HyssCEYVSux>P6HSfLde*J#^ z-s}0Ps;UBz@%49)hQIOy@Ee_YgD(=RHX$Z~3RFf1af(@;NwaY_&BeJiALkjm#_2*@ zjEfG<>%O!5`?Q3G{qKxenvqfT7=vs26iXRYOn5S5L6lSykStc6QA~5xKc?!ph=gwVx1^#MU^Yf;g)(kV~>Ed!6{Ha!^ot@(ECcKIn%M6ktV? zZ6qh?2Zba@aZ)5c@bSu=FXqRUy;*DcEJRnd1jK%#-LW%KbdPWY5*YwE@~zeqFbQnN z1~Q@CkpnSifEdrJgE1EKCe)LN+G^5M(de_+JBN)l>`Z2db#16~1Q{uqu*}Xg7v!VE zigm=WI!#x(*{Kjqaz%{T`+ceI9;#(yXfCZRV zG#&d#is8i~f>st~64VE8_z2TQ*Jp)2zEqt@tz&!5hB3hwZ2p5b0MNk_>+9EfJxcYLYq2?1qA5vm zMG;rJ_=P^Lm7-ep89yefL0eQqN$xBt(fgvPRhR3{@!Nsb;Mvsz&?{rU5*aUwPz{x# z*4jQ2f8L8N11^x}GUofpm-D%Jlo0_n zf0akc!-_eaj}91Xdr`VlBGA#{+E!)-M94t-malBc~bxmI@d$2lbstvG=p%>5VU0KgFKjX*Rh}*qYzn|BiULuKyJ@MEjI; z>4?4>4shPyV`O$6tniEwDQw-l3J6{i+lB6>4Gk+C#VxH4UY3I6){Xb3)S0eXZsx#r zW`4u&S+fw@J1=!T6$qoNfeMd>u#YA_O?c7DjS%db;uuBE!?oVuLx<-5<~Tm#x-9*} z=~ycWXX=(pwYycUK=S9~mZU^V>a})hqP@@`Tivv2X>MvTdZM4}G&rrLNM4_MAJO!5C-z z)GPU%JNKM>?wxzSd(IjEp|-Y$g2q38J^qD*qW+2xM&nAI?JRWWDS;B`I2AjYu#xXX|CoDk=>2q;w!WOiVJ|DLyYJxR1#ZV$O(QFvs;i7Yi)}Mm440VkX zET2v$6wFy?xvsdUDIyS)u(i&50F=tx@J4hU+q~@*m z9iZnVd$5SLVx7o~E`4pXJ|{RqUQg^)m)C;aovsVGG{=Z6O2eY`X)GdYHaHb>ev#6# zlcT^s3%~6KAoEm~&Qc*FK$4~c^bi~>BRmW+8YheKF$vF5##w&lP zMSCWt)PxvO_8qgV+)u3A@IYxcw37@cM2!~{;aFU=O_l(lStL=Jl9CYv(x}hFkG$P)p#yJ6 zO_X4WLZiVuGg)>C^`OmiSx({vI?IhQ!#JZfu1j@_GYs(V)>m*v(k3iMZ->JwrS)fd zu#E3l(a2tSV=u#0fEl_P;I*dEr#h^~5IM+La&k(MVK_1_Mjq*7;!I3d#AHO2tYB1Y z91qLmA>(vHax5_!7q#Y4SW(2pq@vG>NFuo^0gF@zlOzOzE#obBXPE#sXSpU!AkObhtM?zJ()C zE~rlbt8#^P_xTF(Yv17w-`TwHY;IuPcX_UM)8*N4b>&@Miv!Cextr^*k5t=7k{j0A z1qO5^0mHY@nWv)QYQ==ZMERuvIkqfqxJ!0txe3#?x)iBkYS2`ft!l1k{--TdW0x)4 z&T2+)2S)c{*R%YrCCif?8u86g1fI1R>(W$~13h zC?l?Q-1!OcBrgnP+RFh~^`4-0c?<|b&ogJ)avj)k_2yl@%f5o^?54Bfr#HX6skZhN zoTrHBMBa5`Q7pJlnWEl;^WCkkGaFsk^Ig~1K3MM>$=i<3)h)PQy7rfp7J3TKu1#0d zT&<40@~~kd?`N}uj^Kqb!J#d0m!2nBI zmN#MyYT+6Y<}TEWv;1fLaEVXT)6@)mmzsu3Zz$7-nDXn{LGa5{5hxMlv8i}Geb#?F z`30qb2oBy-_jxNdP(P57?zz*s-)9h{nfL z)1stV;;Cp9I2TKfr8MhwSW1Ek&3qkSL^$~-E#T<@Tkq#Zk5G zJ+-x8_4NPI+5hh%4|Cqg9kA6O584Jhsa3~5q@DIl9qj76otF->FIs5mzc|PP-BoRx z_1K?b_I!ED{O;%z>A|oEggO*KrBqP%&WXf0*`@Pzh+Xk;E#s!|FONk7BP238FzdhNK5b zfYoCssmxBofQ+%pjG8ztv%ef-6fjp)vQk=(IWH`HT)8n1*f7-v{IiB|% zUmW@My|3;qJy`dgQ=R7wp!iIn4CLH70LuA-^TL+LOAz6EBV#sR=p3Y}RoXsyoL#N) z4IX7zkMhv34uTgj;r|JOU5+;EsFI^i$4_8LsAzkm?sq%dU)|A0?gL+2bzdKZg>+wc zVz0WJNfo}=%{U|Df18_)wJw8}d>cr~(>rxerKfxHo}Ojfy624QJhRuw=W>I&KDFih z1?R;wALD1iLTexO+&*}K{k?CngXGyU(RgJFze>1=sZ?C!;!tvs*h~sL35x*|J|zqr65f3YaW9c;f~WBnMQSa* zc0h+pNH819{{iwjL{ge>Q`=8&Q^1Rs8vZ){?ENBze3{jGPS*L#)Y@%z_>MYyFF$;L zEtJ3ZV4LU_eRjTiF;b*}il|#AF zuj}$X*S2x2*nomzB3~ZO2`hbT?8?B`$^7Y?|3tZdHh3cNSAZ4M940o4lAZ*vpCma` zJYB89_;;W?X8gTEoTW8R;Xfzfry4P~G29$6wi7=e!&C*1WxS VVPM_f@!0Y&%SD=o9EOyb{Vx|~RHgs` literal 0 HcmV?d00001 diff --git a/services/user_service.py b/services/user_service.py index 83fa5b7..e95d1d1 100644 --- a/services/user_service.py +++ b/services/user_service.py @@ -12,39 +12,38 @@ class UserService: def __init__(self, database: DatabaseInterface): self.db = database - def create_user( - self, username: str, email: str, password: str - ) -> tuple[bool, list[str]]: - errors = [] + def create_user(self, username: str, email: str, password: str) -> tuple[bool, list[str]]: + errors = self._validate_user_inputs(username, email, password) + if errors: + return False, errors - # Validierung + errors = self._check_user_existence(username, email) + if errors: + return False, errors + + password_hash = PasswordUtils.hash_password_simple(password) + return self._attempt_user_creation(username, email, password_hash) + + def _validate_user_inputs(self, username: str, email: str, password: str) -> list[str]: + errors = [] if not ValidationUtils.validate_username(username): errors.append("Invalid username format") - if not ValidationUtils.validate_email(email): errors.append("Invalid email format") - password_valid, password_errors = ValidationUtils.validate_password(password) if not password_valid: errors.extend(password_errors) + return errors - if errors: - return False, errors - - # Prüfe auf existierende User + def _check_user_existence(self, username: str, email: str) -> list[str]: + errors = [] if self.get_user_by_email(email): errors.append("Email already registered") - if self.get_user_by_username(username): errors.append("Username already taken") + return errors - if errors: - return False, errors - - # Passwort hashen - password_hash = PasswordUtils.hash_password_simple(password) - - # User erstellen + def _attempt_user_creation(self, username: str, email: str, password_hash: str) -> tuple[bool, list[str]]: try: success = self.db.create_user(username, email.lower(), password_hash) if success: diff --git a/utils/__pycache__/__init__.cpython-312.pyc b/utils/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f45d26bba00dfe65b71d8a55f9ae7afdbe535dd3 GIT binary patch literal 147 zcmX@j%ge<81o^ukW`O9&AOanHW&w&!XQ*V*Wb|9fP{ah}eFmxdWu%{xpPQ2KczG$)vkyY UXapk=7lRldnHd=wi7%Q6rNr0+G}U?(}dDADb0okiu;q$A}Ugaq5>i)DWOt9w7!_FXKZh}-ZeAp zMzMkviAuB=-~b{LMe3nKM7eO_1_$n3Y$d2-2~rVAh?}W7pq_Yd?6uRB0|!R(n>Rc2 zX5P>DJ%8WZn<6m2_~w`5Nu7{iaS@GJTWKzW@+qN&DlW<3th!1`&8Q0MF*jDyGFnN` z=%sijUP@#VB_m@fL?w(Y4n~)CXO`MfTB}SC)vl3@Np+CDG!C+FSxG1U!0m-~CDfO= zT^4CQ)bp+_ilM<7bvVlfVS=-FDolVPm=KQdg^3Dxvw5HA+Ly~GFa-QHCqcXqK?I%M z8zge$I>{?kxn^ug6GGlqR+I}Qtya&bEEq4doX_pR=T_ibW$p*?zQz4Yz=RbPZP39L z@XE3)L6LcZld}VGNZRJwSIPVwiZH0UbIo4~q6$EkskWiE zPAVkOBCEwjq;+Si2S&77l+}$^t@$(Zxf+EIclAcQL4Tytc(fnQ7oeIq)D_~873H?_ z0j4Lh04W!YXB`^qtYkZGb^N@`Y{4woFIbL;>9TVW!!3@NHaG^uF?V4cJ{1@bHOGTOW9Xs5JX-c0FW_-JmISdL z3pJY;L>RvUkHM_u1t!w6R_{+w75x&M%2$f6Q<#EcECJ|M=RI_5SgiG2Vo`3CBR!RsJaI!yp8L=534bgDLEL z&|N+XA2DO%5D4(=uM~;*TtD&N#ipw3k2hl^-q%2_(MQaKHSICJAI|-c{Nj=$U4B7P zA0U<}`W2U2zUMAmmw{grOwMJOSxZ1PYvJ`b5NZX$kJF;tQ*5#@c?>@~-Z9{1!4U!D z5_uvmAIm`mozWpAg-;I=k^tc`opMl>#&!@8E#(M01O$S%drLI`3u*KPZh~EP|0Ta- z+1N8&&TP8ejf3xj{V++P-Cg!=PSaYK09}mpAvhJGS{7GUyLuEthtBk$5Q(iwoC48C zWTM_PCZTxz%d1=FsTSVmHxE3$Idr0Cp4g2y2?mKbK7u#x1X}+tH#ok9;OQXE>>y3+ zAPuyJxf5w%&>7hBuo}%d5W89@;iKKgNfmr($6DRBj^UbWH)9vbvYw7tUy#6fmAPer zN-A<+)$7+J8FIQdTrH@PucV7{`X1j)kg2`8cR@y^vO9 z8P`cGZIX@y@IbcxKo-sU1e(H6JOg5tGz?~$~fwX`w8zyBuzV8Z-32gn3UXk6j1tx@V3t-p? z!X&tKuGM6XY!<`GX88b~!CoQDD4pckF}k7LH)cvct+?zAKLQ)b191{WBc>?IPo(c> rGWt82`GL&bO^#gOcPBYgPmZiTx0#$+jo*v+DhKabAevT6X+`i4$&?3| literal 0 HcmV?d00001 diff --git a/utils/__pycache__/password_utils.cpython-312.pyc b/utils/__pycache__/password_utils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fb59076055cd258ba665126c62e546c26f82e3bf GIT binary patch literal 2067 zcmZuxO=ufO6rTN)R<`ABBF9lBrwH4EsMHZ{TGxQo$j@iCbza8B%2Jn}E>YuyL2z6Hf0jp@B4{aRrogIG5z?J)h)xggM>g8VxuW_c&*l zlz4O(Y5X?Qggw5e^K5W2@fB=V(vHfZc05cxC5$u>M&K#QV?pz2JQg*9{Y5Nc5sMlA zZHCEsG-+GfbF5L)!;paU^s(NIta-P^K0@vx;095XhfaJfrV-1(nxgbOgJ@rv`2tjQK#{Pf_Nz7u_o>FZj?<>)chxFrDVRlIoh`(3MiIv|73Mk{FB1dcG`{+! zx|~aycMLOLfp&=Z?d|Q2@`mNN?|1c^;nm^xxpD5$$K28TjBKHoqe}huaUj$Q%(eov z&ClC`>-EG@Alz7dy4ViP)a9elbo1V`cwIT3yw)f^Ej86n^j0f+>&4x6G|`^?q&|8S zoaqGTTEV$?Fkbf`%i~YR9*-Sfx%r3u;gK@6qa7;Khw}6(bBC-^Y8r%P1;R-~r@9NK z-0s|On9x9`t4I1Us;6b0$h#B#HS6k{P!r95@4o33s0vliwOB*Xxs{kmz$FO+fp)dV z(?+qJB3N~5>lQNv0K1}o092r+5WU5zgR+sUaD(zKCi%=pzvP?O&e!0=@dUG>?=iB4 z{s~|2gy&n~`Td6n6YcP)Ejd{C|M=iond~UhmJ)3i_rGc@ONa6jfwv~zpJ}#%@3u4d zJrmf>BYpUk>0tF|3YqX3j7i&^()dvG*(CESVAp@l9i*9V(IeucmT%5n(vO<;_P z0^}_qFv~H{o)rqQMx69boa<4Q=8NS5-kd(4!#80dB{a?mYv-ZPW!Zc3=<%bS+)u_c zV>jD=XTGg`+)X2gk`k<03^iIa8 znKJX~A~th|W(n+_uq3m>qO{w{64wo*KqBluGR??yM`jp^Tm}Mg z@-7glfL+8h`L>h0MKZ^9P+hyly8_2?f1+{c_tF=tU+wrpEnjG7q3xU9^8DwS;1b*k I0&3s(KQYVD?*IS* literal 0 HcmV?d00001 diff --git a/utils/__pycache__/validation.cpython-312.pyc b/utils/__pycache__/validation.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7a3e984bc906ed97ed3fe3af8fd54cdbd15f7eea GIT binary patch literal 3408 zcmb_e%Wo4$7@u8x?RDbBPD~yoX<0}@V;~8Hh^7=$2+vlKQX!BU2=3yY*lQfGnOy_f zIuZve8TC*QhomZ1Bekli=)qDs1ocno#SlxROH_f{OHNG*QYB9PX1(i&6oL<3X}@`V zk9qy(_sws0bu|dSAAfxweaIv9CvDiD)2ghVfXWP#ki^8%SfOOb7#3j^vu$i2D6!){ zQ)rGkS#%6Z>{_Xm9BK3o`j)kQ z7?fsDqo8y2sJ`>UIk8ti*gLkf_r1PQ_x9fL?FY(wpn1N}YL9*%>}!`+YOQa^|D z9RrJj)@S~vncCa6cj}(_J0JNw7yR8BZn5!5#=R71xyydXf6dRe-0NOw-MJ9hmEoWJ zT9&+xUya@z&AqiddnEgAuKoSIci%H#OUAbf;gP|oR9L4tiPy&9Fd*;$!QeE~iYNpO zS%{X{OMqv!eodX@(qV+i7R|o5C|1NKoqOSvoNM`3Vr`0%IKX(F?W6hZTFh_PO658j zUwTx6h~y>V!^( z&|6C=y&4V(N9eK$T@j&Im(cYRdMyFg&9qK0CTRp=qnQMtVKfxMXAh)rel0$26B%fP%Rdo3HwwI9rTM;0lVNfTWN zpA=Q~szRg+Fw+EL66!EOZ3acqG?3UENwq1>tVO93V?&n#;!HCWKx1nGP;#sTY^MqA zhS!Y1l}0Gha?DJku#&P*0>Ig1tiCRqyXt6s712CZN2{qKT5Z+Qyj4W2D~nd5n&Np$ z^_O}OvXWIXwZ)25P}*3@mu4ynByF8^&_AkgIAwuMkX3=;%PE;)>F6>=+42AgeY9vW znNl_3A{ImqZo3HeK_MI!i5Q05q6%>(5fQ|MB$#FiMHBF~FvgOwYhb9%PUp@+avaxp zSB4EM2~Cs}rPxXW3#nuhldz~_7>_0}@P*u3ov)c9%YE7NlHOCrppqPsHNE-V<^!Ew z-50iQ>k01Y`(Vr7&!^M-hR5~6Dk7*!9G1m+Y0-o}a`cX(t3^=od=e($-Gn8`_I!x~ z4VMTDPe`N<+)UatTq+hxI9j4a;J^;h8ZJzTLezC>Fln9eIy7jTbVE$_ZxGkfvxY#% z1teACLP)(QZ=TGx?aX_30kzF;y|q8*6_(cK#KnU3qW`m(4z{lTr3?8RznZ!^HQPEj zl=tnh)Va2g^WIZSzJ@ocn&$YtFIe9)fqnY;(@HDaUUz33oJDYw)2EeLjRjMolO*sYt0ft$RbE z%PBE#X}s_x)8z0Z)}o43NLprs+CY!1ot_G(rIK-MIO8%r*gB!-CuELbCMZJhmMQ49 zR#gx;&?48c!q#%Fv*8s4#hmnl7OM{AYBc*-+RU04REJg&6!#9lpoL`twUrLjqKOlz z1r+y=WV_~_^QRwrvi*;CjJ%+IrujcC)C%*VQwh2ZH+?w5gRuZMPXucx%$FqTqEj{V zusP{%v`KT5xsX@ Date: Tue, 7 Oct 2025 08:44:02 +0200 Subject: [PATCH 5/6] Dashboard Finished --- config/__pycache__/database.cpython-312.pyc | Bin 3097 -> 3510 bytes config/database.py | 11 +++- .../__pycache__/sqlite_db.cpython-312.pyc | Bin 10999 -> 12327 bytes database/sqlite_db.py | 49 ++++++++++++------ .../__pycache__/user_service.cpython-312.pyc | Bin 4843 -> 4847 bytes services/user_service.py | 12 +++-- 6 files changed, 53 insertions(+), 19 deletions(-) diff --git a/config/__pycache__/database.cpython-312.pyc b/config/__pycache__/database.cpython-312.pyc index 760518b43a557a178e18bd628818bed8759521c8..71bd015262284b729609df815890c2477948d7d5 100644 GIT binary patch literal 3510 zcmbVPUrZZE8lPRS*9QNA#1tHC0!g_f+oYHaY5tX?g5VaKgm9R&jT>oYm^Ik9_Bylc zL`Fo4s#Hp(tI|FZ6e|4Chg5lSrK+M&_j;#$v9l+E=2G>fODpw_mPnQQbThji8&K}x z7|Gwx%=gWF-}jsO=KK72pRW;+cIlhvvww2~@NYU`O{jJ@`blR2Kma)v#Oaq;xeOoY zIofxqj*Ji&GS0Y@13Y*KK;bTc&L_ORIxZGCN&JZp#v~34;|XI{;;~~eTfo9_YTB5# zzOsvi2GZaTEb_e+AKuBb_!n%ebSUu0IxD3N4-R!z-Ba!5-n(}o@yzb0RpO&CL(5wVv=U=@U( zTmidfIh9QrvOL$e6`LN$p#JFHgxmqo+YT%gJ}VRtJRULI-nb|H*}K--zS?@U(t6Zv zmF@|jcs8h~SVW4EN7*g#l3QiN`y+v10T7_5=(d)o2e7R%@F4f6V*sF!4JQ*Y*fjx9 zs)v=PTDG;9%|U+71IV4F^fqS@YPYnP_3B?J7)@+6&oNEx@Ne^Vd**q@P48nX>R;xE z-d10c-e2dl9+R85Y`o1w=O+C%4Jj_R7Ys!U!<##J?1FCQpYaN_Ylk%ru#v4{DD1Gp z1HEj;4w63T-=$;|Y-W;hAKbqr?g^#9u25>(14^&_-zc^28l|>fqZHhP(t$mr)NY}a z-{I^+dq61+JJ>1i@-7|RHA*mD^IC*{#7W&_ zh^AHCz+PN^u5p^Y#Z#Km1E;Vj_Qy-3lTmqmaB>6-Ig$~vGgBam05@K~MtJhbmDnV1 zP_^lVI;-ghn;yS1F^Pq~zTVT=Zwn3&P7V$Y#-i9&-JXeFjYTK0fHciuqT_?H*!x!| zhB3gdypcScnL0%hqhReX8HBizejrU6L31 zhzxeB+AReknz(2(O{P>uma&*iASG)cnpqG{D%hbL2zyexoS4!zHE$@`F?|bSM=DFs z^}U3eSE2}MNOB;WJFpij$wXc?Wb0aZ?CQW8=u}l#R~MqW1NjM=3vEx`n~DXhT>pXO z$2(xn)AXSKe*dbcqvGi>J)Om~Pd&$l;bm!2DqjA&uQYG=4V&%Jdlz4bpe6XwV+Oic1HF|%?>_=3pB+5BJi9piDE;`& z%E8m0dj8eYzI37JF~cXyf!E94*Vlae9$deFebv`l@pYQML&f)>`c6C#wl6mrZ{ZX9^=F;?7%jg<9#R86KchOyRkeb7nZo6h=ztH(PUV}yJhdYsD&K&mb#0UrdC;dl63xC-9=urS_w4m8#4_qgtQN9o}{yUm|mg?n7$}axI$z59aUBKb&0t zaPh-()3LJqnB~Tp)JP*Lo5;|JYLw-S2J=>Qd1d)VKB3wi6rgs|q7V&GLdr`!EU?qa z=Trr~O(wns)|Ph6(25pOLhDDJ{;RnQe&HR?*VY@4I4^P!VX^PAqj+{Py8-BUeVpT* zQt|5JzLHRit-Me%reNG)5S-oYjMbtUEZ4`zL7l4g|jk;a|lFC;b8lu~z;E^<~~4 delta 1384 zcmbVMO=}ZD7@pb9ZnF8b-K33a+NN4fVnGW<5lM?51P%RAN%W8&Byoai-Fz_FL@JSZ z=s{1Si`YP*ITfW|q~N7Lp_hP{vL2*IZ=oIpPwu;6B~l@=b9iRnnfH0#*=J|w^GMz6 z+;cdrNNZcW2ib)AwbL7!)}nWaAc7^7gr1Rbj!7~(Hpybdpqq%W>xh`P8Q>w5G_Bz< z_Z@~ypDJ4z^U5f58{3r}GZ*v{M&@7%+A81ayOFSW9o|9jx++k>ILJs9rt!253xPU;?%d)V$fh6f|WZ~TCM&%tQl9*mK3L%he<16>|W zG`KjDZN?!Wr>e?~d2;&n5{1L9nu;kotJ>ms7h;L%gFDv}x1PF5N=~IyrA+C;05e&O|9K zQ0mfVOK?X5bO5p(%B~RLA-D8aIS_oq`)*(3`ev*iYvx)P=fC(DTH<2MzPOXNW-%6( zJ=?t@C`FwB-D=7udn7OgLLLpCqkWh7s`|3Jk=R_WFSlHwmL)_*<&AwRJqT2j1}a;U zDP$=?ikDJd|-t+-4T_S*NQ9oN1cLDU)Q8JVDzWhFH0m>AY~~tN2A&TSfzhZo5dJ^ SMZ!1a|H%h&_z-EJ(|!Z^oxy?t diff --git a/config/database.py b/config/database.py index 2f39957..7b6dc6e 100644 --- a/config/database.py +++ b/config/database.py @@ -1,4 +1,5 @@ import os +from pathlib import Path from typing import Any, Dict @@ -10,7 +11,15 @@ class DatabaseConfig: def _load_config(self) -> Dict[str, Any]: if self.db_type.lower() == "sqlite": - return {"path": os.getenv("SQLITE_PATH", "databases/chatbot.db")} + # Standardpfad relativ zum Projektroot + default_path = Path(__file__).parent.parent / "databases" / "chatbot.db" + sqlite_path = os.getenv("SQLITE_PATH", str(default_path)) + + # Stelle sicher, dass wir einen absoluten Pfad haben + if not Path(sqlite_path).is_absolute(): + sqlite_path = Path.cwd() / sqlite_path + + return {"path": str(sqlite_path)} elif self.db_type.lower() == "mysql": return { "host": os.getenv("MYSQL_HOST", "localhost"), diff --git a/database/__pycache__/sqlite_db.cpython-312.pyc b/database/__pycache__/sqlite_db.cpython-312.pyc index 8044406fd9ca17b71756b588520e4479df63efc2..01339283e31e739e5565b92bfaa5ffa287bf22c5 100644 GIT binary patch delta 3414 zcmZ`*Z%iD=6`$GN+uh^tVEK302970Q;J|iGOfa@%$2PVxu7g9se}Y|IkJ|+fA9rMS zDF#E%sjSwPECsqB+{(4&^owf|DYb~&NNp;oQd6XU=pkPP-8zw_`a`NpEs9+=a#g8s zX77)w=xX=Py!U3_d-LY~X6Ik0?|!@R_dZ_%f=B!LlaY~{`NB>3d-IJgNsKh42{Ca@ z8j!~10eQ?l;0BpX6JrHqo&gU=9MaL~COUQfqx%-HBN-^&Mg31VA#BW#X9>xv~J;aHHj`9tw3d;XKx@ZabE6Y!O5;#FZl)C64`RV)>kCnezB zTDc}eTL7&aS`V}Z(0VnGE@)o(eDDdnZ%Eb(L0-sYf?lL6x}X;iaht(A{e}ds2=pav z-o|r(8k5^(7wlzXASkq8U7cLeO)b z8Dt$StO{Xdy0W5$oGO&b7(!Dhh&SVdLUNnr-xf@+%KZlT*kwq7v$F4DwV?j3FtPohiwTWAsorRnxQ zQ;)?=)rdw$bh1s=!iGVKdL*;{?Pqi{t%EimHB|jl)G(tuG5dp@EsckX9ybkJX5vud z;&fFf(Zfko*T966J~fxVz3O!Rv2Zj7N;9EGV4$gQFid^U?Nxh%ZbGx;?1|_&vPI^{ zuw7#p!Ky9B62rqfv4v=SC}B&d`i>HkAhs*1(>BNx1uWR2Hb}S7#=1c*s;Wwgsb!kF z>0n>)$*8Gk*Sh2XZ@wRf8#6$zpeM!UbK1?=eC%Oy-AZxua&hxDakZ%Yz1i!tHr972) ztJT%g)`tLId9P}ALcYyFE^n%inriVRDfqk_fRFnh@cFEOcmVfU7sT7R*?KNE2>_8M z3m4QMSHq@C= zV)aO`b`Tn(?b7tYiDBEtKtgJ$?F>TX@SqVIhaUy01!*27)=#B2iHXi(>n~C*)OLx_ z|D>|!j&RrezV~6}_La(4mMdR*Sh;&neiYpKVa>goM`aa1l&#lS8(LPY)JL^VE43ZV zwH?3Oy|S-&8Q$97XKq(>$(%sZkX9O=c~SfRU!1>x-jS>*4a-VHT6y`gQbtEO{ED(; zS=o{LM)G)C>0aGPb0V#Lb3;W}S~z7xG zwk{WKP03rYnOXKMMG%XSK{ibuyA38^$)p$gR{NDeHLRY;jRTb?=I!>JJ`DGzPi5+ zrn7w{)wIWcRqmsgBKo))O~l!D-s9MT=WHTHPWGg0w#Ex8tM-7zcoWDKv?jRRC97U# z#j7rR)wK7e#d`%`VO(eZ*n4VUBekC^HQN=5B@Eqh-AYyMKx}C;Oybe_Fxd^9k#%Nm z_ci0gi|2d?g?<{aEk-7YksxHJ!z9MWqUH;$pr%;pga!wHV0K^&w1CNes$<1Rj{`Wh z;n=qRR@@<;1lG82h3nPD?vnd_l4XXCre4SaN@&45iK2!{5Qtsa9XIu15;dnB1ni|k znIvMd!EodvTb6?g$w}iOI`c3kos_&rNj@lgl+vJ7fdw|}-zI7xG9I(Q{@`EZLhA#w zo{#L?XIj zIP1!7N2ccOvWaoHf#{(LtGT`vFDzcD=lRw%)aHgcCg-SiR&MJSG}pKdKd?S&{6Z>& z0X@MA>nBaylca@?roT6Ki*V|zpwl^bDI8e_o2h;uB?p1n!eAm1BVClI(Gu#1(0eKA zp`@3RK1$xAj}k8e7#g2L?<)F}&R3XXi0KDN n6j%(OLDRIxV~qcd3gP`6ZL)sbtd<<%ab>E!;h%_hSTg<#rlT9# delta 2383 zcmZuyU2GIp6rP!#ot@pC{ptR+h0=Druq{)TpV9`XDG0U&E2U}>jeW3`o!NHlcBkB# zO|5`M(}dPYuwD~Pj0u_;f{n&zNeI5^gNY^@ZDW&NMjm(|CO&8y3&EI(-g9TSU9^*# zbMN^-_q+F=xq9-!3Ga6vkBcGCpSiokZ`aIvtJzm)o3{0j3jM;Uqu;?Y3a{AH;;6IV z$ubT1yP3WzOVvHJwCm{12xd z1fcW)A?KMwRoyiImUOqW1`kd17u_pFO5BiYWKkwj+z5~{4)Q_Fl^-}fZ`*=@6xug$ zHb6?B5wSE|8_zN$E_}rsiYqolD2Yd;(rj%k(|Yl|qsqq5@p!+usd8;?WhQ?7w_`u+ z#PdQO{!I*r!)t*`GsTW)oo(Dm7;9n=8^$-qo`&_z#L`(~8KV+^yP+1Jbh`2T&NwH# zaKd!}f8_dr-HH#ox5j0U=@=f=2Mq%u56Oez?3xb!bUJ0It)?TPWio2Qpy1?)Dos^EH+vFGUxn=#sSK zj^qami_c5Vi&FE#wyq_qyRe?(@RIcWk##klOH$XmitZ)p@NFq@sduJ#VFOs*@dYoP znK_g9#TI?B1u=#y$m06&Lr({Hj>R3`7i^rt;fMZOe5<-be1lPJ=eXB6{JnRoJ4!53 zgb3Vr~yg=_-B4j?o*PiACIB>X#7`-FDF=`;9reI)l%)x2$z0!57>2igfF0)!@jun5|X z>FvoF>JUm96WxFu+6F=qY3cN-!NkjJmB4Ln+-DJE4TF|1`&lUGvYde9;PT&r-v5gBAd&x7P1thjZ!rFStDbk6d)7OIUSA`ym5GwA`5p%@BS)8p31I7(0Q}^)2|D z=rH?uZrA2K+x}?j=rM?~PQ9puDD?8U_+acQ;Z2ZUpqur1%)jnt!5)k!v}~sQT&!gP zFwh=CO8Y_)=>qBM%1Fn_CK9TyTdP~$o6^>VvSSL}5&XE^!oHU~E!%7@hau*=D5EDK z`u~8!AIIaur$nWH0t>49@~THTM_Rzy+U2&y;` z_>GzTDNReGy}$!*$PNU~IywO45RgtFJwT2Ua*d%4#Jb!rkOF}}n_gfD8dJ*sEi|_A@1Q5s8EQA~HGcck4{{oX<0r&s_ diff --git a/database/sqlite_db.py b/database/sqlite_db.py index 6efffda..0d9ef02 100644 --- a/database/sqlite_db.py +++ b/database/sqlite_db.py @@ -1,5 +1,6 @@ import logging import sqlite3 +from pathlib import Path from threading import local from typing import Any, Dict, Optional @@ -13,32 +14,50 @@ class SQLiteDatabase(DatabaseInterface): def __init__(self, db_path: str): self.db_path = db_path + # Erstelle Verzeichnis falls nicht vorhanden + self._ensure_database_directory() # Thread-local storage für Verbindungen self._local = local() + def _ensure_database_directory(self) -> None: + """Stellt sicher, dass das Database-Verzeichnis existiert""" + db_dir = Path(self.db_path).parent + if not db_dir.exists(): + try: + db_dir.mkdir(parents=True, exist_ok=True) + logger.info(f"Created database directory: {db_dir}") + except OSError as e: + logger.error(f"Failed to create database directory {db_dir}: {e}") + raise + def _get_connection(self) -> sqlite3.Connection: """Holt oder erstellt eine thread-lokale Verbindung""" if not hasattr(self._local, "connection") or self._local.connection is None: - self._local.connection = sqlite3.connect( - self.db_path, - check_same_thread=False, # Erlaubt thread-übergreifende Nutzung - timeout=30.0, - detect_types=sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES, - ) - self._local.connection.row_factory = sqlite3.Row - # Optimierungen für bessere Performance - self._local.connection.execute("PRAGMA journal_mode=WAL") - self._local.connection.execute("PRAGMA synchronous=NORMAL") - self._local.connection.execute("PRAGMA cache_size=1000") - self._local.connection.execute("PRAGMA temp_store=MEMORY") - logger.debug("New SQLite connection created for thread") - + try: + # Absoluten Pfad verwenden für bessere Kompatibilität + abs_path = Path(self.db_path).resolve() + self._local.connection = sqlite3.connect( + str(abs_path), + check_same_thread=False, # Erlaubt thread-übergreifende Nutzung + timeout=30.0, + detect_types=sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES, + ) + self._local.connection.row_factory = sqlite3.Row + # Optimierungen für bessere Performance + self._local.connection.execute("PRAGMA journal_mode=WAL") + self._local.connection.execute("PRAGMA synchronous=NORMAL") + self._local.connection.execute("PRAGMA cache_size=1000") + self._local.connection.execute("PRAGMA temp_store=MEMORY") + logger.debug(f"New SQLite connection created for thread: {abs_path}") + except sqlite3.Error as e: + logger.error(f"Failed to connect to SQLite database at {abs_path}: {e}") + raise return self._local.connection def connect(self) -> None: """Initialisiert die thread-lokale Verbindung""" try: - conn = self._get_connection() + self._get_connection() # Entfernt das unbenutzte 'conn' logger.info(f"Connected to SQLite database: {self.db_path}") except Exception as e: logger.error(f"Failed to connect to SQLite database: {e}") diff --git a/services/__pycache__/user_service.cpython-312.pyc b/services/__pycache__/user_service.cpython-312.pyc index feb1a13b485380bb2a61aba4c03ca56ca46e81df..68d0cf069670dfefcdd2a5f4ff6ed390180fc817 100644 GIT binary patch delta 274 zcmaE@`d*dyG%qg~0}%Y#@+4#ZM&5cB?o1%Bf#CxigOJ$fsVuon0m5B$=M2|TRcj5j2tKQMzCD(X;% zu^EK%fRnGIWJ1Uc<%y9U^%ptiKeK|=eURa16$9%6(I8DA8l(qEKj7r;NbZ#U%nD?G xkeZw+C}+gWY5`UaqCu)bw1qX8#M zQEl@Lj>}BEdLXG~V5tvGn|E*rGBH|j=Hh$F$mp{93%@jD92cuM;{xXo3?O;~Glbqz z451H{o(Q=R9DX4p`eJa*iTI1|v7f=}K1gt~imgcgzyPFnD1)gJ!eHt`VCaRg$cuqd zpFwgT#3ttp%9(JpTC4z?2&8rxgQ*h`-i7d(3$ck8lG86_WM53qxe%LkF+BG(NZkji W&HDuv8TlO;86`e3fXE_2pdSD(ms4s0 diff --git a/services/user_service.py b/services/user_service.py index e95d1d1..2cf6634 100644 --- a/services/user_service.py +++ b/services/user_service.py @@ -12,7 +12,9 @@ class UserService: def __init__(self, database: DatabaseInterface): self.db = database - def create_user(self, username: str, email: str, password: str) -> tuple[bool, list[str]]: + def create_user( + self, username: str, email: str, password: str + ) -> tuple[bool, list[str]]: errors = self._validate_user_inputs(username, email, password) if errors: return False, errors @@ -24,7 +26,9 @@ class UserService: password_hash = PasswordUtils.hash_password_simple(password) return self._attempt_user_creation(username, email, password_hash) - def _validate_user_inputs(self, username: str, email: str, password: str) -> list[str]: + def _validate_user_inputs( + self, username: str, email: str, password: str + ) -> list[str]: errors = [] if not ValidationUtils.validate_username(username): errors.append("Invalid username format") @@ -43,7 +47,9 @@ class UserService: errors.append("Username already taken") return errors - def _attempt_user_creation(self, username: str, email: str, password_hash: str) -> tuple[bool, list[str]]: + def _attempt_user_creation( + self, username: str, email: str, password_hash: str + ) -> tuple[bool, list[str]]: try: success = self.db.create_user(username, email.lower(), password_hash) if success: From 80a00a379ea7eef7631a3d41ca5b35819bcb3c74 Mon Sep 17 00:00:00 2001 From: Florian Uhlig Date: Tue, 7 Oct 2025 08:49:56 +0200 Subject: [PATCH 6/6] Bug Fixes --- main.py | 5 ++++ requirements.txt | 64 +++++++++++++++++++++--------------------------- 2 files changed, 33 insertions(+), 36 deletions(-) diff --git a/main.py b/main.py index 49e1f9f..0c9fee6 100644 --- a/main.py +++ b/main.py @@ -1,8 +1,12 @@ import logging import os +from dotenv import load_dotenv + from frontend.app import app +load_dotenv() + # Logging konfigurieren logging.basicConfig( level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s" @@ -15,6 +19,7 @@ if __name__ == "__main__": debug = os.getenv("FLASK_DEBUG", "False").lower() == "true" host = os.getenv("FLASK_HOST", "0.0.0.0") port = int(os.getenv("FLASK_PORT", "8080")) + print(port) logger.info(f"Starting ChatBot application on {host}:{port}") logger.info(f"Debug mode: {debug}") diff --git a/requirements.txt b/requirements.txt index 2bc2985..1b37a24 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,36 +1,28 @@ -# Requirements for PY_ChatBot -# Core Framework -Flask>=2.3.0,<3.0.0 -Werkzeug>=2.3.0,<3.0.0 - -# Database & ORM (Optional for future expansion) -SQLAlchemy>=2.0.0,<3.0.0 - -# Environment & Configuration -python-dotenv>=1.0.0 - -# Security & Authentication -bcrypt>=4.0.0 - -# HTTP Client (for health checks and external APIs) -requests>=2.31.0 - -# Date/Time utilities -python-dateutil>=2.8.0 - -# Development Dependencies (commented out for production) -# pytest>=7.4.0 -# pytest-flask>=1.2.0 -# pytest-cov>=4.1.0 -# black>=23.7.0 -# flake8>=6.0.0 -# mypy>=1.5.0 - -# Production WSGI Server -gunicorn>=21.2.0 - -# Logging -colorlog>=6.7.0 - -# Utility -click>=8.1.0 \ No newline at end of file +astroid==3.3.11 +black==25.9.0 +blinker==1.9.0 +click==8.3.0 +dill==0.4.0 +dotenv==0.9.9 +flake8==7.3.0 +Flask==3.1.2 +iniconfig==2.1.0 +isort==6.1.0 +itsdangerous==2.2.0 +Jinja2==3.1.6 +MarkupSafe==3.0.3 +mccabe==0.7.0 +mypy_extensions==1.1.0 +packaging==25.0 +pathspec==0.12.1 +platformdirs==4.4.0 +pluggy==1.6.0 +pycodestyle==2.14.0 +pyflakes==3.4.0 +Pygments==2.19.2 +pylint==3.3.8 +pytest==8.4.2 +python-dotenv==1.1.1 +pytokens==0.1.10 +tomlkit==0.13.3 +Werkzeug==3.1.3