From 07cc163abcf780a84ebff6529980a1d42db081f0 Mon Sep 17 00:00:00 2001 From: Mikael <46541386+ahnl@users.noreply.github.com> Date: Sat, 6 Jul 2024 18:29:41 +0300 Subject: [PATCH] feat: displayName internal route and optoutPublicName field --- .env.example | 1 + src/database/schemas/userInfo.js | 1 + src/middleware/internalApi.js | 11 +++++++++++ src/routes/misc.js | 34 ++++++++++++++++++++++++++++++++ src/routes/projects.js | 4 ++-- 5 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 src/middleware/internalApi.js diff --git a/.env.example b/.env.example index 0d7969a..ccf0d6e 100644 --- a/.env.example +++ b/.env.example @@ -22,3 +22,4 @@ TESTAUSKOIRA_MARIADB= SESSION_SECRET= NODE_ENV=development COAL_REDIRECT_URI=http://localhost:3001/api/authorized +INTERNAL_API_SECRET= \ No newline at end of file diff --git a/src/database/schemas/userInfo.js b/src/database/schemas/userInfo.js index c536eec..4e0f62a 100644 --- a/src/database/schemas/userInfo.js +++ b/src/database/schemas/userInfo.js @@ -38,6 +38,7 @@ const SchemaUserInfo = new Schema({ }, timestamp: Number }, + optoutPublicName: Boolean, internalNotices: String }) diff --git a/src/middleware/internalApi.js b/src/middleware/internalApi.js new file mode 100644 index 0000000..a499150 --- /dev/null +++ b/src/middleware/internalApi.js @@ -0,0 +1,11 @@ +/* This middleware is used to restrict access to certain API routes, that are used internally by Testausserveri's other systems */ +/* Must be only used to avoid abuse use, not as a data protection measure */ + +export default function internalApiMiddleware(req, res, next) { + res.setHeader('X-Testausapis-Internal-Api-Middleware', 'hit'); + if (process.env.INTERNAL_API_SECRET != req.get('X-Testausapis-Secret')) { + res.status(403).json({error: "Unauthorized"}).end() + return + } + next() +} \ No newline at end of file diff --git a/src/routes/misc.js b/src/routes/misc.js index 785d537..8139ce5 100644 --- a/src/routes/misc.js +++ b/src/routes/misc.js @@ -1,4 +1,6 @@ import express, { Router } from "express" +import database from "../database/database.js" +import internalApiMiddleware from "../middleware/internalApi.js" // eslint-disable-next-line new-cap const router = Router() @@ -12,4 +14,36 @@ router.use("/media", (req, res, next) => { next() }, express.static("media")) +router.get("/displayName", internalApiMiddleware, async (req, res) => { + const id = req.query.id; + if (!id) return res.status(400).json({error: "Missing id query parameter"}) + if (!/^[a-f\d]{24}$/i.test(id)) return res.status(400).json({error: "Invalid id"}) + + const member = await database.UserInfo.findOne({ _id: req.query.id }, "associationMembership.firstName associationMembership.lastName username nickname optoutPublicName") + + /* + Display name is sourced from in the following order: + 1. first name & last name initial + 2. nickname + 3. username + 4. id + */ + + let displayName = id; + let kind = 4; + + if (member?.associationMembership?.firstName && member?.associationMembership?.lastName && member?.optoutPublicName != true) { + displayName = `${member.associationMembership.firstName} ${member.associationMembership.lastName[0]}.` + kind = 1; + } else if (member?.nickname) { + displayName = member.nickname; + kind = 2; + } else if (member?.username) { + displayName = member.username; + kind = 3; + } + + return res.json({ displayName, kind }) +}) + export default router diff --git a/src/routes/projects.js b/src/routes/projects.js index bd965c2..1b2148c 100644 --- a/src/routes/projects.js +++ b/src/routes/projects.js @@ -10,7 +10,7 @@ router.get("/", async (req, res) => { let task = database.Projects.find({ publishState: "PUBLISHED" }, req.query.slugs ? "slug" : null) if (!req.query.slugs) { - task = task.populate("members", "nickname username associationMembership.firstName associationMembership.lastName") + task = task.populate("members", "nickname username associationMembership.firstName associationMembership.lastName optoutPublicName") .populate("tags", "name") } @@ -38,7 +38,7 @@ router.get("/", async (req, res) => { _id, associationMembership, nickname, username }) => ({ _id, - name: associationMembership?.lastName ? + name: (associationMembership?.lastName && associationMembership?.optoutPublicName != true) ? `${associationMembership.firstName} ${associationMembership.lastName[0]}.` : (nickname || username) })),