env variables

This commit is contained in:
ebby 2026-09-27 13:15:11 +02:00
parent 91c13307aa
commit c4d64f6ac7
18 changed files with 44 additions and 27 deletions

View file

@ -2,6 +2,7 @@
"cSpell.language": "en,de-DE", "cSpell.language": "en,de-DE",
"cSpell.words": [ "cSpell.words": [
"Chiara", "Chiara",
"dotenv",
"Hobbithöhle", "Hobbithöhle",
"mailtrap", "mailtrap",
"Masala", "Masala",

4
backend/src/backend/.env Normal file
View file

@ -0,0 +1,4 @@
BACKEND_URL="http://localhost:8000"
FRONTEND_URL="http://localhost:4321"
SECRET="IamALocalSecretAndMustBeReplacedInProduction"
ENVIRONMENT="local"

Binary file not shown.

View file

@ -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"]

View file

@ -1,3 +1,5 @@
from backend.config import SECRET_KEY
import os
from fastapi.security import HTTPBasicCredentials from fastapi.security import HTTPBasicCredentials
from fastapi import Security from fastapi import Security
from fastapi.security import HTTPBearer from fastapi.security import HTTPBearer
@ -10,13 +12,11 @@ from backend.models.user import User
from backend.internal.database import get_session from backend.internal.database import get_session
from sqlmodel import Session from sqlmodel import Session
from fastapi import HTTPException from fastapi import HTTPException
from fastapi.security.oauth2 import OAuth2PasswordBearer
from fastapi import Depends from fastapi import Depends
from datetime import datetime from datetime import datetime
from datetime import timedelta from datetime import timedelta
SECRET_KEY = "secret-key"
ALGORITHM = "HS256" ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_DAYS = 360 ACCESS_TOKEN_EXPIRE_DAYS = 360

View file

@ -20,7 +20,7 @@
<span>Abbestellen</span> <span>Abbestellen</span>
</a> </a>
<a id="admin" href="https://blauwasser-mausis.de">Approve</a> <a id="admin" href="https://backend.blauwasser-mausis.de/?secret={{data.secret}}">Approve</a>
</div> </div>
</body> </body>

View file

@ -7,10 +7,12 @@
<body> <body>
<div> <div>
<h1>Willkommen, {{user.name}}</h1> <h1>Willkommen, {{data.name}}</h1>
<p>Du hast dich bei Blauwasser-Mausis.de angemeldet. Solltest du das nicht gewesen sein, dann lösche die Daten einfach über den untenstehenden Link.</p> <p>Du hast dich bei Blauwasser-Mausis.de angemeldet. Solltest du das nicht gewesen sein, dann lösche die Daten einfach über den untenstehenden Link.</p>
<a href="https://blauwasser-mausis.de/blog/bootsuche-england"> <p>Dein persönlicher Code, um alle Funktionen nutzen zu können: {{data.user_code}}</p>
<a href="https://backend.blauwasser-mausis.de/bootsuche-england">
<span>Daten löschen</span> <span>Daten löschen</span>
</a> </a>
</div> </div>

View file

@ -1,8 +1,8 @@
from backend.config import ENVIRONMENT
from mailtrap import Mail from mailtrap import Mail
import mailtrap as mt import mailtrap as mt
from jinja2 import Environment, FileSystemLoader from jinja2 import Environment, FileSystemLoader
class ArticleData(): class ArticleData():
def __init__(self, title, subtitle, description, link): def __init__(self, title, subtitle, description, link):
self.title=title self.title=title
@ -27,9 +27,6 @@ def send_newsletter_admin_approval(data: ArticleData ):
template = env.get_template('approval.jinja') template = env.get_template('approval.jinja')
output = template.render(data=data) output = template.render(data=data)
# with open("src/backend/internal/jinja_templates/output.html", "w") as f:
# f.write(output)
mail = mt.Mail( mail = mt.Mail(
sender=mt.Address(email="newsletter@blauwasser-mausis.de", name="Flaschenpost"), sender=mt.Address(email="newsletter@blauwasser-mausis.de", name="Flaschenpost"),
to=[mt.Address(email="blauwasser-mausis@proton.me")], to=[mt.Address(email="blauwasser-mausis@proton.me")],
@ -40,8 +37,15 @@ def send_newsletter_admin_approval(data: ArticleData ):
def send_mail(mail: Mail): def send_mail(mail: Mail):
client = mt.MailtrapClient(token="<YOUR_API_TOKEN>") if ENVIRONMENT == "local":
client.send(mail) print(f"Mail sent: {mail.subject}")
else:
client = mt.MailtrapClient(token="<YOUR_API_TOKEN>")
client.send(mail)
def send_batch_mail(): def send_batch_mail():
pass mt.BatchMail(
sender=mt.Address(email="newsletter@blauwasser-mausis.de", name="Flaschenpost"),
subject="Flaschenpost | Blauwasser-Mausis"
)

View file

@ -1,4 +1,5 @@
from backend.config import FRONTEND_URL
from backend.internal.authentication import create_access_token from backend.internal.authentication import create_access_token
from backend.internal.mail_util import AdminApprovalData from backend.internal.mail_util import AdminApprovalData
from backend.internal.mail_util import send_newsletter_admin_approval from backend.internal.mail_util import send_newsletter_admin_approval
@ -6,15 +7,13 @@ from datetime import timedelta
from datetime import datetime from datetime import datetime
import feedparser import feedparser
FEED_URL="http://localhost:4321/rss.xml"
def check_blog_rss_and_send_admin_mail(): 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: for article in feed.entries:
date_string = str(article["published"]) date_string = str(article["published"])
date_object = datetime.strptime(date_string, '%a, %d %b %Y %H:%M:%S %Z') 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"]) title = str(article["title"])
description = str(article["summary"]) description = str(article["summary"])
subtitle = str(article["subtitle"]) subtitle = str(article["subtitle"])

View file

@ -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 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 backend.internal.database import create_db_and_tables
from fastapi import APIRouter from fastapi import APIRouter
from fastapi import FastAPI from fastapi import FastAPI
from fastapi_crons import Crons, get_cron_router from fastapi_crons import Crons
# TODO: Newsletter # TODO: Newsletter
# TODO: env
# TODO: TLS # TODO: TLS
# TODO: Deploy # TODO: Deploy
@ -26,4 +28,5 @@ def on_startup():
router = APIRouter() router = APIRouter()
app.include_router(users.router) app.include_router(users.router)
app.include_router(comments.router) app.include_router(comments.router)
app.include_router(newsletters.router)

View file

@ -1,9 +1,8 @@
from fastapi import Form from fastapi import Form
from fastapi import Depends
from fastapi import APIRouter from fastapi import APIRouter
router = APIRouter( router = APIRouter(
prefix="newsletter", prefix="/newsletter",
tags=[""], tags=[""],
dependencies=[], dependencies=[],
responses={404: {"description": "Not found"}}, responses={404: {"description": "Not found"}},

View file

@ -18,14 +18,13 @@ from fastapi import APIRouter
from fastapi_limiter.depends import RateLimiter from fastapi_limiter.depends import RateLimiter
router = APIRouter( router = APIRouter(
prefix="", prefix="/users",
tags=[""],
dependencies=[], dependencies=[],
responses={404: {"description": "Not found"}}, responses={404: {"description": "Not found"}},
) )
@router.post( @router.post(
"/users", "/",
status_code=201, status_code=201,
dependencies=[Depends(RateLimiter(limiter=Limiter(Rate(1, Duration.MINUTE))))] 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}) return create_access_token({"sub": user.user_code})
@router.post( @router.post(
"users/forgot", "/forgot",
dependencies=[Depends(RateLimiter(limiter=Limiter(Rate(1, Duration.MINUTE))))] dependencies=[Depends(RateLimiter(limiter=Limiter(Rate(1, Duration.MINUTE))))]
) )
def forgot_user_code(email: str = Form(), session: Session = Depends(get_session)): def forgot_user_code(email: str = Form(), session: Session = Depends(get_session)):