big update i guess

This commit is contained in:
2026-03-26 18:55:15 +01:00
parent 1bbabd6c4d
commit 3f3609c944
12 changed files with 511 additions and 104 deletions

View File

@@ -7,6 +7,7 @@ import uvicorn
from fastapi import FastAPI, HTTPException
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles
from sqlalchemy import text
sys.path.insert(0, str(Path(__file__).parent))
@@ -18,6 +19,21 @@ logging.basicConfig(level=logging.INFO)
# Create DB tables on startup
Base.metadata.create_all(bind=engine)
# Run column migrations for new fields (safe: only adds if not exists)
def _migrate():
with engine.connect() as conn:
# Add week_start_day to user_settings if not present
try:
conn.execute(text(
"ALTER TABLE user_settings ADD COLUMN week_start_day VARCHAR(10) DEFAULT 'monday'"
))
conn.commit()
logging.info("Migration: added week_start_day column")
except Exception:
pass # Column already exists
_migrate()
app = FastAPI(title="Calendarr", docs_url=None, redoc_url=None)
app.include_router(auth_router.router, prefix="/api/auth", tags=["auth"])

View File

@@ -60,6 +60,7 @@ class UserSettings(Base):
id = Column(Integer, primary_key=True, index=True)
user_id = Column(Integer, ForeignKey("users.id"), unique=True, nullable=False)
default_view = Column(String(20), default="month")
week_start_day = Column(String(10), default="monday")
primary_color = Column(String(7), default="#4285f4")
accent_color = Column(String(7), default="#ea4335")
today_color = Column(String(7), default="#4285f4")

View File

@@ -6,7 +6,7 @@ from typing import Optional
import pyotp
import qrcode
from fastapi import APIRouter, Depends, File, HTTPException, UploadFile
from fastapi.responses import FileResponse
from fastapi.responses import FileResponse, Response
from PIL import Image
from pydantic import BaseModel
from sqlalchemy.orm import Session
@@ -80,10 +80,19 @@ async def upload_avatar(
if len(data) > MAX_AVATAR_SIZE:
raise HTTPException(400, "Datei zu groß (max. 5 MB)")
# Resize to 256x256
# Resize to 512x512 square
img = Image.open(io.BytesIO(data))
img = img.convert("RGB")
img.thumbnail((512, 512))
# Use resize instead of thumbnail to ensure exact dimensions
# If already cropped (square), this just resizes; otherwise fit to 512x512
w, h = img.size
if w != h:
# Crop to square center
side = min(w, h)
left = (w - side) // 2
top = (h - side) // 2
img = img.crop((left, top, left + side, top + side))
img = img.resize((512, 512), Image.LANCZOS)
filename = f"user_{current_user.id}.jpg"
path = AVATAR_DIR / filename
@@ -101,7 +110,11 @@ def get_avatar(current_user: models.User = Depends(get_current_user)):
path = AVATAR_DIR / current_user.avatar_filename
if not path.exists():
raise HTTPException(404, "Kein Profilbild")
return FileResponse(str(path), media_type="image/jpeg")
return FileResponse(
str(path),
media_type="image/jpeg",
headers={"Cache-Control": "no-cache, no-store, must-revalidate"},
)
@router.get("/avatar/{user_id}")

View File

@@ -13,6 +13,7 @@ router = APIRouter()
class SettingsUpdate(BaseModel):
default_view: Optional[str] = None
week_start_day: Optional[str] = None
primary_color: Optional[str] = None
accent_color: Optional[str] = None
today_color: Optional[str] = None
@@ -22,6 +23,7 @@ class SettingsUpdate(BaseModel):
def _settings_dict(s: models.UserSettings) -> dict:
return {
"default_view": s.default_view,
"week_start_day": s.week_start_day or "monday",
"primary_color": s.primary_color,
"accent_color": s.accent_color,
"today_color": s.today_color,