User authentication, waiting lists, and invitations for express
Drawbridge.js is a Node.js module for adding authentication, waiting lists and account invitations to an Express.js application. Drawbridge stores all its data in a Redis database obviating migrations or slow queries. Drawbridge.js includes an admin panel to view those on the waiting list, sent invitations and app users.
The goal of Drawbridge is to create a password authentication module that requires as few lines of code to add authentication to your app. While drawbridge creates a views and email templates you are free to change their content - only the names of the templates and views need to stay the same.
The Good Drawbridge makes it extremely easy to add authentication to your express.js app. Drawbridge uses bcrypt to hash bash passwords and Redis to store its data.
The Bad Drawbridge still needs a lot of work, and should be considered an alpha product.
The Ugly I need your help to make it better! Unit Tests and Integration Tests have not been added yet. I wanted to gage interests in Drawbridge and its features before I tested its components (poor excuse, I know). Furthermore, lots of the code needs refactoring and better organization (fun!).
npm install drawbridgejs -g
In the root of your express application's directory, from the terminal:
drawbridge build shell command will create a number of views, email templates, a Terms of Service text file, and a configuration file (drawbridge.config.json). It is important that you modify the values on the configuration file before you get started - if you do not, emails will not be sent. See the drawbridge.config.json section below for more details. Also note that the express app was created using the
--sessions switch, to add support for sessions.
var express = require'express'routes = require'./routes'drawbridge = require'drawbridge';var app = moduleexports = expresscreateServer;appconfigureappset'views' __dirname + '/views';appset'view engine' 'jade';appuseexpressbodyParser;appuseexpressmethodOverride;appuseexpresscookieParser;appuseexpresssession secret: 'your secret here' ;appuseapprouter;appuseexpressstatic__dirname + '/public';appuseexpresslogger;;// start drawbridge using .up()drawbridge = drawbridgeup app ;// provide a function to be called after a user logindrawbridgeafterLoginresponseredirect'/' + userscreenName ;;// A route with authenticationappget'/:screenName' drawbridgeauthenticateUserresjson drawbridgecurrentUser req// Routesappget'/' routesindex;applisten3000;console.log"Express server listening on port %d in %s mode" appaddressport appsettingsenv;
Drawbridge provides all the basic password authentication services and views. It provides:
Many new applications start with a sign-up form that put potential users on a waiting list. Drawbridge.js provides the code for both the sign-up form and the functionality to store the sign-up data, and notify the potential user, via email, that the sign-up was successful. To add the sign-up form to your site see the "View Partial" section below.
The app's admin can then use Drawbridge.js's admin view to manually invite each user ( if there is interest inviting users could be automated ). Once a user is invited, they are sent an email with a registration link that includes a unique token. After a user register they receive an email with a confirmation email. Once they've confirmed their account they're logged in.
Drawbridge.js can currently send emails using postmark or nodemailer. To use either service the drawbridge.config.json must be modified. Adding adapters for other emailing methods should be extremely easy, see
lib/email.js and the files within
To use nodemailer:
"email" :"module" : "nodemailer""service" : "Gmail""auth" :"user" : "firstname.lastname@example.org""pass" : "password"
To use postmark:
IMPORTANT: To use postmark the "from" email addresses in the drawbridge.config.json file have to be registered as "Sender Signatures" within your Postmark.com account.
"email" :"module" : "postmark""APIKEY" : "********-****-****-****-************"
The drawbridge.config.json files defines all of the basic settings an configuration for drawbridge. It defines all of the "subject" and "from" values for each email type that drawbridge sends. It defines the email and database modules that it uses ( right now the only database is Redis ). It also defines a super user account that is created when drawbridge is instantiated.
The drawbridge.config.json file also has a flag for whether your app will include a waitlist ("waitlist" : true - within the "signups" sub object). If the waitlist flag is true only those invited will be able to register.
.afterLogin is called directly after a user 1) logins, 2) confirms registration and 3) resets their password. If this function is not called, drawbridge will redirect to the root url.
drawbridgeafterLoginresponseredirect '/users/' + userscreenName ;;
.authenticateUser() is used to add authenticate to a route.
appget '/account/:screenName' drawbridgeauthenticateUservar screenName = reqparamsscreenName;resrender'account' title: 'Account' screenName : screenName ;;
.authenticateSuperUser() is used to authenticate users with the
superUser flag for a route.
appget '/admin/settings' drawbridgeauthenticateSuperUservar settings = databasegetSettings;resrender'admin/settings' title: 'Settings' settings : settings ;;
.currentUser() returns the logged in user associated with the current request.
appget '/getuser.json' drawbridgeauthenticateUserresjson drawbrdigegetCurrentUser req ;;
.getUser() takes an object that specifies either an email, or a screenName, and through the callback function returns the matching user. If there is no matching user
null is returned.
var aUser;drawbridgegetUser email: 'email@example.com'if errorthrow "An error!!!"elseaUser = user;;
.changeUsersAttributes() will modify the value for keys that already exist for a user. If a key in object does not exist, the key and value will be added to the user.
var obj =firstName : "Ringo"lastName : "Star";drawbridgechangeUsersAttributes 'firstname.lastname@example.org' objif errorthrow "Oh no!";elseconsole.log "Success" ;;
.getUsers() takes a callback function and returns an array with all the users in the database.
appget'/numUsers.json'drawbrdigegetUsersresjson userslength ;;;
.getWaitlist() takes a callback function and returns an array of objects, each object representing a person on the waiting list.
appget'/waitinglist'drawbrdigegetWaitlistresrender'waitlist' title : "Waitlist" waitlist : users ;;;
.getInvited() takes a callback function and returns an array of objects, each object representing a person who has been invited.
appget'/invited'drawbridgegetInvitedresrender'invited' title : "Invited" invited : users ;;
MIT License. Copyright 2012 Liam Kaufman. http://liamkaufman.com