From 334402d8c501d4168fc76a7d81a781625fd9e854 Mon Sep 17 00:00:00 2001 From: Jan Szumotalski Date: Sat, 31 May 2025 19:56:38 +0200 Subject: [PATCH] feat: Added notification dialog on frontend --- .../api/{adminRouter.ts => admin/index.ts} | 22 ++++++------ .../api/admin/{notif.ts => notif/index.ts} | 14 ++------ src/routes/api/admin/notif/outbox.ts | 35 +++++++++++++++++++ src/routes/api/{appRouter.ts => app/index.ts} | 28 +++++++++++++-- src/routes/api/index.ts | 8 +++++ src/routes/index.ts | 8 ++--- 6 files changed, 86 insertions(+), 29 deletions(-) rename src/routes/api/{adminRouter.ts => admin/index.ts} (56%) rename src/routes/api/admin/{notif.ts => notif/index.ts} (81%) create mode 100644 src/routes/api/admin/notif/outbox.ts rename src/routes/api/{appRouter.ts => app/index.ts} (74%) create mode 100644 src/routes/api/index.ts diff --git a/src/routes/api/adminRouter.ts b/src/routes/api/admin/index.ts similarity index 56% rename from src/routes/api/adminRouter.ts rename to src/routes/api/admin/index.ts index 6e2087a..dcf5664 100644 --- a/src/routes/api/adminRouter.ts +++ b/src/routes/api/admin/index.ts @@ -1,15 +1,15 @@ import { Router } from "express"; import { islogged, isadmin} from "@/utility"; -import { newsRouter } from "./admin/news"; -import { accsRouter } from "./admin/accs"; -import { menuRouter } from "./admin/menu"; -import { groupsRouter } from "./admin/groups"; -import { notifRouter } from "./admin/notif"; -import { keysRouter } from "./admin/keys"; -import { cleanRouter } from "./admin/clean"; -import { settingsRouter } from "./admin/settings"; +import { newsRouter } from "./news"; +import { accsRouter } from "./accs"; +import { menuRouter } from "./menu"; +import { groupsRouter } from "./groups"; +import { notifRouter } from "./notif"; +import { keysRouter } from "./keys"; +import { cleanRouter } from "./clean"; +import { settingsRouter } from "./settings"; -const adminRouter = Router() +export const adminRouter = Router() adminRouter.use(islogged, isadmin) adminRouter.use('/news', newsRouter) @@ -24,6 +24,4 @@ adminRouter.use('/settings', settingsRouter) adminRouter.get('/usearch', (req, res) => { // TODO: Add search res.send([req.query['q']]) -}) - -export {adminRouter}; \ No newline at end of file +}) \ No newline at end of file diff --git a/src/routes/api/admin/notif.ts b/src/routes/api/admin/notif/index.ts similarity index 81% rename from src/routes/api/admin/notif.ts rename to src/routes/api/admin/notif/index.ts index 25fc549..b084dcc 100644 --- a/src/routes/api/admin/notif.ts +++ b/src/routes/api/admin/notif/index.ts @@ -6,6 +6,7 @@ import capability, { Features } from "@/helpers/capability"; import Inbox from "@/schemas/Inbox"; import { Types } from "mongoose"; import { IUser } from "@/schemas/User"; +import { outboxRouter } from "./outbox"; const notifRouter = Router() @@ -49,19 +50,10 @@ notifRouter.post("/send", async (req: Request { - var result = await Inbox.find({}, {}, {sort: {sentDate: -1}}).populate<{rcpt: IUser & {_id: Types.ObjectId}}>("rcpt", ['fname', 'surname', 'uname', '_id', 'room']).exec() - var final = result.map(v => { - return { - ...v.toJSON(), - ack: v.ack.length - } - }) - res.send(final) -}) - notifRouter.get("/groups", async (req, res) => { res.send(await Group.find({}, { name: 1, _id: 1 })) }) +notifRouter.use("/outbox", outboxRouter) + export { notifRouter } \ No newline at end of file diff --git a/src/routes/api/admin/notif/outbox.ts b/src/routes/api/admin/notif/outbox.ts new file mode 100644 index 0000000..23ea332 --- /dev/null +++ b/src/routes/api/admin/notif/outbox.ts @@ -0,0 +1,35 @@ +import Inbox from "@/schemas/Inbox"; +import { IUser } from "@/schemas/User"; +import { Response, Router } from "express"; + +export const outboxRouter = Router() + +outboxRouter.get("/", async (req, res: Response) => { + var result = await Inbox.find({}, {message: 1, sentDate: 1}, {sort: {sentDate: -1}}) + var final = result.map(v => { + return { + _id: v._id, + sentDate: v.sentDate, + title: v.message.title + } + }) + res.send(final) +}) + +outboxRouter.get("/:id/message", async (req, res) => { + var msg = await Inbox.findById(req.params.id, {message: 1}) + if (msg) { + res.send(msg.message.body) + } else { + res.status(404).send({message: "ERR: 404 Message id not found"}) + } +}) + +outboxRouter.get("/:id/rcpts", async (req, res) => { + var msg = await Inbox.findById(req.params.id, {rcpt: 1}).populate<{rcpt: Pick}>({path: "rcpt", select: ["uname", "room", "fname", "surname"]}).exec() + if (msg) { + res.send(msg.rcpt) + } else { + res.status(404).send({message: "ERR: 404 Message id not found"}) + } +}) \ No newline at end of file diff --git a/src/routes/api/appRouter.ts b/src/routes/api/app/index.ts similarity index 74% rename from src/routes/api/appRouter.ts rename to src/routes/api/app/index.ts index 1cdc23e..be3642b 100644 --- a/src/routes/api/appRouter.ts +++ b/src/routes/api/app/index.ts @@ -9,7 +9,9 @@ import Key, { IKey } from "@schemas/Key"; import usettings from "@/helpers/usettings"; import Grade from "@schemas/Grade"; import { createHash } from "node:crypto"; -const appRouter = Router(); +import Inbox from "@/schemas/Inbox"; + +export const appRouter = Router(); appRouter.use(islogged) @@ -75,4 +77,26 @@ appRouter.get("/clean/:date", capability.mw(Features.Clean), async (req, res) => })) }) -export {appRouter}; \ No newline at end of file +appRouter.get("/notif/check", capability.mw(Features.Notif), async (req, res) => { + var result = await Inbox.find({rcpt: req.user._id, $nor: [{ack: req.user._id}]}, {message: 1, sentDate: 1}) + if (result) { + res.send(result) + } else { + res.send([]) + } +}) + +appRouter.post("/notif/:id/ack", capability.mw(Features.Notif), async (req, res) => { + var result = await Inbox.findById(req.params.id) + if (result) { + if (result.rcpt.includes(req.user._id) && !result.ack.includes(req.user._id)) { + result.ack.push(req.user._id) + await result.save({}) + res.send({status: 200}) + } else { + res.status(403).send({status: 401, message: "User doesn't have access or message already acknowledged"}) + } + } else { + res.status(404).send({status: 404, message: "Message not found"}) + } +}) \ No newline at end of file diff --git a/src/routes/api/index.ts b/src/routes/api/index.ts new file mode 100644 index 0000000..215940d --- /dev/null +++ b/src/routes/api/index.ts @@ -0,0 +1,8 @@ +import { Router } from "express"; +import { appRouter } from "./app"; +import { adminRouter } from "./admin"; + +export const apiRouter = Router(); + +apiRouter.use("/app", appRouter) +apiRouter.use("/admin", adminRouter) \ No newline at end of file diff --git a/src/routes/index.ts b/src/routes/index.ts index 00370fc..b137bef 100644 --- a/src/routes/index.ts +++ b/src/routes/index.ts @@ -1,16 +1,14 @@ import { Router } from "express"; import Notification from "@schemas/Notification"; import { islogged } from "@/utility"; -import { adminRouter } from "./api/adminRouter"; -import { appRouter } from "./api/appRouter"; import { authRouter } from "./auth/index"; import capability, { Features } from "@/helpers/capability"; import mongoose from "mongoose"; +import { apiRouter } from "./api"; const router = Router(); -router.use('/app', appRouter) -router.use('/admin', adminRouter) +router.use('/', apiRouter) router.use('/auth', authRouter) router.get("/healthcheck", async (req, res) => { @@ -27,4 +25,6 @@ router.post("/notif", islogged, capability.mw(Features.Notif), async (req, res) res.send({"status": 200}) }) +router.use("/", apiRouter) + export default router; \ No newline at end of file