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 0000000..d9ad864 Binary files /dev/null and b/backend/src/backend/__pycache__/config.cpython-314.pyc differ diff --git a/backend/src/backend/__pycache__/main.cpython-314.pyc b/backend/src/backend/__pycache__/main.cpython-314.pyc index 980e683..f28ff91 100644 Binary files a/backend/src/backend/__pycache__/main.cpython-314.pyc and b/backend/src/backend/__pycache__/main.cpython-314.pyc differ 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 cc0e7fc..6c8df75 100644 Binary files a/backend/src/backend/internal/__pycache__/authentication.cpython-314.pyc and b/backend/src/backend/internal/__pycache__/authentication.cpython-314.pyc differ 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 5b23524..e56b7ef 100644 Binary files a/backend/src/backend/internal/__pycache__/mail_util.cpython-314.pyc and b/backend/src/backend/internal/__pycache__/mail_util.cpython-314.pyc differ diff --git a/backend/src/backend/internal/__pycache__/rss_reader.cpython-314.pyc b/backend/src/backend/internal/__pycache__/rss_reader.cpython-314.pyc index 6d5cb1e..3fe9348 100644 Binary files a/backend/src/backend/internal/__pycache__/rss_reader.cpython-314.pyc and b/backend/src/backend/internal/__pycache__/rss_reader.cpython-314.pyc differ diff --git a/backend/src/backend/internal/authentication.py b/backend/src/backend/internal/authentication.py index c284964..478e03e 100644 --- a/backend/src/backend/internal/authentication.py +++ b/backend/src/backend/internal/authentication.py @@ -1,3 +1,5 @@ +from backend.config import SECRET_KEY +import os from fastapi.security import HTTPBasicCredentials from fastapi import Security from fastapi.security import HTTPBearer @@ -10,13 +12,11 @@ from backend.models.user import User from backend.internal.database import get_session from sqlmodel import Session from fastapi import HTTPException -from fastapi.security.oauth2 import OAuth2PasswordBearer from fastapi import Depends from datetime import datetime from datetime import timedelta -SECRET_KEY = "secret-key" ALGORITHM = "HS256" ACCESS_TOKEN_EXPIRE_DAYS = 360 diff --git a/backend/src/backend/internal/jinja_templates/approval.jinja b/backend/src/backend/internal/jinja_templates/approval.jinja index 4ae4767..d95ae11 100644 --- a/backend/src/backend/internal/jinja_templates/approval.jinja +++ b/backend/src/backend/internal/jinja_templates/approval.jinja @@ -20,7 +20,7 @@ Abbestellen - Approve + Approve diff --git a/backend/src/backend/internal/jinja_templates/welcome.jinja b/backend/src/backend/internal/jinja_templates/welcome.jinja index b7a0285..d6ad6f6 100644 --- a/backend/src/backend/internal/jinja_templates/welcome.jinja +++ b/backend/src/backend/internal/jinja_templates/welcome.jinja @@ -7,10 +7,12 @@
-

Willkommen, {{user.name}}

+

Willkommen, {{data.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.

- +

Dein persönlicher Code, um alle Funktionen nutzen zu können: {{data.user_code}}

+ +
Daten löschen
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 0000000..8ae8574 Binary files /dev/null and b/backend/src/backend/routers/__pycache__/newsletters.cpython-314.pyc differ diff --git a/backend/src/backend/routers/__pycache__/users.cpython-314.pyc b/backend/src/backend/routers/__pycache__/users.cpython-314.pyc index 1501f2e..a18358a 100644 Binary files a/backend/src/backend/routers/__pycache__/users.cpython-314.pyc and b/backend/src/backend/routers/__pycache__/users.cpython-314.pyc differ 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)):