NUSID - Node.JS User Space for Idle Developers!
NUSID is a generic user space you can use in all your Node.js apps as a starting point. It contains everything, from the MongoDB database model to the dynamic views made with EJS, Bootstrap3 and AngularJS.
If you are an idle developer NUSID is made for you!
Click here to see a live demo!
- Registration
- Login
- "Remember me" session login
- Email verification
- Password recovery
- Account modification
- Account deletion
- Input field validation rules for both the client & server side (centralized with Browserify)
- MongoDB User model with password encryption & salt
- CSRF protection
- Flash message manager
- Responsive design
- Designed in bundles similar to the Symfony framework
- HTTP Strict Transport Security
This is a Node.js app working with MongoDB. Before installing, download and install Node.js. Node.js 0.10 or higher is required. You also need to have a distant access or a local installation of MongoDB.
Installation is done using the
git clone
command and npm install
command:
$ git clone https://github.com/jrebecchi/NUSID.git
$ cd NUSID
$ npm install
Then you need to rename the app.js.exemple
file as app.js
, and edit it to enter your email and MongoDB information:
- MongoDB configuration (where will be stored the users)
global.userDBOptions = {
hostname :"dbuser:dbpassword@host.com",
port :"19150",
database : "user_management"
};
If you wish to use your local MongoDB use the following:
global.userDBOptions = {
hostname :"localhost",
port :"27017",
database : "users"
}
- Email configuration (from where will be sent the administration emails)
global.userspaceMailOptions = {
from: 'myemail@myhost.com', //email address
host: 'smtp.myhost.com', // hostname
secureConnection: true, // use SSL
port: 465, // port for secure SMTP
auth: {
user: 'username', //email login
pass: 'mypassword' //email password
}
};
You can have more options for the email parameters looking at the nodemailer options.
- Server configuration
Adapt the following code to your installation configuration:
server.listen(process.env.PORT || 3000, process.env.IP || "0.0.0.0", function(){
const addr = server.address();
console.log("Server listening at", addr.address + ":" + addr.port);
});
Finally launch this app with :
$ node app.js
TIP! You can deploy for free this NodeJS app on Zeit
TIP! You can have a free MongoDB database on MLab
TIP! You can use a Gmail email by allowing less secure app
NUSID is designed in bundles using the MVC pattern. A bundle is simply a component which contains :
- A router : Redirecting some given routes to its different controllers
- Controlers : Responsible for sending responses the user requests
- Models : To represent the data retrieved from the database and offer different treatment functions
- Services : Any utility methods that can be used anywhere in the bundle
- Views : template views that are sent back by the controllers to the users
Here you are going to learn how to add our own bundles and extend this user space to create your own app ! As an exemple we are going to create a bundle named MyOwnBundle containing 2 routes, one to a public page and one to a private page that you can see only by being connected as a user.
- Step 1: Create your bundle folder under the
bundles
directory
$ mkdir bundles/MyOwnBundle
- Step 2: Create the bundle structure with a
controller
,model
,router
,service
andviews
folder
$ mkdir bundles/MyOwnBundle/controller
$ mkdir bundles/MyOwnBundle/model
$ mkdir bundles/MyOwnBundle/router
$ mkdir bundles/MyOwnBundle/service
$ mkdir bundles/MyOwnBundle/views
$ mkdir bundles/MyOwnBundle/views/pages
- Step 3: Create the entry file of your bundle, the router, a controller and the 2 different views for the public page and the private page
$ touch bundles/MyOwnBundle/MyOwnBundle.js
$ touch bundles/MyOwnBundle/router/Router.js
$ touch bundles/MyOwnBundle/controller/MyOwnController.js
$ touch bundles/MyOwnBundle/views/pages/my-private-tab.ejs
$ touch bundles/MyOwnBundle/views/pages/my-public-tab.ejs
-
Step 4: We are now going to create the public and the private template pages
- Step 4.1: Edit the
my-public-tab.ejs
template as followed
<% include partials/head %> <% include partials/header %> <div class="container"> <div id="content"> <h1>This is a public page</h1> <hr> <p>You don't need to register to see this !</p> </div> </div> <% include partials/footer %> <% include partials/end %>
We use here the
include
mechanism of EJS to import the headers and footers of the page.- Step 4.2: Edit the
my-private-tab.ejs
template
<% include partials/head %> <% include partials/header %> <div class="container"> <div id="content"> <h1>This is a private page</h1> <hr> <p>You need to be registered to see this !</p> </div> </div> <% include partials/footer %> <% include partials/end %>
We do the same for the private page.
- Step 4.1: Edit the
-
Step 5: Edit the controller
MyOwnController.js
that will return those templates we just created
exports.getMyPrivateTab = function (req, res){
res.render('pages/my-private-tab.ejs', { user: req.user });
};
exports.getMyPublicTab = function (req, res){
res.render('pages/my-public-tab.ejs', {csrfToken: req.csrfToken() });
};
For the public page, you need to include a crsfToken to enable the different forms present on the page for unconnected users.
- Step 6: Edit the router
Router.js
that will serve those 2 pages
const MyOwnControler = require("../controller/MyOwnController.js");
const proxy = require('connect-ensure-login');
exports.init = function(app) {
app.get('/myprivatetab', proxy.ensureLoggedIn(),function(req, res){
MyOwnControler.getMyPrivateTab(req, res);
});
app.get('/mypublictab', function(req, res) {
MyOwnControler.getMyPublicTab(req, res);
});
};
For the private page, add the proxy.ensureLoggedIn()
middleware to ensure that the user is logged in to access this page. By taping yourwebsite.com/mypublictab
a user will acces the public page you just created.
- Step 7: Edit the
./bundles/MainBundle/views/partials/header.ejs
file to add some buttons on the header nav-bar redirecting to those 2 pages Add the following on line 14 :
<li><a href="/mypublictab">My public tab</a></li>
<li><a href="/myprivatetab">My private tab</a></li>
- Step 8: Edit the bundle launcher
MyOwnController.js
to init the rooter
const Router = require('./router/Router');
exports.init = function(app) {
//Launch router
Router.init(app);
};
- Step 9: configure the
app.js
file to integrate your new bundle
Import the bundle line 10:
const myOwnBundle = require('./bundles/MyOwnBundle/MyOwnBundle');
Init the bundle line 37:
myOwnBundle.init(app);
Add its view folder in the EJS repository line 43:
path.join(__dirname+'/bundles/MyOwnBundle', 'views')
This example bundle is already included in the actual Nusid repository. Feel free to delete it or modify it!
-
How to modify the general design
You can modify the design and appearance of Nusid by modifying the style sheet located in
./client/css/style.css
and also the different partial templates present in all the pages. Those are located in the MainBundle :./bundles/MainBundle/views/partials
.head.ejs
for the metadata and Javascript/CSS Style sheets importshearder.ejs
for the menu nav-bar of the pagefooter.ejs
for the footer of the pageend.ejs
for the page closing, contains others Javascript/CSS Style sheets importsalerts.ejs
for the flash messenger.
-
How to modify the client-side input form validation
The client-side input form validation use 2 different technologies : AngularJS and Browserify.
You will find the Angular input validation animations in the form templates located here:
./bundles/UserspaceBundle/views/forms
and its Javascript code in this file :./client/js/app.js
.Thanks to Browserify the Angular Javascript code in
app.js
can use therequire
function and import the input validation rules from the server located in./bundles/UserspaceBundle/service/forms
. It means that the same code validate the inputs client and server side.If you want to modify the code in
app.js
you will have to install browserify which provide thisrequire
function. !!Warning!! Every time you modify this code you will have to run the following command in a terminal :$ browserify client/js/app.js -o client/js/app-browserified.js
The web pages will indeed import the
app-browserified.js
file which will convert the require imports into something the browser can read. -
How to change the input validation rules
You can change the input validation rules by editing the validation callbacks located in
./bundles/UserspaceBundle/service/forms/callbacks/ValidationCallbacks.js
. Those functions have to return an object with 2 properties :hasError
: if the input has an errorerrorMsg
: the error message to display to the user ifhasError
istrue
-
How to change the general behavior of the UserspaceBundle
You have to modify the different controllers located in
./bundles/UserspaceBundle/controller
and also its user model./bundles/UserspaceBundle/model/UserModel.js
. Feel free to contact me if you need any information.
If you discover a security vulnerability or a bug please contact me.
NUSID wish to give you a starting point into your Node.js project with a complete user space and also a framework. This app is architectured in bundles, similarly as in the PHP framework Symfony. Feel free to adapt/modify the present bundles to make them fit your needs and simply add your own bundles as shown above.
If you want to share some improvements, contact me and I will add you as a contributor.