mirror of
https://github.com/aykhans/portfolio-blog.git
synced 2025-04-16 19:03:11 +00:00
258 lines
6.0 KiB
Python
258 lines
6.0 KiB
Python
from datetime import timedelta
|
|
from typing import (
|
|
Annotated,
|
|
Optional
|
|
)
|
|
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from fastapi.templating import Jinja2Templates
|
|
from fastapi.responses import (
|
|
FileResponse,
|
|
HTMLResponse,
|
|
RedirectResponse
|
|
)
|
|
from fastapi import (
|
|
APIRouter,
|
|
Form,
|
|
HTTPException,
|
|
Request,
|
|
Depends
|
|
)
|
|
|
|
from app import crud
|
|
from app.core import security
|
|
from app.models.user import User as UserModel
|
|
from app.schemas import (
|
|
JWTToken,
|
|
LoginForm
|
|
)
|
|
from app.core.config import settings
|
|
from app.schemas.post import (
|
|
PostCreate,
|
|
PostUpdate
|
|
)
|
|
from app.schemas.post import Post as PostSchema
|
|
from app.views.depends import (
|
|
get_async_db,
|
|
get_current_active_superuser_or_die,
|
|
get_current_active_superuser_or_none,
|
|
get_post_by_slug_or_die,
|
|
handle_post_image_or_die,
|
|
handle_post_image_or_none
|
|
)
|
|
|
|
|
|
router = APIRouter()
|
|
|
|
templates = Jinja2Templates(directory=settings.APP_PATH / 'templates')
|
|
|
|
|
|
@router.get(
|
|
f"/{settings.LOGIN_URL}",
|
|
response_class=HTMLResponse,
|
|
include_in_schema=False
|
|
)
|
|
async def get_login(
|
|
request: Request
|
|
):
|
|
|
|
return templates.TemplateResponse(
|
|
'admin/login.html',
|
|
{
|
|
'request': request,
|
|
'login_url': f'/{settings.LOGIN_URL}'
|
|
}
|
|
)
|
|
|
|
|
|
@router.post(
|
|
f"/{settings.LOGIN_URL}",
|
|
response_model=JWTToken,
|
|
include_in_schema=False
|
|
)
|
|
async def login(
|
|
db: AsyncSession = Depends(get_async_db),
|
|
form_data: LoginForm = Depends()
|
|
):
|
|
|
|
user = await crud.user.authenticate(
|
|
db, email=form_data.email, password=form_data.password
|
|
)
|
|
|
|
if user is None:
|
|
raise HTTPException(
|
|
status_code=400,
|
|
detail="Incorrect email or password"
|
|
)
|
|
|
|
elif user.is_active is False:
|
|
raise HTTPException(status_code=400, detail="Inactive user")
|
|
|
|
access_token_expires = timedelta(
|
|
minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES
|
|
)
|
|
|
|
return {
|
|
"access_token": security.create_access_token(
|
|
user.email,
|
|
expires_delta=access_token_expires
|
|
),
|
|
"token_type": "bearer",
|
|
}
|
|
|
|
|
|
@router.get(
|
|
'/add-post',
|
|
response_class=HTMLResponse,
|
|
)
|
|
async def get_create_post(
|
|
request: Request,
|
|
user: UserModel = Depends(get_current_active_superuser_or_die)
|
|
):
|
|
|
|
return templates.TemplateResponse(
|
|
'admin/add-post.html',
|
|
{
|
|
'request': request
|
|
}
|
|
)
|
|
|
|
|
|
@router.post('/add-post')
|
|
async def create_post(
|
|
request: Request,
|
|
db: AsyncSession = Depends(get_async_db),
|
|
user: UserModel = Depends(get_current_active_superuser_or_die),
|
|
title: str = Form(...),
|
|
text: str = Form(...),
|
|
image: str = Depends(handle_post_image_or_die)
|
|
):
|
|
|
|
obj_in = PostCreate(
|
|
title=title,
|
|
text=text,
|
|
image_path=image
|
|
)
|
|
|
|
post = await crud.post.create_with_owner(
|
|
db, obj_in=obj_in, owner_id=user.id
|
|
)
|
|
|
|
return RedirectResponse(
|
|
str(request.url_for('get_update_post', slug=post.slug)),
|
|
status_code=303
|
|
)
|
|
|
|
|
|
@router.get('/update-post/{slug}')
|
|
async def get_update_post(
|
|
request: Request,
|
|
user: UserModel = Depends(get_current_active_superuser_or_none),
|
|
post: str = Depends(get_post_by_slug_or_die)
|
|
):
|
|
|
|
if user is None:
|
|
return RedirectResponse(
|
|
f'/{settings.LOGIN_URL}',
|
|
status_code=303
|
|
)
|
|
|
|
if user.id != post.owner_id:
|
|
raise HTTPException(status_code=404, detail="Post not found")
|
|
|
|
return templates.TemplateResponse(
|
|
'admin/update-post.html',
|
|
{
|
|
'request': request,
|
|
'post': PostSchema.model_validate(post)
|
|
}
|
|
)
|
|
|
|
|
|
@router.post('/update-post/{slug}')
|
|
async def update_post(
|
|
request: Request,
|
|
user: UserModel = Depends(get_current_active_superuser_or_none),
|
|
post: str = Depends(get_post_by_slug_or_die),
|
|
db: AsyncSession = Depends(get_async_db),
|
|
title: Optional[str] = Form(None),
|
|
text: Optional[str] = Form(None),
|
|
image: Annotated[str, Depends(handle_post_image_or_none)] = None
|
|
):
|
|
|
|
if user is None:
|
|
return RedirectResponse(
|
|
f'/{settings.LOGIN_URL}',
|
|
status_code=303
|
|
)
|
|
|
|
if user.id != post.owner_id:
|
|
raise HTTPException(status_code=404, detail="Post not found")
|
|
|
|
obj_in = PostUpdate(
|
|
title=title,
|
|
text=text,
|
|
image_path=image
|
|
).model_dump(exclude_none=True)
|
|
|
|
updated_post = await crud.post.update(
|
|
db=db,
|
|
db_obj=post,
|
|
obj_in=obj_in
|
|
)
|
|
|
|
return templates.TemplateResponse(
|
|
'admin/update-post.html',
|
|
{
|
|
'request': request,
|
|
'post': PostSchema.model_validate(updated_post)
|
|
}
|
|
)
|
|
|
|
|
|
@router.get('/delete-post/{slug}')
|
|
async def get_delete_post(
|
|
request: Request,
|
|
user: UserModel = Depends(get_current_active_superuser_or_die),
|
|
post: str = Depends(get_post_by_slug_or_die)
|
|
):
|
|
|
|
if user.id != post.owner_id:
|
|
raise HTTPException(status_code=404, detail="Post not found")
|
|
|
|
return templates.TemplateResponse(
|
|
'admin/delete-post.html',
|
|
{
|
|
'request': request,
|
|
'post': PostSchema.model_validate(post)
|
|
}
|
|
)
|
|
|
|
|
|
@router.post('/delete-post/{slug}')
|
|
async def delete_post(
|
|
request: Request,
|
|
user: UserModel = Depends(get_current_active_superuser_or_die),
|
|
post: str = Depends(get_post_by_slug_or_die),
|
|
db: AsyncSession = Depends(get_async_db)
|
|
):
|
|
|
|
if user.id != post.owner_id:
|
|
raise HTTPException(status_code=404, detail="Post not found")
|
|
|
|
await crud.post.remove_by_slug(db, slug=post.slug)
|
|
|
|
return RedirectResponse(
|
|
str(request.url_for('blog')),
|
|
status_code=303
|
|
)
|
|
|
|
|
|
@router.get("/admin")
|
|
def admin(
|
|
request: Request
|
|
):
|
|
|
|
return FileResponse(settings.STATIC_FOLDER / 'just_a.gif')
|