Node.js Express: require/use one app within another - node.js

I'm facing the following situation. In order to further modulize my software development, I've written a few standard modules stand alone. Think for instance of an login module based upon Express and Passport, allowing users to login with all kinds of social services. The module also contains UI for user management, login, registration, profile, etc.
Now, the thing I'm trying to do is to just drop the Auth app folder (containing the express app, all it's routes, views, models, settings and dependecies) into another Express app (for instance, a CMS) and then load it with something like require('./lib/auth/app.js'). I know this is possible, take a look at Kue.
How would I go about doing this? And how do I manage namespacing problems? I could of cours append /auth/ to each route, but I can imagine the settings (app.use()'s) and public folder would conflict with the 'parent' app.js' settings and public folder.
Thanks in advance,
Fabian

Think I found my answer. So, I found this question, and this one. Guess my terminology was off.
I solved my problem by doing a few things. First of all, I changed all routes and url's to be "namespaced" (not really, but this does the job). All routes now have /auth/ in front of them. I did the same to all links, so that's all working.
Next, I removed the server part from my app.js. So, in stead of doing:
require('http').createServer(app).listen(app.get('port'));
I just do:
module.exports = app;
And I add some custom methods to the app object:
app.isLoggedIn = auth.isLoggedIn;
app.notLoggedIn = auth.notLoggedIn;
Then, in my root app, I just do the following to load the auth app in. Routing, public files, and all other stuff happens magically. pretty cool.
var auth = require('./vendor/auth/app');
var app = express();
app.configure(function() {
app.use(auth); // use our auth app
// do a lot of root-app related stuff...
});
Things still to do:
My auth app uses some session stuff. According to the second link, if I understand correctly, the app.use(session...) stuff in my auth app gets overridden by app.use. Also, I want to define an EJS helper to generate my urls (something like site_url('/facebook/callback') which then points to /auth/facebook/callback). Finally, I need to include settings from my root app. I'm thinking of wrapping my entire app.js (in auth) in a function, to which I pass a config object. Like this:
module.exports = function(config) {
var app = express();
app.set('config', config);
// various app settings, routes, etc
// return app so it's available in my root.
return app;
}
I hope this helps, if you need a bit more information I'll see if I can post some code to a gist. just let me know!

Related

Implementing Passport Local Authentication in Backend

I am trying to implement the passport local authentication in my backend. It is a todo app which is built with the help of the MEAN stack. Unfortunately, I am facing some problems implementing it. The folder structure is
In Controllers folder, the controllers for the various routes are present.
In routes folder, the file "api.route.js" contains the main route. I want to implement authentication here such that no further routes can be accessed if the user is not autheticated.
In the api subfolder, the different routes are configured.
In the config subfolder, the passport local strategy is defined.
Another new problem I have noticed is that the routes after todo are not detected.
Example : localhost:3000/api/todos
localhost :3000/api/todos/login
route does not work. It says Error 404. Every other sub routes are the same. Any help which will help me to implement will be appreciated. The github profile for this project is :
https://github.com/AritraWork97/TODO-FULLSTACK
The main folder is Todo Backend, it contains the backend code
To, protect routes in back-end I think express-jwt will be handy.
Initialize it like this,
const jwt = require("express-jwt");
const auth = jwt({secret: jwt_secret});
Then put the auth middleware before a route that you want to protect.
router.get("/secret/:uid", auth, profileCtrl.secret);

Register new route at runtime in NodeJs/ExpressJs

I want to extend this open topic: Add Routes at Runtime (ExpressJs) which sadly didn't help me enough.
I'm working on an application that allows the creation of different API's that runs on NodeJs. The UI looks like this:
As you can see, this piece of code contains two endpoints (GET, POST) and as soon as I press "Save", it creates a .js file located in a path where the Nodejs application is looking for its endpoints (e.g: myProject\dynamicRoutes\rule_test.js).
The problem that I have is that being that the Nodejs server is running while I'm developing the code, I'm not able to invoke these new endpoints unless I restart the server once again (and ExpressJs detects the file).
Is there a way to register new routes while the
NodeJs (ExpressJs) is running?
I tried to do the following things with no luck:
app.js
This works if the server is restarted. I tried to include this library (express-dynamic-router, but not working at runtime.)
//this is dynamic routing function
function handleDynamicRoutes(req,res,next) {
var path = req.path; //http://localhost:8080/api/rule_test
//LoadModules(path)
var controllerPath = path.replace("/api/", "./dynamicRoutes/");
var dynamicController = require(controllerPath);
dynamicRouter.index(dynamicController[req.method]).register(app);
dynamicController[req.method] = function(req, res) {
//invocation
}
next();
}
app.all('*', handleDynamicRoutes);
Finally, I readed this article (#NodeJS / #ExpressJS: Adding routes dynamically at runtime), but I couldn't figure out how this can help me.
I believe that this could be possible somehow, but I feel a bit lost. Anyone knows how can I achieve this? I'm getting a CANNOT GET error, after each file creation.
Disclaimer: please know that it is considered as bad design in terms of stability and security to allow the user or even administrator to inject executable code via web forms. Treat this thread as academic discussion and don't use this code in production!
Look at this simple example which adds new route in runtime:
app.get('/subpage', (req, res) => res.send('Hello subpage'))
So basically new route is being registered when app.get is called, no need to walk through routes directory.
All you need to do is simply load your newly created module and pass your app to module.exports function to register new routes. I guess this one-liner should work just fine (not tested):
require('path/to/new/module')(app)
Is req.params enough for you?
app.get('/basebath/:path, (req,res) => {
const content = require('content/' + req.params.path);
res.send(content);
});
So the user can enter whatever after /basepath, for example
http://www.mywebsite.com/basepath/bergur
The router would then try to get the file content/bergur.js
and send it's contents.

What does an express app instance give you over an express router instance?

I've come across an interesting situation where we're using express app composition:
const rootApp = express();
const moduleOne = express();
const moduleTwo = express();
rootApp.use(moduleOne);
rootApp.use(moduleTwo);
rootApp.listen(3000);
Each of these module apps have their own routers, middleware, etc. and I was wondering what are some advantages and disadvantages of having app composition versus router composition at a higher level.
It generally allows for better isolation and use of middleware. For example I tend to roll with multiple Express Applications (composed together) when building CRUD based apps which use Single Page Web Apps (React, Ember, Angular, etc). This allows me to attach different headers to each incredibly easier.
It also makes it very easy to move each application into it's own repo, this could be useful if you later on wish to run each application as it's own service. You could then use something like nginx to route to two apps. For example:
myapp.com/api/auth -> authentication express app
myapp.com/api -> general API
myapp.com/ -> light weight express app which serves the front end.
This makes it much easier to scale your application later on, and allows more fine grained control.
In the short term, the control over various middleware is the thing I find most useful about composing express apps vs composing express routers. It means you can do "app.use()" and tends to read a lot better to other developers coming to your project.
An app is a router object with a few more properties and methods related to the overall state of your app. Properties on the app object like app.locals or methods like app.listen() apply to your whole app, not just to a set of routes. Other than that though, you can think of an app like a subclass of a router with all the capabilities of a router with added app properties.
If you look in the source code for the app object, you will see that it has a router in its instance data (not sure why they didn't actually subclass it):
this._router = new Router({...});
And, then further examination of the code shows that app.use(), app.get(), etc... all flow through that above router.
So, your app objects works just perfectly fine if all you need is one router. But, there are reasons to use more than one router. For example, if you have a series of sub-routes (say everything that starts with /api/xxx) that you want to do some authentication on, but lots of other routes don't require that auth, then you can create a router for /api, define middleware on only that router that checks your auth and then define the sub-routes on that router and you get a nice encapsulated definition of sub-routes all with their own middleware.

KeyStone JS Account Controller

I understand MVC structure when coding in NodeJS. I started using Keystone JS recently, and I really like it. But, the way they set their controllers up, it seems that the controllers ONLY serve the purpose of rendering a view.
In an earlier project, I had an Account.js model and an Account.js controller. I'm trying to see how it would copy over to keystone.
So: How would I allow users to signup/signin/logout in a Keystone project (not into the Admin UI, but like a member of a regular site)? How would I make an Account controller (obviously with no view to render)?
There are lots of ways you can implement your own methods of authentication and account management in keystone since it is based on express.js.
You can then add an array of 'middleware' functions to routes which will run before passing the request to the controller.
e.g
Route before middleware added
app.get('/admin', routes.views.userAdmin);
Middleware Function
function isAuthenticated(req, res, next) {
// do any checks you want to in here
// CHECK THE USER STORED IN SESSION FOR A CUSTOM VARIABLE
// you can do this however you want with whatever variables you set up
if (req.user.authenticated)
return next();
// IF A USER ISN'T LOGGED IN, THEN REDIRECT THEM SOMEWHERE
res.redirect('/');
}
Route with middleware added
app.get('/admin', isAuthenticated, routes.views.userAdmin);
It's a very broad questions so I'd recommend you go and decide on the best way you'd like to do it yourself as everyone has their own personal preference. The search terms you want are 'express middleware authentication'. A lot of people use PassporJS http://passportjs.org/
Hope that helps :)

Use Settings of Used Middleware

By "setting" I mean "something that is set", similar to "setters" in Java & other OO languages, not Express's "application settings". Is there a way to access and ideally use "settings" set inside middleware use()d by the app? In particular, some middleware is a full Express app, like vhost and the new Router middleware that comes with Express 4.x. If you do most of your routing in a virtual host and want to access some route param from the main app, that could be a problem. This is especially true if you have several layers, like I'm having, and it would be inconvenient to export the setting all the way out to the main app.
So is there a way to access these settings from the main app?
In particular, some middleware is a full Express app
Express 4.x has a great new feature to get around this problem. You can now use express.Router directly. In cases where you used to use an entire routing path by using a second sub-Express object as middleware, now you can just use Router.
For anything else, I usually add properties to the request object, namespaced by the name of my app.
function (req, res, next) {
req.myApp = req.myApp || {};
req.myApp.someData='whatever';
next();
}
The next middleware in the line will have access to this variable. I use this to track unique connection IDs, assigned by the first piece of middleware and subsequently used by others.

Resources