From 91c13307aabcdf51d70b13c7de1718ba07eb979e Mon Sep 17 00:00:00 2001 From: ebby Date: Sun, 27 Sep 2026 10:57:03 +0200 Subject: [PATCH] secret creation --- .vscode/settings.json | 1 + .../backend/__pycache__/main.cpython-314.pyc | Bin 1282 -> 1262 bytes .../__pycache__/mail_util.cpython-314.pyc | Bin 2944 -> 3313 bytes .../__pycache__/rss_reader.cpython-314.pyc | Bin 1412 -> 1558 bytes .../{output.html => newsletter.jinja} | 17 ++++---- .../internal/jinja_templates/welcome.jinja | 38 ++++++++++++++++++ backend/src/backend/internal/mail_util.py | 24 ++++++----- backend/src/backend/internal/rss_reader.py | 9 +++-- backend/src/backend/main.py | 6 +-- .../routers/__pycache__/users.cpython-314.pyc | Bin 5506 -> 6354 bytes backend/src/backend/routers/newsletter.py | 17 ++++++++ backend/src/backend/routers/users.py | 15 ++++++- 12 files changed, 98 insertions(+), 29 deletions(-) rename backend/src/backend/internal/jinja_templates/{output.html => newsletter.jinja} (58%) create mode 100644 backend/src/backend/internal/jinja_templates/welcome.jinja create mode 100644 backend/src/backend/routers/newsletter.py diff --git a/.vscode/settings.json b/.vscode/settings.json index 65271fe..31aa94b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,6 +3,7 @@ "cSpell.words": [ "Chiara", "Hobbithöhle", + "mailtrap", "Masala", "Pomorie", "Reinke" diff --git a/backend/src/backend/__pycache__/main.cpython-314.pyc b/backend/src/backend/__pycache__/main.cpython-314.pyc index 1fffd0c040a9275c82a8e763f38790ad5ea1d6b9..980e683edfff9aef422674a15bdaef6a34ca8674 100644 GIT binary patch delta 47 zcmZqTddJDD&Bx2dz`($8;rfoONfUV`8T~e@`!a5BV!Y49IB9Yc%Os9#49Z1<3=9ka DLV*n- delta 60 zcmaFI*~G=G&Bx2dz`($eb8tu2?uopTj4>P4eHqze85J2!7&hlHK4)T_F*$@~65kaD Q<%bMP*BDfa1Q{3@0NhRwf&c&j diff --git a/backend/src/backend/internal/__pycache__/mail_util.cpython-314.pyc b/backend/src/backend/internal/__pycache__/mail_util.cpython-314.pyc index c2fbe88ffce0019776428c58cb30c5a7992f0ae9..5b2352419e954d30ee4845a2feb4e52cd4315c95 100644 GIT binary patch delta 1395 zcmZuwOK%%h6#njb-s3oK<7aAc8wa-&+K7axX#j~vDy<_>38Ug5NMpHG(*+yU4Ut$Bv0;V!4=N-C#ek4tQL)2~tFT~!&h};E&$6^v7T_x@@Inirg6gXU&DXMs z;}|?O2~V3*de*)!@AM=*Dftmj@(;bI0@hOlpNfl?T?F0 z-@bo5?96k&R;gFdmHqNpX{NG7?7+=rsZ?v!{8Gsf)5oH$eNq4z z078JddsgzYy#KTqWOq=O*ix>j&IDX$v9#C-m;pTGz=?l1#7zMF5P-IBH>(w1^%cywQP^nXbAxfmg%v_$x`Ir4*<`PR(by!82rJF)M~^Y;>&j~q@a z6$XGl61A5ZcJlz9V=WZ1qKHi;vz3FZ@HoXKFg!t^6`rC!#b{DaW33*tQOe@+MCdx_^CuchIph6n*=}2M!pMs9YxFT;v&wFpe`olR%#BMId-`Iq0T^2a2LSwig0p z??Srac`>KH_6ot2=3@hZ5~YMrEVQtP2#a-S`QnKD4cO^RPQ^`Yi>@U;GmeS7Mq;>aky`0mxmI^IeoFjd9C1`SHL02NV#J)VX#ymPZ;1=$ z8D@)H=IO*p*V4jz>s&VsE%M>&`!7o>#oy-n{PR>eni7}E=6PgQCd5_iOExD)?M#jg z+Ipp4t2TVuWcj1L8a_*&XqgZt`_dByI#MO&YkOEizf$%qS7icx0l=iVXOB@KP`(&8GqU8Dfn6g7i;_|B9#fbelywuvw&= b(pdDS(}l*O4CKTZrajpVvM`%hNL%zSV}ZC4ca6%O^TKyFA2UWg2utug81r#A_X6{4`O{iEredn4FM zqCkj%e{qf&sRz?NIo>Etj=Vh$ny37RE~d@Hg7+j%bL$_bs`gzf3&&k$&6o z2p^TFj8S6A8Dmm@NH?D@0Z0gdC;2b{J~m)yltZyS9HU6+fnuLNmThv}8Yg$eLJ`*QbPo{h3Cqv zPIcPo#6deXcX%j*RBH*Y3Qn!1W|Id=!WHx$oYilu4{hgt>mBO@`d;x^hkK12+H%5uruM|4W9I4G zSC1WKeBiA9nW(mXJ#>0`(Y(KyTgf|epT027FR8&&z4ZwH-=Uk5Kf0fjbPwKS1308e=M z=ygAJ`RM}y*n@{)6AQ{jkUVnCij^fHMJ!pdvMl6?WlJfmLXB9ll(Hg}h*c{t;&xnU zwl)Jox7Dj)>OXOfNy4-i6>$dST=N0N?rVgH5?&%zj!beZEpU zPTUOM%B8K$!eIU&GsqofR`)kf(sOUN4w}P@N9p_f>nF*@LGd_weVm00g)y2ljWEAU zohI|@%dRIF_h@UG_C$ku!gXjQ2z3X4UBsM&_hB6}N9(RQj5etvIT=9ra&s3%#Q!zjO04naAB{8~_I}`KU|GXG49!&e)7LjN6Uo^JcRm=nNQGuNS5Sys|26 z%0;}m0TL*{k5h)u@Rz*dB=t6bx)cL2vO*;Xs?!Tbe6N2fO#qVOB>6fCJ>=zO`g)XX z2jRBt3{=7}Fg{j0rxd%qjh m

Neuer Artikel:

-

England

-

It's gettin' british, my dear!

-

Auf geht's nach Milano! Aber Moment mal...der Artikel heißt England?! Da kann irgendwas nicht stimmen. Ich frage mal in der Redaktion nach. Ihr lest währenddessen einfach schonmal weiter.

+

{{data.title}}

+

{{data.subtitle}}

+

{{data.description}}

- + - Approve + + Abbestellen +
@@ -51,9 +53,4 @@ border-radius: 3px; border: none; } - - #admin { - margin-top: 64px; - color: red; - } \ No newline at end of file diff --git a/backend/src/backend/internal/jinja_templates/welcome.jinja b/backend/src/backend/internal/jinja_templates/welcome.jinja new file mode 100644 index 0000000..b7a0285 --- /dev/null +++ b/backend/src/backend/internal/jinja_templates/welcome.jinja @@ -0,0 +1,38 @@ + + + + + Newsletter + + + +
+

Willkommen, {{user.name}}

+

Du hast dich bei Blauwasser-Mausis.de angemeldet. Solltest du das nicht gewesen sein, dann lösche die Daten einfach über den untenstehenden Link.

+ + + Daten löschen + +
+ + + + \ No newline at end of file diff --git a/backend/src/backend/internal/mail_util.py b/backend/src/backend/internal/mail_util.py index bbfca9f..d8695b1 100644 --- a/backend/src/backend/internal/mail_util.py +++ b/backend/src/backend/internal/mail_util.py @@ -1,10 +1,9 @@ from mailtrap import Mail -import mailtrap as mt -import os +import mailtrap as mt from jinja2 import Environment, FileSystemLoader -class Newsletter(): +class ArticleData(): def __init__(self, title, subtitle, description, link): self.title=title self.subtitle=subtitle @@ -16,23 +15,28 @@ class Newsletter(): description: str link: str -def send_newsletter_admin_approval(data: Newsletter ): +class AdminApprovalData(ArticleData): + def __init__(self,title, subtitle, description, link, secret): + ArticleData.__init__(self, title, subtitle, description, link) + self.secret = secret + + secret: str + +def send_newsletter_admin_approval(data: ArticleData ): env = Environment(loader = FileSystemLoader('src/backend/internal/jinja_templates')) template = env.get_template('approval.jinja') output = template.render(data=data) - - - with open("src/backend/internal/jinja_templates/output.html", "w") as f: - f.write(output) + # with open("src/backend/internal/jinja_templates/output.html", "w") as f: + # f.write(output) mail = mt.Mail( sender=mt.Address(email="newsletter@blauwasser-mausis.de", name="Flaschenpost"), to=[mt.Address(email="blauwasser-mausis@proton.me")], subject=f"[Approval] {data.title}", - text="Jinja2 Template", + text=output, ) - + send_mail(mail) def send_mail(mail: Mail): diff --git a/backend/src/backend/internal/rss_reader.py b/backend/src/backend/internal/rss_reader.py index 7ae806f..c493567 100644 --- a/backend/src/backend/internal/rss_reader.py +++ b/backend/src/backend/internal/rss_reader.py @@ -1,5 +1,6 @@ -from backend.internal.mail_util import Newsletter +from backend.internal.authentication import create_access_token +from backend.internal.mail_util import AdminApprovalData from backend.internal.mail_util import send_newsletter_admin_approval from datetime import timedelta from datetime import datetime @@ -13,13 +14,15 @@ def check_blog_rss_and_send_admin_mail(): date_string = str(article["published"]) date_object = datetime.strptime(date_string, '%a, %d %b %Y %H:%M:%S %Z') - if date_object > (datetime.now() - timedelta(days=15)): + if date_object > (datetime.now() - timedelta(days=1)): title = str(article["title"]) description = str(article["summary"]) subtitle = str(article["subtitle"]) link = str(article["link"]) - data = Newsletter(title, subtitle, description, link) + secret = create_access_token({"sub": title}) + + data = AdminApprovalData(title, subtitle, description, link, secret) send_newsletter_admin_approval(data) diff --git a/backend/src/backend/main.py b/backend/src/backend/main.py index 662bb37..29f49af 100644 --- a/backend/src/backend/main.py +++ b/backend/src/backend/main.py @@ -26,8 +26,4 @@ def on_startup(): router = APIRouter() app.include_router(users.router) -app.include_router(comments.router) - -check_blog_rss_and_send_admin_mail() - - +app.include_router(comments.router) \ No newline at end of file diff --git a/backend/src/backend/routers/__pycache__/users.cpython-314.pyc b/backend/src/backend/routers/__pycache__/users.cpython-314.pyc index a0105bffc0f9cd19aac7846fd88f6d70782a3ae8..1501f2e3eba11374d50c2efe9d120c07ee208d4b 100644 GIT binary patch delta 1747 zcmah}O-vg{6n?YowH<8M2AddTJGL?Q)|kYEL~&?I>Xx50flzk~RE=a1F$-~IFdeT| zsXa7}dT3RtKboGJOD>U$nnNPz5aqGs08N+l3gda6{tSvydmWe;z6XXefK zz4v`HH&ahf$|{^EFAuMO>HJo17e*}iUkQ?9d0!Orfhgp~DCC7GOp`px4d7CI z*dr47#GfJN-|71M1W`LOqB+L%k2Ypb5jEfgHRywqyF^Z#OF$3jgSpr0Kf4|^H2ruV zzL+Pu?5;(??vZ%gfgITHBtCk~2Wof^Ui3fkBKy$xRqHzlDVh=3a}tv}eW1qJ13{6x zrXQP4QIVxDV75dl)NfItIz!+7oe} z_-v)(Vo}#@_M83vfiR}08+*`B09X-d3_ zkR-GVQ&Ia)8pmP8=An-*AL%9vOFR9w2S);gq}h`ue`-bCwO=nLqgfJ(2v0YpQhA}c zM9~n(nb$Ex6s9}0KICCY+Tv`n#H*obpZ`NY#~jWWNB`+c64zR32AMfAxGa1KL1 z&Wq+Zw(0;{?)frZDC;xWL*8%tIso*ucbYFXD**73m|oP9gofDPaxTl+Itx`wwIwr$ zcP=TI$ks!+53-Xoa-WpP!koLnQ)suD_eP`R2^wdsazGjcfH&EO93%?DXSis%idWM> zJxs5+*k>+8{lPVV#zZx&b6QE$HQIx~!p@czflFozK7v3PF0dhY)TA)6$2W(mbs0tN_JxU>;)oz+!o>TGGzbX#l{>p`r-vN6$6u zy2ZKf_OM&tXv79W^EOxnVXF!Hvt-q=c6RIqI7r8~!y*WqO|@RHmn1`PjaD8x(a*N+7j55_ql@(l2lRC3Tbg5N*IW0xZnfrYpcDTBm%~4X#sOfo_agi&Tigc#A_D-v z+I4N=Guu@Gz%Viyv7gdWVK zDq<7>@L6bOIdBdDrg$DqRg4i^X`51H0pPYGa+HVzfXPIju*vD1q!%Prh7v{xCYgah z52t!(2hxm{u&t$vCVvHQiZ1g&exN?oavIH!I7Z-jN2@Xeha>g}q{9!{?e%6$HZN!; z-o}0ue~RP-c6=Q9z%>ZNn060nAM&_0iU4CccGSz~xMmcZRZhrW^x zDDti_1Av8X>y5y>WW)BVud-H~ow_3y0f3acG%?zM_(LuCK+D~n-O>(jst1LEKMbvw z<){f#_P?!lrzxMnLX3P~j@6F@68-Ro-LgGf6iKD>64F)Vpo2A8A|eXM@kuPp46Md4 ze-ilSb}za$(Y)d{ozBbKCim5gj?)S(+)36cOeBiTz=ecZk+Qh>m>4H1NMZfNzYX`- zuy19&c4@uSu&e*kavA_m-bhX`qgP1g*ai8v{P4M@qCoyh=py38X+cn#EHo7f)PJ9Uf^pM<5hPU3kwD;T3Zyvgq-eMDf&dlG{ cwq}-JfW}7t=AaawE4_1ig5mdjj;RFo4^YGusQ>@~ diff --git a/backend/src/backend/routers/newsletter.py b/backend/src/backend/routers/newsletter.py new file mode 100644 index 0000000..a1702e1 --- /dev/null +++ b/backend/src/backend/routers/newsletter.py @@ -0,0 +1,17 @@ +from fastapi import Form +from fastapi import Depends +from fastapi import APIRouter + +router = APIRouter( + prefix="newsletter", + tags=[""], + dependencies=[], + responses={404: {"description": "Not found"}}, +) + +@router.post( + "/approve", + status_code=201 +) +def approve_newsletter(secret: str = Form()): + pass \ No newline at end of file diff --git a/backend/src/backend/routers/users.py b/backend/src/backend/routers/users.py index 2bf0f6d..668dbd4 100644 --- a/backend/src/backend/routers/users.py +++ b/backend/src/backend/routers/users.py @@ -24,7 +24,11 @@ router = APIRouter( responses={404: {"description": "Not found"}}, ) -@router.post("/users", status_code=201) +@router.post( + "/users", + status_code=201, + dependencies=[Depends(RateLimiter(limiter=Limiter(Rate(1, Duration.MINUTE))))] +) def register_user(new_user: NewUser, session: Session = Depends(get_session)) -> str: user = User.model_validate(new_user) @@ -69,6 +73,14 @@ def delete(current_user: User = Depends(get_current_user), session: Session = De session.delete(current_user) session.commit() +@router.delete("/me", status_code=201) +def delete(user_code: str = Form(), session: Session = Depends(get_session)) : + user = session.exec(select(User).where(User.user_code == user_code)).first() + + if user is not None: + session.delete(user) + session.commit() + @router.put("me/subscribe", status_code=201) def change_subscription(subscription: bool = Form(), current_user: User = Depends(get_current_user), session: Session = Depends(get_session)): current_user.subscription = subscription @@ -77,5 +89,6 @@ def change_subscription(subscription: bool = Form(), current_user: User = Depend # TODO: +# Template für Willkommen mit delete link # change mail <- token, new mail # delete all deactivated users after 48h \ No newline at end of file