Profile avatar resize crop eklendi. Hatalar fixlendi.
This commit is contained in:
100
server/server.js
100
server/server.js
@@ -90,6 +90,7 @@ const FFPROBE_MAX_BUFFER =
|
||||
Number(process.env.FFPROBE_MAX_BUFFER) > 0
|
||||
? Number(process.env.FFPROBE_MAX_BUFFER)
|
||||
: 10 * 1024 * 1024;
|
||||
const AVATAR_PATH = path.join(__dirname, "..", "client", "src", "assets", "avatar.png");
|
||||
|
||||
app.use(cors());
|
||||
app.use(express.json());
|
||||
@@ -180,6 +181,19 @@ const { router: authRouter, requireAuth, requireRole, issueMediaToken, verifyTok
|
||||
|
||||
app.use(authRouter);
|
||||
|
||||
const avatarUpload = multer({
|
||||
storage: multer.memoryStorage(),
|
||||
limits: { fileSize: 3 * 1024 * 1024 },
|
||||
fileFilter: (req, file, cb) => {
|
||||
const type = (file.mimetype || "").toLowerCase();
|
||||
const allowed = ["image/png", "image/jpeg", "image/jpg"];
|
||||
if (!allowed.includes(type)) {
|
||||
return cb(new Error("INVALID_FILE_TYPE"));
|
||||
}
|
||||
cb(null, true);
|
||||
}
|
||||
});
|
||||
|
||||
buildHealthReport({
|
||||
ffmpegPath: "ffmpeg",
|
||||
ffprobePath: FFPROBE_PATH,
|
||||
@@ -201,6 +215,73 @@ buildHealthReport({
|
||||
|
||||
app.get("/api/health", requireAuth, healthRouter(() => healthSnapshot));
|
||||
|
||||
// --- Profil bilgisi ---
|
||||
app.get("/api/profile", requireAuth, (req, res) => {
|
||||
const username = req.user?.sub || req.user?.username || "user";
|
||||
const role = req.user?.role || "user";
|
||||
const avatarExists = fs.existsSync(AVATAR_PATH);
|
||||
res.json({
|
||||
username,
|
||||
role,
|
||||
avatarExists,
|
||||
avatarUrl: avatarExists ? "/api/profile/avatar" : null
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/api/profile/avatar", requireAuth, (req, res) => {
|
||||
if (!fs.existsSync(AVATAR_PATH)) {
|
||||
return res.status(404).json({ error: "Avatar bulunamadı" });
|
||||
}
|
||||
res.setHeader("Content-Type", "image/png");
|
||||
res.setHeader("Cache-Control", "no-store");
|
||||
fs.createReadStream(AVATAR_PATH).pipe(res);
|
||||
});
|
||||
|
||||
app.post(
|
||||
"/api/profile/avatar",
|
||||
requireAuth,
|
||||
(req, res, next) => {
|
||||
avatarUpload.single("avatar")(req, res, (err) => {
|
||||
if (err) {
|
||||
const isSize = err.code === "LIMIT_FILE_SIZE";
|
||||
const message = isSize
|
||||
? "Dosya boyutu 3MB'ı aşmamalı."
|
||||
: "Geçersiz dosya tipi. Sadece jpg, jpeg veya png.";
|
||||
return res.status(400).json({ error: message });
|
||||
}
|
||||
next();
|
||||
});
|
||||
},
|
||||
(req, res) => {
|
||||
try {
|
||||
if (!req.file?.buffer) {
|
||||
return res.status(400).json({ error: "Dosya yüklenemedi" });
|
||||
}
|
||||
|
||||
const buffer = req.file.buffer;
|
||||
if (!isAllowedImage(buffer)) {
|
||||
return res.status(400).json({ error: "Sadece jpeg/jpg/png kabul edilir" });
|
||||
}
|
||||
|
||||
if (!isPng(buffer)) {
|
||||
return res
|
||||
.status(400)
|
||||
.json({ error: "Lütfen kırptıktan sonra PNG olarak yükleyin." });
|
||||
}
|
||||
|
||||
ensureDirForFile(AVATAR_PATH);
|
||||
fs.writeFileSync(AVATAR_PATH, buffer);
|
||||
res.json({
|
||||
success: true,
|
||||
avatarUrl: "/api/profile/avatar"
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("Avatar yükleme hatası:", err);
|
||||
res.status(500).json({ error: "Avatar kaydedilemedi" });
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
function tvdbImageUrl(pathSegment) {
|
||||
if (!pathSegment) return null;
|
||||
if (pathSegment.startsWith("http")) return pathSegment;
|
||||
@@ -505,6 +586,25 @@ function sanitizeRelative(relPath) {
|
||||
return relPath.replace(/^[\\/]+/, "");
|
||||
}
|
||||
|
||||
function isPng(buffer) {
|
||||
return (
|
||||
buffer &&
|
||||
buffer.length >= 8 &&
|
||||
buffer[0] === 0x89 &&
|
||||
buffer[1] === 0x50 &&
|
||||
buffer[2] === 0x4e &&
|
||||
buffer[3] === 0x47
|
||||
);
|
||||
}
|
||||
|
||||
function isJpeg(buffer) {
|
||||
return buffer && buffer.length >= 2 && buffer[0] === 0xff && buffer[1] === 0xd8;
|
||||
}
|
||||
|
||||
function isAllowedImage(buffer) {
|
||||
return isPng(buffer) || isJpeg(buffer);
|
||||
}
|
||||
|
||||
function determineMediaType({
|
||||
tracker,
|
||||
movieMatch,
|
||||
|
||||
Reference in New Issue
Block a user