summary refs log tree commit diff
path: root/src/api/routes
diff options
context:
space:
mode:
Diffstat (limited to 'src/api/routes')
-rw-r--r--src/api/routes/adminRoutes.js55
-rw-r--r--src/api/routes/alarmRoutes.js38
-rw-r--r--src/api/routes/assignedUserRoutes.js56
-rw-r--r--src/api/routes/auth/accountRoutes.js2
-rw-r--r--src/api/routes/index.js2
-rw-r--r--src/api/routes/statusRoute.js2
6 files changed, 141 insertions, 14 deletions
diff --git a/src/api/routes/adminRoutes.js b/src/api/routes/adminRoutes.js
new file mode 100644

index 0000000..7a1d1e2 --- /dev/null +++ b/src/api/routes/adminRoutes.js
@@ -0,0 +1,55 @@ +import { + requireMonitor, + requireUser, + requireRole, + requireAdmin +} from '#api/middlewares/index.js'; +import { DbUser, UserType } from '#db/schemas/index.js'; +import { RouteMethod } from '#api/RouteDescription.js'; +import { getUserById } from '#db/dbAccess/index.js'; +import { AlarmDto } from '#dto/AlarmDto.js'; + +/** + * @type {RouteDescription} + */ +export const adminGetUserIdsRoute = { + path: '/admin/allUserIds', + methods: { + get: new RouteMethod({ + middlewares: [requireAdmin], + description: 'Get all user IDs', + async method(req, res) { + // streaming json array + res.status(200); + res.write('[\n'); + + const users = DbUser.find().lean().cursor(); + for await (const user of users) { + res.write(JSON.stringify(user._id) + ',\n'); + } + + res.write(']'); + res.end(); + } + }) + } +}; +export const adminMonitorAllRoute = { + path: '/admin/monitorAllUsers', + methods: { + post: new RouteMethod({ + middlewares: [requireAdmin], + description: 'Monitor all users', + async method(req, res) { + const users = await DbUser.find({ type: UserType.USER }).lean(); + const monitoredUsers = users.map(user => user._id); + + // Update the admin's monitoredUsers + req.user.monitoredUsers = monitoredUsers; + await req.user.save(); + + res.status(204).send(); + } + }) + } +}; diff --git a/src/api/routes/alarmRoutes.js b/src/api/routes/alarmRoutes.js
index 23b79c1..ae5a88a 100644 --- a/src/api/routes/alarmRoutes.js +++ b/src/api/routes/alarmRoutes.js
@@ -3,7 +3,7 @@ import { requireUser, requireRole } from '#api/middlewares/index.js'; -import { UserType } from '#db/schemas/index.js'; +import { DbUser, UserType } from '#db/schemas/index.js'; import { RouteMethod } from '#api/RouteDescription.js'; import { getUserById } from '#db/dbAccess/index.js'; import { AlarmDto } from '#dto/AlarmDto.js'; @@ -12,7 +12,7 @@ import { AlarmDto } from '#dto/AlarmDto.js'; * @type {RouteDescription} */ export const alarmByUserRoute = { - path: '/alarm/:id', + path: '/user/:id/alarm', methods: { get: new RouteMethod({ middlewares: [requireMonitor], @@ -27,8 +27,10 @@ export const alarmByUserRoute = { description: 'Clear the alarm for a monitored user', async method(req, res) { const user = await getUserById(req.params.id); - user.alarm = null; - await user.save(); + if (user.alarm) { + user.alarm = null; + await user.save(); + } res.status(204).send(); } }) @@ -45,15 +47,24 @@ export const alarmListRoute = { middlewares: [requireMonitor], description: 'Get a list of all alarms for monitored users', async method(req, res) { - console.log(req.user.monitoredUsers); - const alarms = {}; - for (const userId of req.user.monitoredUsers) { - const user = await getUserById(userId); + // execute the query asynchronously and manually construct a response, for scaling reasons + const users = DbUser.find({ + _id: { $in: req.user.monitoredUsers } + }) + .lean() + .cursor(); + res.status(200); + res.write('{\n'); + for await (const user of users) { if (user.alarm) { - alarms[userId] = user.alarm; + // alarms[user._id] = user.alarm; + res.write( + `"${user._id}": ${JSON.stringify(user.alarm)},\n` + ); } } - res.send(alarms); + res.write('}'); + res.end(); } }) } @@ -76,7 +87,6 @@ export const alarmRoute = { middlewares: [requireUser], description: 'Raise an alarm', async method(req, res) { - console.log(req.body); req.user.alarm = await AlarmDto.create(req.body); await req.user.save(); res.status(204).send(); @@ -86,8 +96,10 @@ export const alarmRoute = { middlewares: [requireUser], description: 'Clear alarm', async method(req, res) { - req.user.alarm = null; - await req.user.save(); + if (req.user.alarm) { + req.user.alarm = null; + await req.user.save(); + } res.status(204).send(); } }) diff --git a/src/api/routes/assignedUserRoutes.js b/src/api/routes/assignedUserRoutes.js new file mode 100644
index 0000000..dac9b13 --- /dev/null +++ b/src/api/routes/assignedUserRoutes.js
@@ -0,0 +1,56 @@ +import { getUserById } from '#db/dbAccess/index.js'; +import { requireMonitor } from '#api/middlewares/index.js'; +import { RouteMethod } from '#api/RouteDescription.js'; +import { SafeNSoundError } from '#util/error.js'; + +/** + * @type {RouteDescription} + */ +export const assignedUserRoute = { + path: '/monitor/assignedUsers', + methods: { + get: new RouteMethod({ + middlewares: [requireMonitor], + description: 'Get assigned users', + async method(req, res) { + res.send(req.user.monitoredUsers); + } + }), + patch: { + middlewares: [requireMonitor], + description: 'Add an assigned user by ID', + async method(req, res) { + if (!req.body.userId) { + throw new SafeNSoundError({ + errCode: 'MISSING_FIELD_ERROR', + message: 'User ID is required', + field: 'userId' + }); + } + + if (req.user.monitoredUsers.includes(req.body.userId)) { + throw new SafeNSoundError({ + errCode: 'DUPLICATE_KEY_ERROR', + message: 'User is already assigned' + }); + } + + req.user.monitoredUsers.push(req.body.userId); + await req.user.save(); + res.status(204).send(); + } + }, + delete: { + middlewares: [requireMonitor], + description: 'Remove an assigned user by ID', + async method(req, res) { + // noinspection EqualityComparisonWithCoercionJS + req.user.monitoredUsers = req.user.monitoredUsers.filter( + userId => userId != req.body.userId + ); + await req.user.save(); + res.status(204).send(); + } + } + } +}; diff --git a/src/api/routes/auth/accountRoutes.js b/src/api/routes/auth/accountRoutes.js
index 547110e..34592ed 100644 --- a/src/api/routes/auth/accountRoutes.js +++ b/src/api/routes/auth/accountRoutes.js
@@ -2,6 +2,7 @@ import { deleteUser, loginUser, registerUser } from '#db/index.js'; import { AuthDto, RegisterDto } from '#dto/index.js'; import { RouteDescription, RouteMethod } from '#api/RouteDescription.js'; import { WhoAmIDto } from '#dto/auth/WhoAmIDto.js'; +import { requireAuth } from '#api/middlewares/index.js'; /** * @type {RouteDescription} @@ -101,6 +102,7 @@ export const whoAmI = { methods: { get: new RouteMethod({ description: 'Get current user', + middlewares: [requireAuth], async method(req, res) { const data = await WhoAmIDto.create({ userId: req.auth.sub, diff --git a/src/api/routes/index.js b/src/api/routes/index.js
index 4feeb11..bc6c853 100644 --- a/src/api/routes/index.js +++ b/src/api/routes/index.js
@@ -4,3 +4,5 @@ export * from './indexRoute.js'; export * from './auth/index.js'; export * from './budgetRoutes.js'; export * from './alarmRoutes.js'; +export * from './assignedUserRoutes.js'; +export * from './adminRoutes.js'; diff --git a/src/api/routes/statusRoute.js b/src/api/routes/statusRoute.js
index 2c111a8..8ccbf7d 100644 --- a/src/api/routes/statusRoute.js +++ b/src/api/routes/statusRoute.js
@@ -13,7 +13,7 @@ export const statusRoute = { const status = { status: 'ok', timestamp: new Date().toISOString(), - users: await User.countDocuments() + users: await DbUser.countDocuments() }; res.status(200).json(status);