feat: 공지 탭 추가
Some checks failed
Build and Push Images / build-backend (push) Has been cancelled

This commit is contained in:
qorgh529
2026-04-10 19:58:43 +09:00
parent 1a6e9b6327
commit 68e9fc0a32
3 changed files with 273 additions and 1 deletions

View File

@@ -501,3 +501,105 @@ def delete_reply(reply_id: int, token=Depends(verify_token), conn=Depends(get_db
cur.execute("DELETE FROM board_replies WHERE id = %s", (reply_id,))
conn.commit()
return {"ok": True}
# ─── 공지사항 ──────────────────────────────────────────────
class NoticeCreate(BaseModel):
title: str
content: str
class NoticeReplyCreate(BaseModel):
content: str
def init_notice_db():
conn = psycopg2.connect(**DB_CONFIG)
cur = conn.cursor()
cur.execute("""
CREATE TABLE IF NOT EXISTS notice_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 notice_replies (
id SERIAL PRIMARY KEY,
post_id INTEGER REFERENCES notice_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_notice():
import time
for _ in range(10):
try:
init_notice_db()
print("Notice DB initialized")
break
except Exception as e:
print(f"Notice DB not ready... {e}")
time.sleep(3)
@app.get("/api/notice/posts")
def list_notice_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 notice_posts ORDER BY created_at DESC")
return cur.fetchall()
@app.post("/api/notice/posts")
def create_notice_post(data: NoticeCreate, token=Depends(require_admin), conn=Depends(get_db)):
cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
cur.execute(
"INSERT INTO notice_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/notice/posts/{post_id}")
def get_notice_post(post_id: int, token=Depends(verify_token), conn=Depends(get_db)):
cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
cur.execute("SELECT * FROM notice_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 notice_replies WHERE post_id = %s ORDER BY created_at ASC", (post_id,))
replies = cur.fetchall()
return {"post": post, "replies": replies}
@app.delete("/api/notice/posts/{post_id}")
def delete_notice_post(post_id: int, token=Depends(require_admin), conn=Depends(get_db)):
cur = conn.cursor()
cur.execute("DELETE FROM notice_posts WHERE id = %s", (post_id,))
conn.commit()
return {"ok": True}
@app.post("/api/notice/posts/{post_id}/replies")
def create_notice_reply(post_id: int, data: NoticeReplyCreate, token=Depends(verify_token), conn=Depends(get_db)):
cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
cur.execute(
"INSERT INTO notice_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/notice/replies/{reply_id}")
def delete_notice_reply(reply_id: int, token=Depends(verify_token), conn=Depends(get_db)):
cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
cur.execute("SELECT * FROM notice_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 notice_replies WHERE id = %s", (reply_id,))
conn.commit()
return {"ok": True}