98 lines
2.4 KiB
JavaScript
98 lines
2.4 KiB
JavaScript
/**
|
|
* 관리자 전용 API 라우트
|
|
* - 서버 명령어 실행
|
|
* - 인증 + 관리자 권한 필요
|
|
*/
|
|
|
|
import express from "express";
|
|
import jwt from "jsonwebtoken";
|
|
import { pool } from "../lib/db.js";
|
|
|
|
const router = express.Router();
|
|
|
|
const JWT_SECRET = process.env.JWT_SECRET || "minecraft-jwt-secret";
|
|
const MOD_API_URL = `http://${
|
|
process.env.MINECRAFT_HOST || "host.docker.internal"
|
|
}:${process.env.MINECRAFT_MOD_PORT || 25580}`;
|
|
|
|
/**
|
|
* JWT 토큰에서 사용자 정보 추출
|
|
*/
|
|
function getUserFromToken(req) {
|
|
const authHeader = req.headers.authorization;
|
|
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
const token = authHeader.split(" ")[1];
|
|
return jwt.verify(token, JWT_SECRET);
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 관리자 권한 확인 미들웨어
|
|
*/
|
|
async function requireAdmin(req, res, next) {
|
|
const user = getUserFromToken(req);
|
|
|
|
if (!user) {
|
|
return res.status(401).json({ error: "인증이 필요합니다" });
|
|
}
|
|
|
|
try {
|
|
// DB에서 관리자 권한 확인
|
|
const result = await pool.query(
|
|
"SELECT is_admin FROM users WHERE id = $1 AND is_active = true",
|
|
[user.id]
|
|
);
|
|
|
|
if (result.rows.length === 0 || !result.rows[0].is_admin) {
|
|
return res.status(403).json({ error: "관리자 권한이 필요합니다" });
|
|
}
|
|
|
|
req.user = user;
|
|
next();
|
|
} catch (error) {
|
|
console.error("[Admin] 권한 확인 오류:", error);
|
|
res.status(500).json({ error: "서버 오류" });
|
|
}
|
|
}
|
|
|
|
// 모든 라우트에 관리자 권한 필요
|
|
router.use(requireAdmin);
|
|
|
|
/**
|
|
* POST /admin/command - 서버 명령어 실행
|
|
*/
|
|
router.post("/command", async (req, res) => {
|
|
const { command } = req.body;
|
|
|
|
if (!command || typeof command !== "string" || !command.trim()) {
|
|
return res
|
|
.status(400)
|
|
.json({ success: false, message: "명령어를 입력해주세요" });
|
|
}
|
|
|
|
try {
|
|
console.log(`[Admin] ${req.user.email}님이 명령어 실행: ${command}`);
|
|
|
|
const response = await fetch(`${MOD_API_URL}/command`, {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ command: command.trim() }),
|
|
});
|
|
|
|
const data = await response.json();
|
|
res.json(data);
|
|
} catch (error) {
|
|
console.error("[Admin] 명령어 전송 오류:", error);
|
|
res
|
|
.status(500)
|
|
.json({ success: false, message: "서버에 연결할 수 없습니다" });
|
|
}
|
|
});
|
|
|
|
export default router;
|