feat: MY Page, 게시판, Favicon 기능 추가
Some checks failed
Build and Push Images / build-backend (push) Has been cancelled

This commit is contained in:
qorgh529
2026-04-10 18:38:21 +09:00
parent 2ef0e47693
commit 1a6e9b6327
2 changed files with 646 additions and 381 deletions

View File

@@ -393,3 +393,111 @@ def update_user_pages(user_id: int, data: AccessUpdate, token=Depends(require_ad
@app.get("/health")
def health():
return {"status": "ok"}
# ─── 게시판 ──────────────────────────────────────────────
class PostCreate(BaseModel):
title: str
content: str
class ReplyCreate(BaseModel):
content: str
def init_board_db():
conn = psycopg2.connect(**DB_CONFIG)
cur = conn.cursor()
cur.execute("""
CREATE TABLE IF NOT EXISTS board_posts (
id SERIAL PRIMARY KEY,
title VARCHAR(300) NOT NULL,
content TEXT NOT NULL,
author_id INTEGER REFERENCES users(id) ON DELETE SET NULL,
author_name VARCHAR(100) NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS board_replies (
id SERIAL PRIMARY KEY,
post_id INTEGER REFERENCES board_posts(id) ON DELETE CASCADE,
content TEXT NOT NULL,
author_id INTEGER REFERENCES users(id) ON DELETE SET NULL,
author_name VARCHAR(100) NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);
""")
conn.commit()
cur.close()
conn.close()
@app.on_event("startup")
def startup_board():
import time
for _ in range(10):
try:
init_board_db()
print("Board DB initialized")
break
except Exception as e:
print(f"Board DB not ready... {e}")
time.sleep(3)
@app.get("/api/board/posts")
def list_posts(token=Depends(verify_token), conn=Depends(get_db)):
cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
cur.execute("SELECT id, title, author_name, created_at FROM board_posts ORDER BY created_at DESC")
return cur.fetchall()
@app.post("/api/board/posts")
def create_post(data: PostCreate, token=Depends(verify_token), conn=Depends(get_db)):
cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
cur.execute(
"INSERT INTO board_posts (title, content, author_id, author_name) VALUES (%s, %s, %s, %s) RETURNING *",
(data.title, data.content, int(token["sub"]), token["username"])
)
conn.commit()
return cur.fetchone()
@app.get("/api/board/posts/{post_id}")
def get_post(post_id: int, token=Depends(verify_token), conn=Depends(get_db)):
cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
cur.execute("SELECT * FROM board_posts WHERE id = %s", (post_id,))
post = cur.fetchone()
if not post:
raise HTTPException(status_code=404, detail="Post not found")
cur.execute("SELECT * FROM board_replies WHERE post_id = %s ORDER BY created_at ASC", (post_id,))
replies = cur.fetchall()
return {"post": post, "replies": replies}
@app.delete("/api/board/posts/{post_id}")
def delete_post(post_id: int, token=Depends(verify_token), conn=Depends(get_db)):
cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
cur.execute("SELECT * FROM board_posts WHERE id = %s", (post_id,))
post = cur.fetchone()
if not post:
raise HTTPException(status_code=404, detail="Post not found")
if not token.get("is_admin") and post["author_id"] != int(token["sub"]):
raise HTTPException(status_code=403, detail="Permission denied")
cur.execute("DELETE FROM board_posts WHERE id = %s", (post_id,))
conn.commit()
return {"ok": True}
@app.post("/api/board/posts/{post_id}/replies")
def create_reply(post_id: int, data: ReplyCreate, token=Depends(verify_token), conn=Depends(get_db)):
cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
cur.execute(
"INSERT INTO board_replies (post_id, content, author_id, author_name) VALUES (%s, %s, %s, %s) RETURNING *",
(post_id, data.content, int(token["sub"]), token["username"])
)
conn.commit()
return cur.fetchone()
@app.delete("/api/board/replies/{reply_id}")
def delete_reply(reply_id: int, token=Depends(verify_token), conn=Depends(get_db)):
cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
cur.execute("SELECT * FROM board_replies WHERE id = %s", (reply_id,))
reply = cur.fetchone()
if not reply:
raise HTTPException(status_code=404, detail="Reply not found")
if not token.get("is_admin") and reply["author_id"] != int(token["sub"]):
raise HTTPException(status_code=403, detail="Permission denied")
cur.execute("DELETE FROM board_replies WHERE id = %s", (reply_id,))
conn.commit()
return {"ok": True}