HotTRDealsBackend/services/profile.service.js
2026-02-04 06:39:10 +00:00

168 lines
4.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const bcrypt = require("bcryptjs")
const userDb = require("../db/user.db")
const notificationDb = require("../db/notification.db")
const refreshTokenDb = require("../db/refreshToken.db")
const { queueNotificationReadAll } = require("./redis/dbSync.service")
function assertPositiveInt(v, name = "id") {
const n = Number(v)
if (!Number.isInteger(n) || n <= 0) throw new Error(`Geçersiz ${name}.`)
return n
}
async function updateAvatarUrl(userId, url) {
const id = assertPositiveInt(userId, "userId")
if (!url || typeof url !== "string" || !url.trim())
throw new Error("Geçersiz URL.")
const select = { id: true, username: true, avatarUrl: true }
return userDb.updateUser({ id }, { avatarUrl: url.trim() }, { select })
}
async function getUserProfile(userId) {
const id = assertPositiveInt(userId, "userId")
const select = {
id: true,
username: true,
avatarUrl: true,
createdAt: true,
userBadges: {
orderBy: { earnedAt: "desc" },
select: {
earnedAt: true,
badge: { select: { id: true, name: true, iconUrl: true, description: true } },
},
},
notifications: {
orderBy: { createdAt: "desc" },
take: 3,
select: {
id: true,
message: true,
type: true,
createdAt: true,
readAt: true,
},
},
}
const user = await userDb.findUser({ id }, { select })
if (!user) return user
const formatDate = (value) => (value instanceof Date ? value.toISOString() : value ?? null)
const notifications = Array.isArray(user.notifications)
? user.notifications.map((n) => ({
...n,
createdAt: formatDate(n.createdAt),
readAt: formatDate(n.readAt),
unread: n.readAt == null,
}))
: []
const badges = Array.isArray(user.userBadges)
? user.userBadges.map((item) => ({
badge: item.badge
? {
id: item.badge.id,
name: item.badge.name,
iconUrl: item.badge.iconUrl ?? null,
description: item.badge.description ?? null,
}
: null,
earnedAt: formatDate(item.earnedAt),
}))
: []
return {
id: user.id,
username: user.username,
avatarUrl: user.avatarUrl ?? null,
createdAt: formatDate(user.createdAt),
notifications,
badges,
}
}
module.exports = {
updateAvatarUrl,
getUserProfile,
markAllNotificationsRead,
getUserNotificationsPage,
changePassword,
}
async function markAllNotificationsRead(userId) {
const id = assertPositiveInt(userId, "userId")
const readAt = new Date().toISOString()
await queueNotificationReadAll({ userId: id, readAt })
return { queued: true, readAt }
}
async function getUserNotificationsPage(userId, page = 1, limit = 10) {
const id = assertPositiveInt(userId, "userId")
const pageNumber = assertPositiveInt(page, "page")
const take = assertPositiveInt(limit, "limit")
const skip = (pageNumber - 1) * take
const [total, notifications] = await Promise.all([
notificationDb.countNotifications({ userId: id }),
notificationDb.findNotifications(
{ userId: id },
{
orderBy: { createdAt: "desc" },
skip,
take,
select: {
id: true,
message: true,
type: true,
createdAt: true,
readAt: true,
},
}
),
])
const formatDate = (value) => (value instanceof Date ? value.toISOString() : value ?? null)
const results = Array.isArray(notifications)
? notifications.map((n) => ({
...n,
createdAt: formatDate(n.createdAt),
readAt: formatDate(n.readAt),
unread: n.readAt == null,
}))
: []
const totalPages = Math.ceil(total / take)
return {
page: pageNumber,
total,
totalPages,
results,
}
}
async function changePassword(userId, { currentPassword, newPassword }) {
const id = assertPositiveInt(userId, "userId")
if (!currentPassword || typeof currentPassword !== "string")
throw new Error("Mevcut şifre gerekli.")
if (!newPassword || typeof newPassword !== "string")
throw new Error("Yeni şifre gerekli.")
const user = await userDb.findUser(
{ id },
{ select: { id: true, passwordHash: true } }
)
if (!user) throw new Error("Kullanıcı bulunamadı.")
const isMatch = await bcrypt.compare(currentPassword, user.passwordHash)
if (!isMatch) throw new Error("Mevcut şifre hatalı.")
const passwordHash = await bcrypt.hash(newPassword, 10)
await userDb.updateUser({ id }, { passwordHash })
await refreshTokenDb.revokeAllUserRefreshTokens(id)
return { message: "Şifre güncellendi." }
}