From c4d64f6ac7d8e3a6177ecacabbf64e1625928e98 Mon Sep 17 00:00:00 2001
From: ebby
Date: Sun, 27 Sep 2026 13:15:11 +0200
Subject: [PATCH] env variables
---
.vscode/settings.json | 1 +
backend/src/backend/.env | 4 ++++
.../__pycache__/config.cpython-314.pyc | Bin 0 -> 484 bytes
.../backend/__pycache__/main.cpython-314.pyc | Bin 1262 -> 1397 bytes
backend/src/backend/config.py | 6 ++++++
.../authentication.cpython-314.pyc | Bin 3552 -> 3515 bytes
.../__pycache__/mail_util.cpython-314.pyc | Bin 3313 -> 3696 bytes
.../__pycache__/rss_reader.cpython-314.pyc | Bin 1558 -> 1583 bytes
.../src/backend/internal/authentication.py | 4 ++--
.../internal/jinja_templates/approval.jinja | 2 +-
.../internal/jinja_templates/welcome.jinja | 6 ++++--
backend/src/backend/internal/mail_util.py | 18 +++++++++++-------
backend/src/backend/internal/rss_reader.py | 9 ++++-----
backend/src/backend/main.py | 11 +++++++----
.../__pycache__/newsletters.cpython-314.pyc | Bin 0 -> 837 bytes
.../routers/__pycache__/users.cpython-314.pyc | Bin 6354 -> 6335 bytes
.../routers/{newsletter.py => newsletters.py} | 3 +--
backend/src/backend/routers/users.py | 7 +++----
18 files changed, 44 insertions(+), 27 deletions(-)
create mode 100644 backend/src/backend/.env
create mode 100644 backend/src/backend/__pycache__/config.cpython-314.pyc
create mode 100644 backend/src/backend/config.py
create mode 100644 backend/src/backend/routers/__pycache__/newsletters.cpython-314.pyc
rename backend/src/backend/routers/{newsletter.py => newsletters.py} (83%)
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 31aa94b..7c7e6a0 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -2,6 +2,7 @@
"cSpell.language": "en,de-DE",
"cSpell.words": [
"Chiara",
+ "dotenv",
"Hobbithöhle",
"mailtrap",
"Masala",
diff --git a/backend/src/backend/.env b/backend/src/backend/.env
new file mode 100644
index 0000000..6bff5c7
--- /dev/null
+++ b/backend/src/backend/.env
@@ -0,0 +1,4 @@
+BACKEND_URL="http://localhost:8000"
+FRONTEND_URL="http://localhost:4321"
+SECRET="IamALocalSecretAndMustBeReplacedInProduction"
+ENVIRONMENT="local"
\ No newline at end of file
diff --git a/backend/src/backend/__pycache__/config.cpython-314.pyc b/backend/src/backend/__pycache__/config.cpython-314.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d9ad86485fc9c7c78ca0a9772e0e441083cae60a
GIT binary patch
literal 484
zcmZ{eK}*757{~wHbeVHn*Pugm2r1kbh$wA=Xfvh-2_6#n0&z8k1D*Dy`?Vb5$!aF|Vd{wZI~0
zdQK~-+G*)h&oU`_lFG~=E;8P6*&4Asb?Vqu0Kme(Yo&~OO@jca2;c>i=>?WmYEF|V
z#4x%_-mFnlH@v!Q)|3`?EMj`Dl5DieL)jzLXgF2HD4X}ht|%@w|GMeeclBzb)n%c>
zrc-G*$PtwRZ~)w60AB*fac@|Ek8TXCzBSw)MfZGZEXM}LesLHY$vb{{9NQf9`n_Rd
P6pQ*w`!}@(Llj#!Ut(kl1BBDMBn#
z2|fViJ^#Q8exnk!)KbI-7HoJd*swxl7l;5ci>o{LoO2&D_fzp($vkVBB>;Hz{ng!r
zXXf1aIRSRD370sq2`5c>WEmTR1E47o$&qZC%S~(&S9S`v!WCQPs;zM?!wZgX7kM%B
z6{lny+{k>@DcNOS&V0==ZHrq?c;(;OdBq!B%kU~2BrnISUbWN8{psWCZqY4Wkn)&o
zG=4S6YhI+lPt`8m4CwO|6whI7w4=N
z+LezYeVe4lAPRbZFXA-ZNycP#NlukfOj(@j-Do(ZA&*ldqz~c&<(#tQB{{E?RJqEc
zFis@NCxv873Y8fE_2i9o>qZp-D++T=n3^zk0BI=-{g?-gkG5F@z$}1Rhxq3Ah1vbW
ze8#=rZlr474wC^S_vNMAiqLB;8ga^ErizrBFhZTqZ3W$XH0-VQLrz&34Ay!954M7s
zGO<#rb|;8=u-#{dkd#HpJPP?;F$Ob}&+>_}7$Mc8(5E{zvz0EnfDUjXRmVY~^GWl2U+vNKChZ*CI*
zg6Tiw#sAAr4q-#71OFGvbnmgqg7wHDsgCd2C0Hbn4uS?Z}mGoi}1H@}(a&Wiv$P
zZeWMz0FXiEZy*bH*!*}^
zIdc}quVg{ezhqolW+q#J+GA_o|KmK_QoC&3PlF!%tslfxU)jBmp{+@ki%L6(MOjpO=~XTVhoUS7qMXQFsLU8JQ++fFYXv|@ZJRHiECCQUxi+~Dxn%&_
zD~mxTheA%qVif?L$^q@@JHL6(Z`HN?{p;$BdFL7@iancC35&WkRGWv-iJ|S6!%7av
zuZ2qhtz8H6r&?eod;*#Tn8Wc{TO_;EoPr>++9``cev%hbtg5$s{qa9)o!wD+G=q
p#3lgRZ*>OXm&q8L;@Ji6PVs1p+f%GvVEcDled8z2IePUc{sQQuex(2a
diff --git a/backend/src/backend/config.py b/backend/src/backend/config.py
new file mode 100644
index 0000000..e2ab97c
--- /dev/null
+++ b/backend/src/backend/config.py
@@ -0,0 +1,6 @@
+import os
+
+ENVIRONMENT = os.environ["ENVIRONMENT"]
+SECRET_KEY = os.environ["SECRET"]
+FRONTEND_URL = os.environ["FRONTEND_URL"]
+BACKEND_URL = os.environ["BACKEND_URL"]
diff --git a/backend/src/backend/internal/__pycache__/authentication.cpython-314.pyc b/backend/src/backend/internal/__pycache__/authentication.cpython-314.pyc
index cc0e7fccbfff5bd7a19a642fd4bf691de5ba6091..6c8df753c68c3db74ac05afe862c57b2b15f183a 100644
GIT binary patch
delta 711
zcmXw$O;1xn6o${-_I~u{#hQKjZZiiR!!}Pb7hS^+x0#2YVV7r^kG^4#2Q0+U
zu*E6TO%NF#u`Fgy&*wQdf=44p1bmd`F>g5J5i4N9Fy%HYV$pEKZC1jP;VchWfPvv0
z4_J(G6~qXRiBT+zvdG6E3NiF@J%Zy+w+0RUXaK-U)2TtT(jb?5V}Xcb45D;po@kb8
z(44p)8wO=It
z?fLegztioQ+nia0p}HUDAEixfr!~aZURTKt=JYtD
z%arzb!&kkRgYBdzef2RclR$k5tC>*GDFA$+#qqipvzO+iy)V0XC>M2aO*Lpe`vw3m
eQiPCmnEC-3wMD1H$~jD)!;K3EXh9v*2mb+Yu#v<7
delta 765
zcmX|-&rcIU6vyA}ZoAv$VZ)r7YNBMJ0_*5Mm&5P!OGo2F++pj25#gi-OhS>?8cR
zz|pIjnI+?aju
zSNE?GfCE?oP8d*vq^8(l1~t*tY%-u0TAD3p&0b0O<<~-Za(;^nN@t8qNSkmmXL0ZPL=71Trf)&jJ%%KiCnhVUK
zLpW3eUc``>aF`Ebm5=ap2)q(Pr_dod(z3>3Mm-n+Flw3O(28crsh=i%XfXsH_M1mr
zm2qf|p2gY~&fK)YheP1ie(xB!>o6JpRVT?k@|Y~kALK@*eE;SazP$P%PSfqKSY1eB
zkqGG<7rZ?;P1+*CE3cB>-jwmdAddWQ&3i}g!=**O^yvBBr6S!UjFd;pj<
z#Ed+&&yzX%&HkEg0)X&(@0`#eQ}WQQPh3)!%K&g>zDQ808DT4HB|Ax5iAGcP%
zu5eyO_GY}>>Bg(#mW=WZLgk(OZ@J)=?wLAWi&Km@*M+49GD@%b=+-sWA$Ys
zP%Q&Wic0=JP1KcboG$3kh&ffGvgp@y2LNzl5<=vnf3ZA!4AC)+9mBbkECeG5?oV$}
IZuz(W0R)Yrd;kCd
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 5b2352419e954d30ee4845a2feb4e52cd4315c95..e56b7ef3fb493b42a172da8f0319506d59559769 100644
GIT binary patch
delta 1534
zcmZ`(O>7%Q6n^9V_u3mfb>lccjg!!%ON2#3M5+=Znx86e6DOKN04Wr0?4@<;I??P#
zNan{C7oZ0kG!+UbkT?}_L6s`Rg)0}N2t}n@QX!#m;MRy#5uDJQwOa_{9o~-KzWL^R
z-+MEAnFn3*AuApQ0QmCHZ&vm{j%Vuc0>Cx62$bYuhWMlh*O7c=M)D=Gmhur_z6ey#
zD>JIE&S<{Y14p43sFDV%jzka+z}H1gO9Rzk(?_I6)SyNhXfzF#gde458fZ+cO&U*w
zAEOzmA8hM)%(h8jP8SyQbiOb*U3l^9FEo;f0RW4mv(UBN{+6`=H_CsF43Q+aq$}wZ
z0?Cc+N1J1OLmDHk{0C{Wtpfl&0st?tBqkWb@d5dmikq3i&&l7NGZ9A$f3^ZZpn7hR
zxxTHk1ZEv3hA|tFRR9ERFCHmcf7^gevx33%7J~Ssgzi
zDj@>2z`8N<_#x(l7#!p)YJ>S8|45xWkB0vz^=ZKp78YkdRbV$HEB1Yf<
zOp@9|_f@C(u+;5t?Iuxj0Pq*Tqvyyi{+pg7BRplCRIyH`@$<&9UIkCo&Xh{b^*o_W
zV0dn|^!in&T(K3F1hwkQ-_%Kwih#hVkqTxXP@wupUsTl_fr(OXlbpmw3l7u5BjFLrIkaSF)a4^-pJO
ziLqDbU!uHfw$)XJt5NjBkWnsMnMX;6l!8jIDYXm
z3d5cUfLkDFit_70i
diff --git a/backend/src/backend/internal/mail_util.py b/backend/src/backend/internal/mail_util.py
index d8695b1..d8bc083 100644
--- a/backend/src/backend/internal/mail_util.py
+++ b/backend/src/backend/internal/mail_util.py
@@ -1,8 +1,8 @@
+from backend.config import ENVIRONMENT
from mailtrap import Mail
import mailtrap as mt
from jinja2 import Environment, FileSystemLoader
-
class ArticleData():
def __init__(self, title, subtitle, description, link):
self.title=title
@@ -27,9 +27,6 @@ def send_newsletter_admin_approval(data: ArticleData ):
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)
-
mail = mt.Mail(
sender=mt.Address(email="newsletter@blauwasser-mausis.de", name="Flaschenpost"),
to=[mt.Address(email="blauwasser-mausis@proton.me")],
@@ -40,8 +37,15 @@ def send_newsletter_admin_approval(data: ArticleData ):
def send_mail(mail: Mail):
- client = mt.MailtrapClient(token="")
- client.send(mail)
+ if ENVIRONMENT == "local":
+ print(f"Mail sent: {mail.subject}")
+ else:
+ client = mt.MailtrapClient(token="")
+ client.send(mail)
def send_batch_mail():
- pass
+ mt.BatchMail(
+ sender=mt.Address(email="newsletter@blauwasser-mausis.de", name="Flaschenpost"),
+ subject="Flaschenpost | Blauwasser-Mausis"
+
+ )
diff --git a/backend/src/backend/internal/rss_reader.py b/backend/src/backend/internal/rss_reader.py
index c493567..0e2cb24 100644
--- a/backend/src/backend/internal/rss_reader.py
+++ b/backend/src/backend/internal/rss_reader.py
@@ -1,4 +1,5 @@
+from backend.config import FRONTEND_URL
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
@@ -6,15 +7,13 @@ from datetime import timedelta
from datetime import datetime
import feedparser
-FEED_URL="http://localhost:4321/rss.xml"
-
def check_blog_rss_and_send_admin_mail():
- feed = feedparser.parse(FEED_URL)
+ feed = feedparser.parse(f"{FRONTEND_URL}/rss.xml")
for article in feed.entries:
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=1)):
+
+ if date_object > (datetime.now() - timedelta(days=16)):
title = str(article["title"])
description = str(article["summary"])
subtitle = str(article["subtitle"])
diff --git a/backend/src/backend/main.py b/backend/src/backend/main.py
index 29f49af..e93600f 100644
--- a/backend/src/backend/main.py
+++ b/backend/src/backend/main.py
@@ -1,13 +1,15 @@
+from dotenv import load_dotenv
+load_dotenv()
+
from backend.internal.rss_reader import check_blog_rss_and_send_admin_mail
-from .routers import users, comments
+from .routers import users, comments, newsletters
from backend.internal.database import create_db_and_tables
from fastapi import APIRouter
from fastapi import FastAPI
-from fastapi_crons import Crons, get_cron_router
+from fastapi_crons import Crons
# TODO: Newsletter
-# TODO: env
# TODO: TLS
# TODO: Deploy
@@ -26,4 +28,5 @@ def on_startup():
router = APIRouter()
app.include_router(users.router)
-app.include_router(comments.router)
\ No newline at end of file
+app.include_router(comments.router)
+app.include_router(newsletters.router)
\ No newline at end of file
diff --git a/backend/src/backend/routers/__pycache__/newsletters.cpython-314.pyc b/backend/src/backend/routers/__pycache__/newsletters.cpython-314.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..8ae85747be1c5eaf21d89d8357ce422beaedd009
GIT binary patch
literal 837
zcmYjPL2DC16n<}Zv&|-H+NRYOtJGR4tc9+kP!A&LL0W`TM<@uUVY54FwkA8v%*5KB
zDhT%I!J`MklmEcK;H}3n(1UpDtu;ljGMmKuU}xXVd*6HS`(~EPqXhtflk;yoO9=4O
zY=)K}IK4vvIDjpnxCX1JaL)K-4OWRFb5JGoKrL!7<1)}3b?AtXKGOV(-N!4dYHhf~
zq8CQpt?#t3Li#6FoQHdZ;9aD}X`rQPXpOgUc&c)AbOF5biOKR%+fTS?d#K$<8*7wz
z6chVJKViGF#gt+~L;Mi|bTMKw6mhCzp6t8pTwQPQP7-;xc2dC_@f&TcU|Z@^#8Q?-
zED2*KwJVrRc_NwI&-+1|3jUgTsEbkssv~P5k64HRU_N7pg#`e;o0(Rdutn~_1Bfhu
ztMCk)Nb%($6~M;@@W_e5Xh*V8Fy*1Pq!J!#r@=)#P|{Ssp-0P)q*79Dp0Ie
z6BPg$0{}Uh5%>d$?wMIW$?VrN(`S^2W(LeCI~jt)0(iLo6+9GWQ^>>@#e^YQ87Nr0
zxE^sC0E#AWB!iz7Am<9xeBE>ONF$IcNMm6d2=kD%)2E^BluMPN#U&Fokbal^gEo&k
zE%s1c8QhFCnx9&TcnmYgaP5a%=@w_Yh0@_vcVe#T)?QGXBcgH7Bb3jIWU=ebbhs9f8Hh&vQdagytuRLOZ;J*n`#ex6;
literal 0
HcmV?d00001
diff --git a/backend/src/backend/routers/__pycache__/users.cpython-314.pyc b/backend/src/backend/routers/__pycache__/users.cpython-314.pyc
index 1501f2e3eba11374d50c2efe9d120c07ee208d4b..a18358a3a8fe0cec3df26d45ea920348cdb5de6a 100644
GIT binary patch
delta 1310
zcmaizOHUI~6vxl)v_tKKwzRy2@F+O6U?`OcXd1#pG+Kf@T&bji_ELwmo#xIoA*^sk
z;!3<<0K-N$sOiR)`Vk1mNJf_$T^UUXYjf^^RYKCu$>h#G=lst9f9^s2UEJGO>vaJD
zd^vivy0+zQCKFpd-<$ejJ~UrH-w-1)GT%5X;SB(zmA@yA<#BSu?p&8+C7m*zZ#vq>
zB~vakx}vU`o(wJ0LWUO7D%H&kjOsu_!TXa%x^RD2v)mw{9#MB|VkaGL$v#
z{B{t>B>-qIAIq=E)ph`29ROh3v5QHlZU+EG>F8kHc
zL@gBM1jCWjvTA`{2Y}1`wL2A10ARf)wxY4DW<&{V;?I4vR}ji{(EO5`6H~FlDkus5
z!qa7;@Nb@%_ak^;WB9W>Am9>)KV-@
zqlC30@t7d?q)Uv^f|VnrjM}Wuauxmw{;{@8#TFv%b
zJmN>Kr~NBK7NRLjW7g5T4
z0T)S%=FW3X7CVS0TV0WhT|2vt6`~}Uf)9woQ^D1w<)mI(*3(Qa8md;P%oCMN`?99x
zEK{oqb&rQaeMI47AvPmeC3YJ@dNBy8P7eNBaPnAA%nha=Efumf^&iVL04zMK?;%P#
zQr|~r@gSTaQFE->6OYkQoDyp}2D=qOtR0DR(l
znC~=9b_Wjw!9!o&)5Y!NerRC7HhxrNciA@NUmmbIH(MUJ9NKHRuW^rf%WoU~#EvEZ
E0O64nL;wH)
delta 1313
zcmaizO-vI}5Xa|rx0}*0T3SkIBSO(`N|hF(A`19XL8O3K_26d%Wm`*1m%QC3hIqh}
z8ZVL;FP^xNNKBNZ7jGWDa3FYq?8$?P2V*2gJ&|bUEeINtUM8EjZ)Sco|Nnc}vDV>=
zxm|VufW`HCt&O%>DPGnTs<9PoNDKl1Q)@1QO?2Y|As&iNJa0CcmDt|1pk7vj@Ol+Xi6
ze3lbCvt>$^l9|KT9JQF8r7HYM_TG*BU);mDIlG0Y&^9yg+>SgEbC>mbMbGSQmMN5S
zDop~wdAy3M&cP>#Z`~1IbA%UqJ~$GqVuH%Z+QsdFCHd$(h}E1h$bue3?DOPKn23fn
zsT37mp+}I?vRhKKaN$iW4PYY-7n$K{Asiv`pChZuJHj4#TZvp*@Y+d=H@EGpE%!KT
zYj#C0dg^~C?h*~NpLMs0%&z#RQl@}fc|yz5!i-)}OS|(#1w))r)uO3owMAWLl0PP)
zMY00hbo*J#e`AzG3v>vHVi@?&wh#VlvHfDURrY1?jhFID<{zjL0Jz4!`(+|mg7q;n
zhR@uPuJ$J{k6z%fi~H0N@`}z4!N)a(nX=Avmw+Og=_6auv^rTXDt+`W0O0%AWcECe
zjJh`L&d2@@uWzHa?%AD%)T%$R>hAbaW3^l6q)j(iY>z?@LmQ%#Z3SMFI`%uz!d4o-
HiCFp%2gnrO
diff --git a/backend/src/backend/routers/newsletter.py b/backend/src/backend/routers/newsletters.py
similarity index 83%
rename from backend/src/backend/routers/newsletter.py
rename to backend/src/backend/routers/newsletters.py
index a1702e1..0b37d7a 100644
--- a/backend/src/backend/routers/newsletter.py
+++ b/backend/src/backend/routers/newsletters.py
@@ -1,9 +1,8 @@
from fastapi import Form
-from fastapi import Depends
from fastapi import APIRouter
router = APIRouter(
- prefix="newsletter",
+ prefix="/newsletter",
tags=[""],
dependencies=[],
responses={404: {"description": "Not found"}},
diff --git a/backend/src/backend/routers/users.py b/backend/src/backend/routers/users.py
index 668dbd4..00949a4 100644
--- a/backend/src/backend/routers/users.py
+++ b/backend/src/backend/routers/users.py
@@ -18,14 +18,13 @@ from fastapi import APIRouter
from fastapi_limiter.depends import RateLimiter
router = APIRouter(
- prefix="",
- tags=[""],
+ prefix="/users",
dependencies=[],
responses={404: {"description": "Not found"}},
)
@router.post(
- "/users",
+ "/",
status_code=201,
dependencies=[Depends(RateLimiter(limiter=Limiter(Rate(1, Duration.MINUTE))))]
)
@@ -55,7 +54,7 @@ def login(user_code: str = Form(), session: Session = Depends(get_session)) -> s
return create_access_token({"sub": user.user_code})
@router.post(
- "users/forgot",
+ "/forgot",
dependencies=[Depends(RateLimiter(limiter=Limiter(Rate(1, Duration.MINUTE))))]
)
def forgot_user_code(email: str = Form(), session: Session = Depends(get_session)):