feat: authentication

This commit is contained in:
Leon
2025-07-19 10:12:11 +02:00
parent 95170e7201
commit 6f7503039d
57 changed files with 1405 additions and 244 deletions

View File

@@ -86,16 +86,25 @@ def update_newsletter(
db_newsletter.move_to_folder = newsletter_update.move_to_folder
db_newsletter.extract_content = newsletter_update.extract_content
# Simple approach: delete existing senders and add new ones
# More efficient sender update
existing_emails = {sender.email for sender in db_newsletter.senders}
new_emails = set(newsletter_update.sender_emails)
# Remove senders that are no longer in the list
for sender in db_newsletter.senders:
db.delete(sender)
db.commit()
if sender.email not in new_emails:
db.delete(sender)
for email in newsletter_update.sender_emails:
db_sender = Sender(id=generate(), email=email, newsletter_id=db_newsletter.id)
db.add(db_sender)
# Add new senders
for email in new_emails:
if email not in existing_emails:
db_sender = Sender(
id=generate(), email=email, newsletter_id=db_newsletter.id
)
db.add(db_sender)
db.commit()
db.refresh(db_newsletter)
logger.info(f"Successfully updated newsletter with id={db_newsletter.id}")
return get_newsletter(db, newsletter_id)

View File

@@ -1,6 +1,7 @@
from sqlalchemy.orm import Session
from app.core.config import settings as env_settings
from app.core.hashing import get_password_hash
from app.core.logging import get_logger
from app.models.settings import Settings as SettingsModel
from app.schemas.settings import Settings as SettingsSchema
@@ -9,11 +10,10 @@ from app.schemas.settings import SettingsCreate
logger = get_logger(__name__)
def get_settings(db: Session, with_password: bool = False) -> SettingsSchema:
"""Retrieve application settings, prioritizing environment variables over database."""
logger.debug("Querying for settings")
def create_initial_settings(db: Session):
"""Create initial settings in the database if they don't exist."""
logger.debug("Checking for initial settings.")
db_settings = db.query(SettingsModel).first()
if not db_settings:
logger.info(
"No settings found in the database, creating new default settings from environment variables."
@@ -25,12 +25,29 @@ def get_settings(db: Session, with_password: bool = False) -> SettingsSchema:
k: v for k, v in env_settings.model_dump().items() if k in model_fields
}
if env_settings.auth_password:
env_data_for_db["auth_password_hash"] = get_password_hash(
env_settings.auth_password
)
if "auth_password" in env_data_for_db:
del env_data_for_db["auth_password"]
db_settings = SettingsModel(**env_data_for_db)
db.add(db_settings)
db.commit()
db.refresh(db_settings)
logger.info("Default settings created from environment variables.")
def get_settings(db: Session, with_password: bool = False) -> SettingsSchema:
"""Retrieve application settings, prioritizing environment variables over database."""
logger.debug("Querying for settings")
db_settings = db.query(SettingsModel).first()
if not db_settings:
# This should not happen if create_initial_settings is called at startup.
raise RuntimeError("Settings not initialized.")
# Build dictionary from DB model attributes, handling possible None values
db_data = {
"id": db_settings.id,
@@ -41,6 +58,7 @@ def get_settings(db: Session, with_password: bool = False) -> SettingsSchema:
"mark_as_read": db_settings.mark_as_read,
"email_check_interval": db_settings.email_check_interval,
"auto_add_new_senders": db_settings.auto_add_new_senders,
"auth_username": db_settings.auth_username,
}
# Get all environment settings that were explicitly set.
@@ -80,14 +98,22 @@ def create_or_update_settings(db: Session, settings: SettingsCreate):
db_settings = SettingsModel()
db.add(db_settings)
update_data = settings.model_dump()
update_data = settings.model_dump(exclude_unset=True)
# Do not update fields that are set by environment variables
locked_fields = list(env_settings.model_dump(exclude_unset=True).keys())
logger.debug(f"Fields locked by environment variables: {locked_fields}")
for key, value in update_data.items():
if key not in locked_fields:
if key in locked_fields:
continue
if key == "auth_password":
if value:
db_settings.auth_password_hash = get_password_hash(value)
else:
db_settings.auth_password_hash = None
elif hasattr(db_settings, key):
setattr(db_settings, key, value)
db.commit()