# retoor <retoor@molodetz.nl>
import logging
from typing import Annotated
from fastapi import Depends, APIRouter, Request
from fastapi.responses import RedirectResponse
from fastapi.responses import JSONResponse
from devplacepy.database import get_table, resolve_object_url
from devplacepy.content import (
is_owner,
create_comment_record,
delete_comment_record,
edit_comment_record,
)
from devplacepy.utils import require_user, is_admin
from devplacepy.models import CommentForm, CommentEditForm
from devplacepy.responses import action_result, wants_json, json_error
from devplacepy.schemas import CommentEditOut
from devplacepy.services.audit import record as audit
from devplacepy.dependencies import json_or_form
logger = logging.getLogger(__name__)
router = APIRouter()
@router.post("/create")
async def create_comment(request: Request, data: Annotated[CommentForm, Depends(json_or_form(CommentForm))]):
user = require_user(request)
target_uid = data.target_uid or data.post_uid
comment_uid, comment_url = create_comment_record(
request,
user,
data.target_type,
target_uid,
data.content.strip(),
data.parent_uid,
data.attachment_uids,
)
return action_result(
request, comment_url, data={"uid": comment_uid, "url": comment_url}
)
@router.post("/edit/{comment_uid}")
async def edit_comment(
request: Request, comment_uid: str, data: Annotated[CommentEditForm, Depends(json_or_form(CommentEditForm))]
):
user = require_user(request)
comments = get_table("comments")
comment = comments.find_one(uid=comment_uid, deleted_at=None)
if not comment or not is_owner(comment, user):
target_type = comment.get("target_type", "post") if comment else "post"
target_uid = (
(comment.get("target_uid") or comment.get("post_uid", "")) if comment else ""
)
audit.record(
request,
"comment.edit",
user=user,
result="denied",
target_type="comment",
target_uid=comment_uid,
summary=f"{user['username']} denied editing comment {comment_uid}",
)
if wants_json(request):
return json_error(403, "Not allowed")
return RedirectResponse(
url=resolve_object_url(target_type, target_uid), status_code=302
)
content = data.content.strip()
updated_at = edit_comment_record(request, user, comment, content)
target_type = comment.get("target_type", "post")
target_uid = comment.get("target_uid") or comment.get("post_uid", "")
comment_url = f"{resolve_object_url(target_type, target_uid)}#comment-{comment_uid}"
if wants_json(request):
return JSONResponse(
CommentEditOut(
uid=comment_uid,
content=content,
url=comment_url,
updated_at=updated_at,
).model_dump(mode="json")
)
return RedirectResponse(url=comment_url, status_code=302)
@router.post("/delete/{comment_uid}")
async def delete_comment(request: Request, comment_uid: str):
user = require_user(request)
comments = get_table("comments")
comment = comments.find_one(uid=comment_uid, deleted_at=None)
if not comment or not (is_owner(comment, user) or is_admin(user)):
audit.record(
request,
"comment.delete",
user=user,
result="denied",
target_type="comment",
target_uid=comment_uid,
summary=f"{user['username']} denied deleting comment {comment_uid}",
)
if wants_json(request):
return json_error(403, "Not allowed")
return RedirectResponse(url="/feed", status_code=302)
target_type, target_uid = delete_comment_record(request, user, comment)
redirect_url = resolve_object_url(target_type, target_uid)
return action_result(
request,
redirect_url,
data={
"deleted_uid": comment_uid,
"target_type": target_type,
"target_uid": target_uid,
},
)