Automated Action 771ee5214f Implement LinkedIn-based church management system with FastAPI
- Complete FastAPI application with authentication and JWT tokens
- SQLite database with SQLAlchemy ORM and Alembic migrations
- User management with profile features and search functionality
- LinkedIn-style networking with connection requests and acceptance
- Social features: posts, likes, comments, announcements, prayer requests
- Event management with registration system and capacity limits
- RESTful API endpoints for all features with proper authorization
- Comprehensive documentation and setup instructions

Key Features:
- JWT-based authentication with bcrypt password hashing
- User profiles with bio, position, contact information
- Connection system for church member networking
- Community feed with post interactions
- Event creation, registration, and attendance tracking
- Admin role-based permissions
- Health check endpoint and API documentation

Environment Variables Required:
- SECRET_KEY: JWT secret key for token generation
2025-07-01 12:28:10 +00:00

203 lines
5.7 KiB
Python

from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from typing import List
from app.db.base import get_db
from app.models.user import User
from app.models.post import Post, Comment, Like
from app.schemas.post import (
PostCreate,
PostUpdate,
PostResponse,
CommentCreate,
CommentResponse,
)
from app.api.auth import get_current_user
router = APIRouter()
@router.post("/", response_model=PostResponse)
def create_post(
post: PostCreate,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
db_post = Post(**post.dict(), author_id=current_user.id)
db.add(db_post)
db.commit()
db.refresh(db_post)
db_post.author_name = f"{current_user.first_name} {current_user.last_name}"
db_post.likes_count = 0
db_post.comments_count = 0
return db_post
@router.get("/", response_model=List[PostResponse])
def get_posts(
skip: int = 0,
limit: int = 100,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
posts = (
db.query(Post).order_by(Post.created_at.desc()).offset(skip).limit(limit).all()
)
for post in posts:
post.author_name = f"{post.author.first_name} {post.author.last_name}"
post.likes_count = db.query(Like).filter(Like.post_id == post.id).count()
post.comments_count = (
db.query(Comment).filter(Comment.post_id == post.id).count()
)
return posts
@router.get("/{post_id}", response_model=PostResponse)
def get_post(
post_id: int,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
post = db.query(Post).filter(Post.id == post_id).first()
if not post:
raise HTTPException(status_code=404, detail="Post not found")
post.author_name = f"{post.author.first_name} {post.author.last_name}"
post.likes_count = db.query(Like).filter(Like.post_id == post.id).count()
post.comments_count = db.query(Comment).filter(Comment.post_id == post.id).count()
return post
@router.put("/{post_id}", response_model=PostResponse)
def update_post(
post_id: int,
post_update: PostUpdate,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
post = db.query(Post).filter(Post.id == post_id).first()
if not post:
raise HTTPException(status_code=404, detail="Post not found")
if post.author_id != current_user.id and not current_user.is_admin:
raise HTTPException(
status_code=403, detail="Not authorized to update this post"
)
for field, value in post_update.dict(exclude_unset=True).items():
setattr(post, field, value)
db.commit()
db.refresh(post)
return post
@router.delete("/{post_id}")
def delete_post(
post_id: int,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
post = db.query(Post).filter(Post.id == post_id).first()
if not post:
raise HTTPException(status_code=404, detail="Post not found")
if post.author_id != current_user.id and not current_user.is_admin:
raise HTTPException(
status_code=403, detail="Not authorized to delete this post"
)
db.delete(post)
db.commit()
return {"message": "Post deleted successfully"}
@router.post("/{post_id}/like")
def like_post(
post_id: int,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
post = db.query(Post).filter(Post.id == post_id).first()
if not post:
raise HTTPException(status_code=404, detail="Post not found")
existing_like = (
db.query(Like)
.filter(Like.post_id == post_id, Like.user_id == current_user.id)
.first()
)
if existing_like:
raise HTTPException(status_code=400, detail="Already liked this post")
like = Like(post_id=post_id, user_id=current_user.id)
db.add(like)
db.commit()
return {"message": "Post liked successfully"}
@router.delete("/{post_id}/like")
def unlike_post(
post_id: int,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
like = (
db.query(Like)
.filter(Like.post_id == post_id, Like.user_id == current_user.id)
.first()
)
if not like:
raise HTTPException(status_code=404, detail="Like not found")
db.delete(like)
db.commit()
return {"message": "Post unliked successfully"}
@router.post("/{post_id}/comments", response_model=CommentResponse)
def create_comment(
post_id: int,
comment: CommentCreate,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
post = db.query(Post).filter(Post.id == post_id).first()
if not post:
raise HTTPException(status_code=404, detail="Post not found")
db_comment = Comment(**comment.dict(), post_id=post_id, author_id=current_user.id)
db.add(db_comment)
db.commit()
db.refresh(db_comment)
db_comment.author_name = f"{current_user.first_name} {current_user.last_name}"
return db_comment
@router.get("/{post_id}/comments", response_model=List[CommentResponse])
def get_comments(
post_id: int,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
post = db.query(Post).filter(Post.id == post_id).first()
if not post:
raise HTTPException(status_code=404, detail="Post not found")
comments = (
db.query(Comment)
.filter(Comment.post_id == post_id)
.order_by(Comment.created_at.asc())
.all()
)
for comment in comments:
comment.author_name = f"{comment.author.first_name} {comment.author.last_name}"
return comments