Node JS Express Route Restrict issue - node.js

I'm trying to retrieve audio/image file from db.
app.use(restrictMiddleware());
Tho, because of the Route Restrict: It doesn't work.
The question is, is there any other way to retrieve audio/image file from db so that it won't conflict with Authentication Route Restriction?
self.get = function (req, res) {
let params = [
req.params.record_id,
];
db.query(`SELECT * ...`, params).then((data) => {
console.log('result: ', data.rows.length);
res.contentType('audio/mpeg');
res.send(data.rows[0].audiofile);
}).catch((err) => {
res.status(500).end("Error:" + err);
});
};

Various ways of tackling this:
Simplest way is to declare the route before you call app.use(restrictMiddleware())
Cleanest way is probably go move all the secure routes into their own Router and only apply the restrictMiddleware to that, that way you can add non-secure routes easily
Alternatively, you could check for a specific URL / Header etc in the restrictMiddleware and skip when appropriate (not the nicest, but would do the job)

Related

How to use only PART of the functionality in nested routes NodeJS

So I have a router schoolsRouter where all the school-specific functionality is being handled { login school, adding a new teacher, ...etc.). And I want the admin of the app to be able to add and delete new schools. Now the pattern I'm using encapsulates all the routing functionality in one file schools.routes.js where the School model is exposed. So the createSchool and deleteSchool routes are in the schools.routes.js but I need only the admin to be able to perform those operations and that seems pretty easy with merged routes like this (in admins.routes.js):
adminsRouter.use('/schools/', schoolsRouter);
but the problem is that now the admin can access all the other routes in schools.routes.js like schools/login which is something that I don't want to happen. So how can I make the adminsRouter use the create and delete operations from the schoolsRotuer without being able to access all these other functionalities? (Keeping in mind I'm using JWT authentication).
You could use middlewares in the routes that you wish to controll.
This is the middleware that I will name of admin-middleware.js
module.exports = (req, res, next) => {
if (user.admin === true) {
return next();
} else {
return res.status(403).send('Unauthorized')
}
}
So, this is your route declaration at schools.routes.js
const adminMiddleware = require('../YOUR_FOLDERS/admin-middleware.js');
schools.delete('/:id', adminMiddleware, (req, res) => {
return res.send('ok');
});
If you wish disregard a route, you can use this validation at your code in the middleware.
if(req.originalUrl.includes('/schools/login'))
return next();
I hope that it works to you.

Express: Disable headers for specific routes (Etag, set-cookie, etc)

For my application, we have rest API and the webapp server from the same app. (it is small enought not to have separate deployment)
Is there any way I can exclude all /api/* route paths to disable caching and cookies?
Note: I cannot do app.disable('etag') as it will disable for the entire webapp.
Afaik this is currently not possible - also there are a few open issues on github like this one for example: https://github.com/expressjs/express/issues/2472
As a workaround you could remove the headers for requests on the /api-route using something like this:
const onHeaders = require('on-headers')
// mount custom middleware for all api-requests
app.use("/api*", (req, res, next) => {
removeHeaders(res);
next();
});
function removeHeaders(res) {
onHeaders(res, () => {
res.removeHeader('ETag');
// remove other headers ...
});
}

Best way to handle dynamic routes with its own logic in ExpressJS?

I've been tasked with something at work that's beyond my current skills so any help is appreciated.
I'm building an admin where you can add "games". Each game needs to have it's own front-end, routes, and logic.
Kinda like,
mainsite.com/game/game1
mainsite.com/game/game2
mainsite.com/game/game3
At the moment I'm just creating a directory based on the game name.
var dir = "./games/" + req.body.gameId;
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
In turn I can pull the .ejs file via:
/* GET dynamic game page. */
router.get("/game/:game", function(req, res, next) {
res.render("../games/"+req.params.game+"/index", { title: "Express" });
});
But I am confused on how it can have it's own logic, routes, connecting to database, front-end, stylesheets inside it's own folder.
There must be a better way to achieve this right?
Cheers
Yes! In Express, you can call app.use() inside a route. You will be able to define a public folder to contain the CSS, JS, and assets that are specific to each route. Just call app.use(express.static('route/to/assets')) inside the route.
app.get('/game/:game', (req, res) => {
app.use(express.static(req.params.game + '/public'))
res.render('../games/' + req.params.game + "/index", { title: "Express" })
})
Seems strange, but perfectly allowed.

per-request session in meteor server?

I am adding an auth layer and I think I have it figured out except for one tricky detail.
My Meteor app doesn't have any routes but I've added a hook into the connect middleware so that the "/" route errors if there isn't a correct API token. If the token is okay then I call next() to forward the route to Meteor.
The problem is that, depending on the token, I need to set server-side parameters for the connection, and I don't know how to do this. For example, say I have a static list of API keys mapped to permission levels. If a user sends a request with "ADMIN_API_KEY" then I would like to set Session.permission_level = "admin" for use by the Meteor server's functions. Session is just for the client in Meteor, though.
# this code's in coffeescript
WebApp.connectHandlers.use '/', (req, res, next) ->
validator = new RequestValidator(req, next)
validations = [
"valid_namespace",
"only_https"
]
error = validator.validate(validations)
next(error)
# <<<<<<<<<<<<<<<<<<<<<<<<
# Here I want to set some config option which can be
# read by the server in the same way it can read things like
# Meteor.user()
In Rails I would just say session[:permission_level] = "admin". But it seems to not work this way in Meteor.
By the way, I am not using a Routing package yet in Meteor, though if that would make this easier than I would.
I'm not sure about Session I've been doing something like
import { DDP } from 'meteor/ddp';
import { DDPCommon } from 'meteor/ddp-common';
export const authMiddleware = (req, res, next) => {
const userId = identifyUser(req); // parse the request to get the token you expect
if (!userId) {
return next();
}
DDP._CurrentInvocation.withValue(new DDPCommon.MethodInvocation({
isSimulation: false,
userId,
}), () => {
next();
// in that context, Meteor.userId corresponds to userId
});
};
for my REST api and that works well regarding the user Id and being able to call Meteor function that should be invoke in a DDP context, like Users.find(...).

Is it possible to apply basic authentication / middleware in on routes with a whitelist in Express?

I'm implementing a RESTful API with Express in Node, and I'm new to both. I'd like to use basic authentication to control access.
I would like to apply it using something like a whitelist but I'm not sure how to do that.
Blacklisting is easy, I can just pepper my #VERB calls with the second argument:
app.get('/', asyncAuth, requestHandler);
I can take that even further and blacklist everything with:
app.all('*', asyncAuth, requestHandler);
But I want to apply my basicAuth to every single route, except for POST /users. Is there an elegant way to do that? Can I use the 'blacklist' approach then selectively remove it from the routes I'd like? I couldn't figure out how.
Define your route for POST /users before the blacklisted routes:
app.post('/users', function(req, res) {
...
});
app.all('*', asyncAuth, requestHandler);
You could maintain a list of regexps that are whitelisted, and match the url against each url in the list, if it matches any then proceed, else require auth
app.all('*', asyncAuth);
function asyncAuth(req, res, next) {
var done = false;
whitelist.forEach(function(regexp) {
if (req.url.match(regexp)) {
done = true;
next();
}
});
if (!done) requireAuth(next);
}
Something along those lines

Resources