Files
boc/landvex-admin-backend/app/routers/content.py
T
Bernt aee0f09db8 landvex: Fixar och tester klara för alla komponenter
- Datafabrik: Dockerfile fix, agentorkestrering fungerar
- Vision: Identify-modell, FAISS, OCR alla testade
- API: Alla 7 integrationstester passerade
- Upplösare: Entitetsupplösning verifierad
2026-07-05 06:41:32 +00:00

223 lines
7.2 KiB
Python

"""
Content Management Module
Handles articles, SEO metadata, and content publishing
"""
from fastapi import APIRouter, Depends, HTTPException, status, Query
from sqlalchemy.orm import Session
from typing import List, Optional
from datetime import datetime
from app.database import get_db
from app.models import Article, SEOMetadata, ArticleStatus, User
from app.core.security import get_current_user
router = APIRouter(prefix="/content", tags=["content"])
# ─── ARTICLES ─────────────────────────────────────────────────────────────────
@router.get("/articles")
async def list_articles(
status: Optional[ArticleStatus] = None,
skip: int = 0,
limit: int = 100,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""List all articles with optional filtering."""
query = db.query(Article)
if status:
query = query.filter(Article.status == status)
articles = query.offset(skip).limit(limit).all()
return {
"articles": [
{
"id": a.id,
"title": a.title,
"slug": a.slug,
"status": a.status.value,
"author": a.author.full_name if a.author else None,
"published_at": a.published_at.isoformat() if a.published_at else None,
"created_at": a.created_at.isoformat() if a.created_at else None,
}
for a in articles
],
"total": query.count(),
"skip": skip,
"limit": limit,
}
@router.post("/articles")
async def create_article(
title: str,
slug: str,
content: str,
excerpt: Optional[str] = None,
seo_title: Optional[str] = None,
seo_description: Optional[str] = None,
keywords: Optional[List[str]] = None,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""Create a new article."""
article = Article(
title=title,
slug=slug,
content=content,
excerpt=excerpt,
author_id=current_user.id,
seo_title=seo_title,
seo_description=seo_description,
keywords=keywords,
)
db.add(article)
db.commit()
db.refresh(article)
return {"status": "created", "article_id": article.id, "slug": slug}
@router.get("/articles/{article_id}")
async def get_article(
article_id: int,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""Get a specific article."""
article = db.query(Article).filter(Article.id == article_id).first()
if not article:
raise HTTPException(status_code=404, detail="Article not found")
return {
"id": article.id,
"title": article.title,
"slug": article.slug,
"content": article.content,
"excerpt": article.excerpt,
"status": article.status.value,
"author": article.author.full_name if article.author else None,
"seo_title": article.seo_title,
"seo_description": article.seo_description,
"keywords": article.keywords,
"published_at": article.published_at.isoformat() if article.published_at else None,
"created_at": article.created_at.isoformat() if article.created_at else None,
"updated_at": article.updated_at.isoformat() if article.updated_at else None,
}
@router.put("/articles/{article_id}")
async def update_article(
article_id: int,
title: Optional[str] = None,
content: Optional[str] = None,
status: Optional[ArticleStatus] = None,
seo_title: Optional[str] = None,
seo_description: Optional[str] = None,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""Update an article."""
article = db.query(Article).filter(Article.id == article_id).first()
if not article:
raise HTTPException(status_code=404, detail="Article not found")
if title:
article.title = title
if content:
article.content = content
if status:
article.status = status
if status == ArticleStatus.PUBLISHED and not article.published_at:
article.published_at = datetime.utcnow()
if seo_title:
article.seo_title = seo_title
if seo_description:
article.seo_description = seo_description
db.commit()
db.refresh(article)
return {"status": "updated", "article_id": article.id}
@router.delete("/articles/{article_id}")
async def delete_article(
article_id: int,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""Delete an article."""
article = db.query(Article).filter(Article.id == article_id).first()
if not article:
raise HTTPException(status_code=404, detail="Article not found")
db.delete(article)
db.commit()
return {"status": "deleted", "article_id": article_id}
# ─── SEO METADATA ─────────────────────────────────────────────────────────────
@router.get("/seo")
async def list_seo_metadata(
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""List all SEO metadata entries."""
seo_entries = db.query(SEOMetadata).all()
return {
"entries": [
{
"id": s.id,
"page_path": s.page_path,
"title": s.title,
"description": s.description,
"audit_score": s.audit_score,
"last_audit": s.last_audit.isoformat() if s.last_audit else None,
}
for s in seo_entries
]
}
@router.post("/seo")
async def create_seo_metadata(
page_path: str,
title: Optional[str] = None,
description: Optional[str] = None,
canonical_url: Optional[str] = None,
og_image: Optional[str] = None,
schema_markup: Optional[dict] = None,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""Create SEO metadata for a page."""
seo = SEOMetadata(
page_path=page_path,
title=title,
description=description,
canonical_url=canonical_url,
og_image=og_image,
schema_markup=schema_markup,
)
db.add(seo)
db.commit()
db.refresh(seo)
return {"status": "created", "seo_id": seo.id}
@router.put("/seo/{seo_id}")
async def update_seo_metadata(
seo_id: int,
title: Optional[str] = None,
description: Optional[str] = None,
audit_score: Optional[int] = None,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""Update SEO metadata."""
seo = db.query(SEOMetadata).filter(SEOMetadata.id == seo_id).first()
if not seo:
raise HTTPException(status_code=404, detail="SEO metadata not found")
if title:
seo.title = title
if description:
seo.description = description
if audit_score is not None:
seo.audit_score = audit_score
seo.last_audit = datetime.utcnow()
db.commit()
db.refresh(seo)
return {"status": "updated", "seo_id": seo.id}