from typing import Any, List from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from app import crud, models, schemas from app.auth import deps from app.db.session import get_db router = APIRouter() @router.get("/", response_model=List[schemas.Post]) def read_posts( db: Session = Depends(get_db), skip: int = 0, limit: int = 100, ) -> Any: """ Retrieve published posts. """ posts = crud.post.get_multi_published(db, skip=skip, limit=limit) return posts @router.post("/", response_model=schemas.Post) def create_post( *, db: Session = Depends(get_db), post_in: schemas.PostCreate, current_user: models.User = Depends(deps.get_current_active_user), ) -> Any: """ Create new post. """ post = crud.post.create_with_author(db, obj_in=post_in, author_id=current_user.id) return post @router.get("/{post_id}", response_model=schemas.Post) def read_post( *, db: Session = Depends(get_db), post_id: str, ) -> Any: """ Get post by ID. """ post = crud.post.get(db, id=post_id) if not post: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Post not found", ) if not post.is_published: # Only the author can see unpublished posts current_user = deps.get_current_user(db=db) if current_user.id != post.author_id: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="The post is not published yet", ) return post @router.put("/{post_id}", response_model=schemas.Post) def update_post( *, db: Session = Depends(get_db), post_id: str, post_in: schemas.PostUpdate, current_user: models.User = Depends(deps.get_current_active_user), ) -> Any: """ Update a post. """ post = crud.post.get(db, id=post_id) if not post: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Post not found", ) if post.author_id != current_user.id and not current_user.is_superuser: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="You can only update your own posts", ) post = crud.post.update(db, db_obj=post, obj_in=post_in) return post @router.delete("/{post_id}", response_model=schemas.Post) def delete_post( *, db: Session = Depends(get_db), post_id: str, current_user: models.User = Depends(deps.get_current_active_user), ) -> Any: """ Delete a post. """ post = crud.post.get(db, id=post_id) if not post: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Post not found", ) if post.author_id != current_user.id and not current_user.is_superuser: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="You can only delete your own posts", ) post = crud.post.remove(db, id=post_id) return post @router.get("/user/{user_id}", response_model=List[schemas.Post]) def read_user_posts( user_id: str, db: Session = Depends(get_db), skip: int = 0, limit: int = 100, ) -> Any: """ Retrieve posts by user. """ user = crud.user.get(db, id=user_id) if not user: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="User not found", ) # Check if the current user is the author or a superuser try: current_user = deps.get_current_user(db=db) is_author_or_superuser = (user_id == current_user.id) or current_user.is_superuser except Exception: is_author_or_superuser = False if is_author_or_superuser: # Return all posts for the author or superuser posts = crud.post.get_multi_by_author( db=db, author_id=user_id, skip=skip, limit=limit ) else: # Filter to only published posts for other users posts = [ post for post in crud.post.get_multi_by_author( db=db, author_id=user_id, skip=skip, limit=limit ) if post.is_published ] return posts