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

151 lines
4.3 KiB
JavaScript

const userDb = require("../db/user.db")
const userNoteDb = require("../db/userNote.db")
const refreshTokenDb = require("../db/refreshToken.db")
const { queueUserUpdate, queueUserNoteCreate } = require("./redis/dbSync.service")
const {
getOrCacheUserModeration,
setUserModerationInRedis,
} = require("./redis/userModerationCache.service")
function assertUserId(userId) {
const id = Number(userId)
if (!Number.isInteger(id) || id <= 0) {
const err = new Error("INVALID_USER_ID")
err.statusCode = 400
throw err
}
return id
}
function computeUntil(durationDays = 7) {
const days = Number(durationDays)
const safeDays = Number.isFinite(days) && days > 0 ? days : 7
return new Date(Date.now() + safeDays * 24 * 60 * 60 * 1000)
}
async function ensureUserExists(userId) {
const id = assertUserId(userId)
const existing = await getOrCacheUserModeration(id)
if (!existing) {
const err = new Error("USER_NOT_FOUND")
err.statusCode = 404
throw err
}
return { id, existing }
}
async function updateUserModeration(id, patch) {
const updatedAt = new Date()
const payload = { id, ...patch }
await setUserModerationInRedis(payload, { ttlSeconds: 60 * 60 })
queueUserUpdate({
userId: id,
data: patch,
updatedAt: updatedAt.toISOString(),
}).catch((err) => console.error("DB sync user update failed:", err?.message || err))
return { id, ...patch }
}
async function muteUser(userId, { durationDays = 7 } = {}) {
const { id } = await ensureUserExists(userId)
const mutedUntil = computeUntil(durationDays)
return updateUserModeration(id, { mutedUntil })
}
async function clearMute(userId) {
const { id } = await ensureUserExists(userId)
return updateUserModeration(id, { mutedUntil: null })
}
async function suspendUser(userId, { durationDays = 7 } = {}) {
const { id } = await ensureUserExists(userId)
const suspendedUntil = computeUntil(durationDays)
return updateUserModeration(id, { suspendedUntil })
}
async function clearSuspend(userId) {
const { id } = await ensureUserExists(userId)
return updateUserModeration(id, { suspendedUntil: null })
}
async function disableUser(userId) {
const { id } = await ensureUserExists(userId)
const disabledAt = new Date()
await refreshTokenDb.revokeAllUserRefreshTokens(id)
return updateUserModeration(id, { disabledAt })
}
async function enableUser(userId) {
const { id } = await ensureUserExists(userId)
return updateUserModeration(id, { disabledAt: null })
}
async function updateUserRole(userId, role) {
const { id } = await ensureUserExists(userId)
const normalized = String(role || "").toUpperCase()
if (!["USER", "MOD"].includes(normalized)) {
const err = new Error("INVALID_ROLE")
err.statusCode = 400
throw err
}
return updateUserModeration(id, { role: normalized })
}
async function addUserNote({ userId, createdById, note }) {
const uid = assertUserId(userId)
const cid = assertUserId(createdById)
const text = String(note || "").trim()
if (!text) {
const err = new Error("NOTE_REQUIRED")
err.statusCode = 400
throw err
}
queueUserNoteCreate({
userId: uid,
createdById: cid,
note: text.slice(0, 1000),
createdAt: new Date().toISOString(),
}).catch((err) => console.error("DB sync user note failed:", err?.message || err))
return { userId: uid, createdById: cid, note: text.slice(0, 1000) }
}
async function listUserNotes({ userId, page = 1, limit = 20 }) {
const uid = assertUserId(userId)
const safePage = Number.isInteger(Number(page)) && Number(page) > 0 ? Number(page) : 1
const safeLimit = Number.isInteger(Number(limit)) && Number(limit) > 0 ? Number(limit) : 20
const skip = (safePage - 1) * safeLimit
const [notes, total, userExists] = await Promise.all([
userNoteDb.listUserNotes({ userId: uid, skip, take: safeLimit }),
userNoteDb.countUserNotes({ userId: uid }),
userDb.findUser({ id: uid }, { select: { id: true } }).then((u) => Boolean(u)),
])
if (!userExists) {
const err = new Error("USER_NOT_FOUND")
err.statusCode = 404
throw err
}
return {
page: safePage,
total,
totalPages: total ? Math.ceil(total / safeLimit) : 0,
results: notes,
}
}
module.exports = {
muteUser,
clearMute,
suspendUser,
clearSuspend,
disableUser,
enableUser,
updateUserRole,
addUserNote,
listUserNotes,
}