This commit is contained in:
102
backend/main.py
102
backend/main.py
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user