summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/api/RouteDescription.js74
-rw-r--r--src/api/middlewares/authMiddleware.js4
-rw-r--r--src/api/routes.js73
-rw-r--r--src/api/routes/alarmRoutes.js101
-rw-r--r--src/api/routes/auth/accountRoutes.js78
-rw-r--r--src/api/routes/auth/adminAccountRoutes.js48
-rw-r--r--src/api/routes/auth/deviceRoutes.js45
-rw-r--r--src/api/routes/budgetRoutes.js46
-rw-r--r--src/api/routes/indexRoute.js15
-rw-r--r--src/api/routes/statusRoute.js24
10 files changed, 328 insertions, 180 deletions
diff --git a/src/api/RouteDescription.js b/src/api/RouteDescription.js
new file mode 100644

index 0000000..6ca426b --- /dev/null +++ b/src/api/RouteDescription.js
@@ -0,0 +1,74 @@ +export class RouteDescription { + path; + /** + * @type {RouteMethodList} + */ + methods; + + /** + * @param data {RouteDescription} + */ + constructor(data) { + for (const key of Object.keys(data)) { + this[key] = data[key]; + } + } +} + +export class RouteMethodList { + /** + * @type {RouteMethod} + */ + get; + /** + * @type {RouteMethod} + */ + post; + /** + * @type {RouteMethod} + */ + put; + /** + * @type {RouteMethod} + */ + delete; + /** + * @type {RouteMethod} + */ + patch; + + /** + * @param data {RouteMethodList} + */ + constructor(data) { + for (const key of Object.keys(data)) { + this[key] = data[key]; + } + } +} + +export class RouteMethod { + /** + * @type {Array<Promise>} + */ + middlewares = []; + /** + * @type {Promise} + */ + method; + + description; + + exampleBody; + + /** + * @param data {RouteMethod} + */ + constructor(data) { + for (const key of Object.keys(data)) { + this[key] = data[key]; + } + + if (!Array.isArray(this.middlewares)) this.middlewares = []; + } +} diff --git a/src/api/middlewares/authMiddleware.js b/src/api/middlewares/authMiddleware.js
index 8553517..19de4d8 100644 --- a/src/api/middlewares/authMiddleware.js +++ b/src/api/middlewares/authMiddleware.js
@@ -30,6 +30,10 @@ export function validateAuth(options) { }; } +export const requireUser = validateAuth({ roles: [UserType.USER] }); +export const requireMonitor = validateAuth({ roles: [UserType.MONITOR] }); +export const requireAdmin = validateAuth({ roles: [UserType.ADMIN] }); + class AuthValidationOptions { roles; } diff --git a/src/api/routes.js b/src/api/routes.js
index 5151187..ade440e 100644 --- a/src/api/routes.js +++ b/src/api/routes.js
@@ -15,60 +15,31 @@ function logHttpEntry(method, route, exampleBody) { export function registerRoutes(app) { // http file header: console.log('%', ''); - - // app.get("/status", routes.statusRoute); let routeCount = 0; - Object.values(routes).forEach(route => { - console.log('Registering route:', route); - if (!route.route) - throw new Error( - "Route definition is missing 'route' property: " + - JSON.stringify(route) - ); - - if (route.onGet) { - if (route.onGetValidation) - app.get(route.route, route.onGetValidation, route.onGet); - else app.get(route.route, route.onGet); - routeCount++; - logHttpEntry('GET', route.route, route.exampleGetBody); - } - - if (route.onPost) { - if (route.onPostValidation) - app.post(route.route, route.onPostValidation, route.onPost); - else app.post(route.route, route.onPost); - routeCount++; - logHttpEntry('POST', route.route, route.examplePostBody); - } - if (route.onPut) { - if (route.onPutValidation) - app.put(route.route, route.onPutValidation, route.onPut); - else app.put(route.route, route.onPut); + Object.keys(routes).forEach(routeName => { + /** + * @type {RouteDescription} + */ + const route = routes[routeName]; + console.log( + `Registering ${routeName} (${route.path})`, + routes[routeName] + ); + + Object.keys(route.methods).forEach(routeMethodName => { + /** + * @type {RouteMethod} + */ + const routeMethod = route.methods[routeMethodName]; + console.log(routeMethodName, routeMethod); + app[routeMethodName](route.path, [ + ...routeMethod.middlewares, + routeMethod.method + ]); routeCount++; - logHttpEntry('PUT', route.route, route.examplePutBody); - } - - if (route.onDelete) { - if (route.onDeleteValidation) - app.delete( - route.route, - route.onDeleteValidation, - route.onDelete - ); - else app.delete(route.route, route.onDelete); - routeCount++; - logHttpEntry('DELETE', route.route, route.exampleDeleteBody); - } - - if (route.onPatch) { - if (route.onPatchValidation) - app.patch(route.route, route.onPatchValidation, route.onPatch); - else app.patch(route.route, route.onPatch); - routeCount++; - logHttpEntry('PATCH', route.route, route.examplePatchBody); - } + }); }); + console.log(`Registered ${routeCount} routes.`); } diff --git a/src/api/routes/alarmRoutes.js b/src/api/routes/alarmRoutes.js
index e50d4b2..9739f4f 100644 --- a/src/api/routes/alarmRoutes.js +++ b/src/api/routes/alarmRoutes.js
@@ -1,49 +1,78 @@ -import { validateAuth } from '#api/middlewares/index.js'; +import { + requireMonitor, + requireUser, + validateAuth +} from '#api/middlewares/index.js'; import { UserType } from '#db/schemas/index.js'; +import { RouteMethod } from '#api/RouteDescription.js'; +/** + * @type {RouteDescription} + */ export const alarmByUserRoute = { - route: '/alarm/:id', - onGetValidation: validateAuth({ roles: [UserType.MONITOR] }), - async onGet(req, res) { - const user = await getUserById(req.params.id); - res.send(user.alarm); - }, - - onDeleteValidation: validateAuth({ roles: [UserType.MONITOR] }), - async onDelete(req, res) { - const user = await getUserById(req.params.id); - user.alarm = null; - await user.save(); - res.status(204).send(); + path: '/alarm/:id', + methods: { + get: new RouteMethod({ + middlewares: [requireMonitor], + async method(req, res) { + const user = await getUserById(req.params.id); + res.send(user.alarm); + } + }), + put: new RouteMethod({ + middlewares: [requireMonitor], + async method(req, res) { + const user = await getUserById(req.params.id); + user.alarm = null; + await user.save(); + res.status(204).send(); + } + }) } }; +/** + * @type {RouteDescription} + */ export const alarmListRoute = { - route: '/alarms', - onGetValidation: validateAuth({ roles: [UserType.MONITOR] }), - onGet(req, res) { - console.log(req.user.monitoredUsers); + path: '/alarms', + methods: { + get: new RouteMethod({ + middlewares: [requireMonitor], + async method(req, res) { + console.log(req.user.monitoredUsers); + } + }) } }; +/** + * @type {RouteDescription} + */ export const alarmRoute = { - onGetValidation: validateAuth({ roles: [UserType.USER] }), - async onGet(req, res) { - res.send(req.user.alarm); - }, - - route: '/alarm/@me', - onPutValidation: validateAuth({ roles: [UserType.USER] }), - async onPut(req, res) { - req.user.alarm = req.body; - await req.user.save(); - res.status(204).send(); - }, - - onDeleteValidation: validateAuth({ roles: [UserType.USER] }), - async onDelete(req, res) { - req.user.alarm = null; - await req.user.save(); - res.status(204).send(); + path: '/alarm/@me', + methods: { + get: new RouteMethod({ + middlewares: [requireUser], + async method(req, res) { + res.send(req.user.alarm); + } + }), + put: new RouteMethod({ + middlewares: [requireUser], + async method(req, res) { + req.user.alarm = req.body; + await req.user.save(); + res.status(204).send(); + } + }), + delete: new RouteMethod({ + middlewares: [requireUser], + async method(req, res) { + req.user.alarm = null; + 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 18c204d..76452e3 100644 --- a/src/api/routes/auth/accountRoutes.js +++ b/src/api/routes/auth/accountRoutes.js
@@ -1,44 +1,70 @@ import { deleteUser, loginUser, registerUser } from '#db/index.js'; import { AuthDto, RegisterDto } from '#dto/index.js'; +import { RouteDescription, RouteMethod } from '#api/RouteDescription.js'; +/** + * @type {RouteDescription} + */ export const registerRoute = { - route: '/auth/register', - async onPost(req, res) { - const data = await RegisterDto.create(req.body); - await registerUser(data); - res.status(204).send(); + path: '/auth/register', + methods: { + post: new RouteMethod({ + async method(req, res) { + const data = await RegisterDto.create(req.body); + await registerUser(data); + res.status(204).send(); + } + }) } }; +/** + * @type {RouteDescription} + */ export const loginRoute = { - route: '/auth/login', - async onPost(req, res) { - const data = await AuthDto.create(req.body); - const loginResult = await loginUser(data, req.headers['user-agent']); - res.send(loginResult); + path: '/auth/login', + methods: { + post: new RouteMethod({ + async method(req, res) { + const data = await AuthDto.create(req.body); + const loginResult = await loginUser( + data, + req.headers['user-agent'] + ); + res.send(loginResult); + } + }) } }; +/** + * @type {RouteDescription} + */ export const logoutRoute = { - route: '/auth/logout', - /** - * - * @param req {Request} - * @param res - * @returns {Promise<WhoAmIDto>} - */ - async onPost(req, res) { - const data = await AuthDto.create(req.body); - // const loginResult = await deleteDevice(data, ); - res.status(204).send(); + path: '/auth/logout', + methods: { + post: new RouteMethod({ + async method(req, res) { + const data = await AuthDto.create(req.body); + // const loginResult = await deleteDevice(data, ); + res.status(204).send(); + } + }) } }; +/** + * @type {RouteDescription} + */ export const deleteRoute = { - route: '/auth/delete', - async onDelete(req, res) { - const data = await AuthDto.create(req.body); - await deleteUser(data); - res.status(204).send(); + path: '/auth/delete', + methods: { + delete: new RouteMethod({ + async method(req, res) { + const data = await AuthDto.create(req.body); + await deleteUser(data); + res.status(204).send(); + } + }) } }; diff --git a/src/api/routes/auth/adminAccountRoutes.js b/src/api/routes/auth/adminAccountRoutes.js
index f85cc73..eb9b270 100644 --- a/src/api/routes/auth/adminAccountRoutes.js +++ b/src/api/routes/auth/adminAccountRoutes.js
@@ -1,24 +1,42 @@ import { deleteUser, loginUser, registerUser, UserType } from '#db/index.js'; import { AuthDto, RegisterDto } from '#dto/index.js'; -import { validateAuth } from '#api/middlewares/index.js'; +import { requireAdmin, validateAuth } from '#api/middlewares/index.js'; +import { RouteDescription, RouteMethod } from '#api/RouteDescription.js'; +/** + * @type {RouteDescription} + */ export const adminGetUsersRoute = { - route: '/admin/users', - onGetValidation: validateAuth({ roles: [UserType.ADMIN] }), - async onGet(req, res) { - res.send(DbUser.find({}).exec()); + path: '/admin/users', + methods: { + get: new RouteMethod({ + middlewares: [requireAdmin], + async method(req, res) { + res.send(DbUser.find({}).exec()); + } + }) } }; -export const adminUserRoute = { - route: '/admin/user/:id', - onGetValidation: validateAuth({ roles: [UserType.ADMIN] }), - async onGet(req, res) { - const user = await getUserById(req.params.id); - }, - onDeleteValidation: validateAuth({ roles: [UserType.ADMIN] }), - async onDelete(req, res) { - await deleteUser(data); - res.status(204).send(); +/** + * @type {RouteDescription} + */ +export const adminUserRoute = { + path: '/admin/user/:id', + methods: { + get: new RouteMethod({ + middlewares: [requireAdmin], + async method(req, res) { + const user = await getUserById(req.params.id); + res.send(user); + } + }), + delete: new RouteMethod({ + middlewares: [requireAdmin], + async method(req, res) { + await deleteUser(data); + res.status(204).send(); + } + }) } }; diff --git a/src/api/routes/auth/deviceRoutes.js b/src/api/routes/auth/deviceRoutes.js
index 11cae8f..ac4514f 100644 --- a/src/api/routes/auth/deviceRoutes.js +++ b/src/api/routes/auth/deviceRoutes.js
@@ -1,38 +1,21 @@ import { deleteUser, loginUser, registerUser } from '#db/index.js'; import { AuthDto, RegisterDto } from '#dto/index.js'; import { validateAuth } from '#api/middlewares/index.js'; +import { RouteDescription, RouteMethod } from '#api/RouteDescription.js'; +/** + * @type {RouteDescription} + */ export const getDevicesRoute = { - route: '/auth/devices', - onGetValidation: validateAuth({}), - async onGet(req, res) { - const data = await RegisterDto.create(req.body); - const registerResult = await registerUser(data); - res.send(registerResult); + path: '/auth/devices', + methods: { + get: new RouteMethod({ + middlewares: [validateAuth({})], + async method(req, res) { + const data = await RegisterDto.create(req.body); + const registerResult = await registerUser(data); + res.send(registerResult); + } + }) } }; - -// export const loginRoute = { -// route: '/auth/login', -// /** -// * -// * @param req {Request} -// * @param res -// * @returns {Promise<WhoAmIDto>} -// */ -// async onPost(req, res) { -// const data = await AuthDto.create(req.body); -// console.log(req.headers['user-agent']); -// const loginResult = await loginUser(data, req.headers['user-agent']); -// res.send(loginResult); -// } -// }; -// -// export const deleteRoute = { -// route: '/auth/delete', -// async onDelete(req, res) { -// const data = await AuthDto.create(req.body); -// await deleteUser(data); -// res.status(204).send(); -// } -// }; diff --git a/src/api/routes/budgetRoutes.js b/src/api/routes/budgetRoutes.js
index ed827e8..1cebffe 100644 --- a/src/api/routes/budgetRoutes.js +++ b/src/api/routes/budgetRoutes.js
@@ -1,20 +1,46 @@ -import { validateAuth } from '#api/middlewares/index.js'; +import { + requireMonitor, + requireUser, + validateAuth +} from '#api/middlewares/index.js'; import { UserType } from '#db/schemas/index.js'; +import { RouteDescription, RouteMethod } from '#api/RouteDescription.js'; +/** + * @type {RouteDescription} + */ export const getBudgetByUserRoute = { - route: '/budget/:id', - onGetValidation: validateAuth({ roles: [UserType.MONITOR] }), - onGet(req, res) {} + path: '/budget/:id', + methods: { + get: new RouteMethod({ + middlewares: [requireMonitor], + async method(req, res) {} + }) + } }; +/** + * @type {RouteDescription} + */ export const addBudgetByUserRoute = { - route: '/budget/:id/add', - onGetValidation: validateAuth({ roles: [UserType.MONITOR] }), - onGet(req, res) {} + path: '/budget/:id/add', + methods: { + get: new RouteMethod({ + middlewares: [requireMonitor], + async method(req, res) {} + }) + } }; +/** + * @type {RouteDescription} + */ export const getBudgetRoute = { - route: '/budget/@me', - onGetValidation: validateAuth({ roles: [UserType.USER] }), - onGet(req, res) {} + path: '/budget/@me', + methods: { + get: new RouteMethod({ + middlewares: [requireUser], + async method(req, res) {} + }) + } }; diff --git a/src/api/routes/indexRoute.js b/src/api/routes/indexRoute.js
index 3b9eaef..b6fe28e 100644 --- a/src/api/routes/indexRoute.js +++ b/src/api/routes/indexRoute.js
@@ -1,6 +1,15 @@ +import { RouteDescription, RouteMethod } from '#api/RouteDescription.js'; + +/** + * @type {RouteDescription} + */ export const indexRoute = { - route: '/', - onGet(req, res) { - res.send('What art thou doing here???'); + path: '/', + methods: { + get: new RouteMethod({ + method(req, res) { + res.send('What art thou doing here???'); + } + }) } }; diff --git a/src/api/routes/statusRoute.js b/src/api/routes/statusRoute.js
index 5c3231b..1dbca45 100644 --- a/src/api/routes/statusRoute.js +++ b/src/api/routes/statusRoute.js
@@ -1,14 +1,22 @@ import { DbUser } from '#db/index.js'; +import { RouteDescription, RouteMethod } from '#api/RouteDescription.js'; +/** + * @type {RouteDescription} + */ export const statusRoute = { - route: '/status', - async onGet(req, res) { - const status = { - status: 'ok', - timestamp: new Date().toISOString(), - users: await User.countDocuments() - }; + path: '/status', + methods: { + get: new RouteMethod({ + async method(req, res) { + const status = { + status: 'ok', + timestamp: new Date().toISOString(), + users: await User.countDocuments() + }; - res.status(200).json(status); + res.status(200).json(status); + } + }) } };