HotTRDealsBackend/routes/accountSettings.routes.js
2026-02-09 21:47:55 +00:00

126 lines
3.6 KiB
JavaScript

const express = require("express")
const multer = require("multer")
const requireAuth = require("../middleware/requireAuth.js")
const {
getUserProfile,
markAllNotificationsRead,
getUserNotificationsPage,
changePassword,
} = require("../services/profile.service")
const { endpoints } = require("@shared/contracts")
const router = express.Router()
const upload = multer({ dest: "uploads/" })
const { updateUserAvatar } = require("../services/avatar.service")
const { enqueueAuditFromRequest, buildAuditMeta } = require("../services/audit.service")
const { AUDIT_ACTIONS } = require("../services/auditActions")
const { account } = endpoints
function attachNotificationExtras(validatedList = [], sourceList = []) {
const extrasById = new Map(
(Array.isArray(sourceList) ? sourceList : []).map((item) => [
Number(item?.id),
item?.extras ?? null,
])
)
return (Array.isArray(validatedList) ? validatedList : []).map((item) => ({
...item,
extras: extrasById.get(Number(item?.id)) ?? null,
}))
}
router.post(
"/avatar",
requireAuth,
upload.single("file"),
async (req, res) => {
try {
const updatedUser = await updateUserAvatar(req.auth.userId, req.file)
enqueueAuditFromRequest(
req,
AUDIT_ACTIONS.ACCOUNT.AVATAR_UPDATE,
buildAuditMeta({
entityType: "USER",
entityId: req.auth.userId,
after: { avatarUrl: updatedUser.avatarUrl ?? null },
})
)
res.json(
account.avatarUploadResponseSchema.parse({
message: "Avatar updated",
user: updatedUser,
})
)
} catch (err) {
console.error(err)
res.status(400).json({ error: err.message })
}
}
)
router.get("/me", requireAuth, async (req, res) => {
try {
const user = await getUserProfile(req.auth.userId)
const payload = account.accountMeResponseSchema.parse(user)
payload.notifications = attachNotificationExtras(payload.notifications, user?.notifications)
res.json(payload)
} catch (err) {
res.status(400).json({ error: err.message })
}
})
router.get("/notifications/read", requireAuth, async (req, res) => {
try {
await markAllNotificationsRead(req.auth.userId)
enqueueAuditFromRequest(
req,
AUDIT_ACTIONS.ACCOUNT.NOTIFICATIONS_READ,
buildAuditMeta({
entityType: "USER",
entityId: req.auth.userId,
extra: { action: "mark_all_read" },
})
)
res.sendStatus(200)
} catch (err) {
res.status(400).json({ error: err.message })
}
})
router.get("/notifications", requireAuth, async (req, res) => {
try {
const input = account.accountNotificationsListRequestSchema.parse(req.query)
const payload = await getUserNotificationsPage(req.auth.userId, input.page, 10)
const validated = account.accountNotificationsListResponseSchema.parse(payload)
validated.results = attachNotificationExtras(validated.results, payload?.results)
res.json(validated)
} catch (err) {
res.status(400).json({ error: err.message })
}
})
router.post("/password", requireAuth, async (req, res) => {
try {
const input = account.accountPasswordChangeRequestSchema.parse(req.body)
const payload = await changePassword(req.auth.userId, input)
enqueueAuditFromRequest(
req,
AUDIT_ACTIONS.ACCOUNT.PASSWORD_CHANGE,
buildAuditMeta({
entityType: "USER",
entityId: req.auth.userId,
})
)
res.json(account.accountPasswordChangeResponseSchema.parse(payload))
} catch (err) {
res.status(400).json({ error: err.message })
}
})
module.exports = router