Socket
Socket
Sign inDemoInstall

email-verification

Package Overview
Dependencies
61
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.1.9 to 0.2.0

.jshintrc

205

index.js

@@ -1,7 +0,7 @@

"use strict";
'use strict';
var randtoken = require('rand-token'),
mongoose = require('mongoose'),
nodemailer = require('nodemailer');
// mongoose.connect("mongodb://localhost/YOUR_DB"); // needed for testing
nodemailer = require('nodemailer'),
async = require('async');

@@ -15,13 +15,16 @@ /**

* @param {string} def - default value to return if not found
*/
var getNestedValue = function(obj, path, def){
*/
var getNestedValue = function(obj, path, def) {
var i, len;
for(i = 0,path = path.split('.'), len = path.length; i < len; i++){
if(!obj || typeof obj !== 'object') return def;
for (i = 0, path = path.split('.'), len = path.length; i < len; i++) {
if (!obj || typeof obj !== 'object') {
return def;
}
obj = obj[path[i]];
}
if(obj === undefined)
if (obj === undefined) {
return def;
}
return obj;

@@ -56,10 +59,13 @@ };

html: '<p>Please verify your account by clicking <a href="${URL}">this link</a>. If you are unable to do so, copy and ' +
'paste the following link into your browser:</p><p>${URL}</p>',
'paste the following link into your browser:</p><p>${URL}</p>',
text: 'Please verify your account by clicking the following link, or by copying and pasting it into your browser: ${URL}'
},
verifySendMailCallback: function(err, info) {
if (err) throw err;
else console.log(info.response);
if (err) {
throw err;
} else {
console.log(info.response);
}
},
sendConfirmationEmail: true,
shouldSendConfirmation: true,
confirmMailOptions: {

@@ -72,4 +78,7 @@ from: 'Do Not Reply <user@gmail.com>',

confirmSendMailCallback: function(err, info) {
if (err) throw err;
else console.log(info.response);
if (err) {
throw err;
} else {
console.log(info.response);
}
},

@@ -87,6 +96,9 @@ };

* @param {object} o - options to be changed
*/
*/
var configure = function(o) {
for (var key in o)
options[key] = o[key];
for (var key in o) {
if (o.hasOwnProperty(key)) {
options[key] = o[key];
}
}
transporter = nodemailer.createTransport(options.transportOptions);

@@ -103,6 +115,6 @@ };

* @param {object} User - the persistent User model.
*/
*/
var generateTempUserModel = function(User) {
var tempUserSchemaObject = {}, // a copy of the schema
tempUserSchema, tempUserModel;
tempUserSchema;

@@ -116,3 +128,7 @@ // copy over the attributes of the schema

// create a TTL
tempUserSchemaObject.createdAt = {type: Date, expires: options.expirationTime.toString() + 's', default: Date.now};
tempUserSchemaObject.createdAt = {
type: Date,
expires: options.expirationTime.toString() + 's',
default: Date.now
};

@@ -125,4 +141,6 @@ tempUserSchema = mongoose.Schema(tempUserSchemaObject);

});
options.tempUserModel = mongoose.model(options.tempUserCollection, tempUserSchema);
return mongoose.model(options.tempUserCollection);
};

@@ -140,7 +158,9 @@

* @return {object} null if user already exists; Mongoose Model instance otherwise
*/
*/
var createTempUser = function(user, callback) {
if (!options.tempUserModel)
throw new TypeError("Temporary user model not defined. Either you forgot to generate one or you did not predefine one.");
if (!options.tempUserModel) {
throw new TypeError('Temporary user model not defined. Either you forgot to generate one or you did not predefine one.');
}
// create our mongoose query
var query = {};

@@ -150,10 +170,10 @@ query[options.emailFieldName] = user[options.emailFieldName];

options.tempUserModel.findOne(query, function(err, existingUser) {
if (err)
throw err;
if (err) {
return callback(err, null);
}
// user has already signed up...
if (existingUser)
callback(null);
else {
if (existingUser) {
return callback(null, null);
} else {
var tempUserData = {},

@@ -166,4 +186,12 @@ newTempUser;

});
tempUserData[options.URLFieldName] = randtoken.generate(options.URLLength);
callback(new options.tempUserModel(tempUserData));
newTempUser = new options.tempUserModel(tempUserData);
newTempUser.save(function(err, tempUser) {
if (err) {
return callback(err, null);
}
return callback(null, tempUser);
});
}

@@ -180,4 +208,4 @@ });

* @param {string} url - the unique url generated for the user.
*/
var sendVerificationEmail = function(email, url) {
*/
var sendVerificationEmail = function(email, url, callback) {
var r = /\$\{URL\}/g;

@@ -188,2 +216,3 @@

mailOptions = JSON.parse(JSON.stringify(options.verifyMailOptions));
mailOptions.to = email;

@@ -193,20 +222,59 @@ mailOptions.html = mailOptions.html.replace(r, URL);

transporter.sendMail(mailOptions, options.verifySendMailCallback);
if (!callback) {
callback = options.verifySendMailCallback;
}
transporter.sendMail(mailOptions, callback);
};
/**
* Send an email to the user requesting confirmation.
*
* @func sendVerificationEmail
* @param {string} email - the user's email address.
* @param {string} url - the unique url generated for the user.
*/
var sendConfirmationEmail = function(email, callback) {
var mailOptions = JSON.parse(JSON.stringify(options.confirmMailOptions));
mailOptions.to = email;
if (!callback) {
callback = options.confirmSendMailCallback;
}
transporter.sendMail(mailOptions, callback);
};
/**
* Save the user to the temporary collection, and send an email to the user
* requesting confirmation.
* requesting verification.
*
* @func registerTempUser
* @param {object} newTempUser - an instance of the temporary user model
*/
var registerTempUser = function(newTempUser) {
var r = /\$\{URL\}/g;
newTempUser.save(function(err) {
if (err)
throw err;
sendVerificationEmail(getNestedValue(newTempUser, options.emailFieldName),
newTempUser[options.URLFieldName]);
*/
var registerTempUser = function(newTempUser, cb) {
// var r = /\$\{URL\}/g;
async.waterfall([
function(callback) {
newTempUser.save(function(err, tempUser) {
if (err) {
return callback(err);
}
return callback();
});
},
function(callback) {
try {
sendVerificationEmail(getNestedValue(newTempUser, options.emailFieldName), newTempUser[options.URLFieldName]);
} catch (err) {
return callback(err);
}
return callback();
},
], function(err, result) {
if (err) {
return cb(err);
} else {
return cb();
}
});

@@ -222,3 +290,3 @@ };

* @param {string} url - the randomly generated URL assigned to a unique email
*/
*/
var confirmTempUser = function(url, callback) {

@@ -230,4 +298,5 @@ var TempUser = options.tempUserModel,

TempUser.findOne(query, function(err, tempUserData) {
if (err)
throw err;
if (err) {
return callback(err, null);
}

@@ -244,14 +313,14 @@ // temp user is found (i.e. user accessed URL before their data expired)

// save the temporary user to the persistent user collection
user.save(function(err) {
if (err)
throw err;
user.save(function(err, savedUser) {
if (err) {
return callback(err, null);
}
TempUser.remove(query, function(err) {
if (err)
throw err;
if (err) {
return callback(err, null);
}
if (options.sendConfirmationEmail) {
var mailOptions = JSON.parse(JSON.stringify(options.confirmMailOptions));
mailOptions.to = getNestedValue(userData, options.emailFieldName);
transporter.sendMail(mailOptions, options.confirmSendMailCallback);
if (options.shouldSendConfirmation) {
sendConfirmationEmail(savedUser.email, null);
}

@@ -261,7 +330,7 @@ });

callback(user);
return callback(null, user);
// temp user is not found (i.e. user accessed URL after data expired, or something else...)
// temp user is not found (i.e. user accessed URL after data expired, or something else...)
} else {
callback(null);
return callback(null, null);
}

@@ -277,3 +346,3 @@ });

* @param {object} email - the user's email address
*/
*/
var resendVerificationEmail = function(email, callback) {

@@ -284,11 +353,16 @@ var query = {};

options.tempUserModel.findOne(query, function(err, tempUser) {
if (err)
throw err;
if (err) {
return callback(err, null);
}
// user found (i.e. user re-requested verification email before expiration)
if (tempUser) {
sendVerificationEmail(getNestedValue(tempUser, options.emailFieldName), tempUser[options.URLFieldName]);
callback(true);
sendVerificationEmail(getNestedValue(tempUser, options.emailFieldName), tempUser[options.URLFieldName], function(err, info) {
if (err) {
return callback(err, null);
}
return callback(null, true);
});
} else {
callback(false);
return callback(null, false);
}

@@ -307,3 +381,4 @@ });

resendVerificationEmail: resendVerificationEmail,
sendConfirmationEmail: sendConfirmationEmail,
sendVerificationEmail: sendVerificationEmail,
};
};
{
"name": "email-verification",
"version": "0.1.9",
"version": "0.2.0",
"description": "Verify email sign-up using MongoDB.",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"format:examples": "js-beautify -r examples/**/*.js",
"format:main": "js-beautify -r index.js",
"format:test": "js-beautify -s 2 -r test/*.js",
"format": "npm run format:main && npm run format:examples && npm run format:test",
"lint:examples": "jshint --reporter=node_modules/jshint-stylish examples/**/*.js",
"lint:main": "jshint --reporter=node_modules/jshint-stylish index.js",
"lint:test": "jshint --reporter=node_modules/jshint-stylish test/*.js",
"lint": "npm run lint:main && npm run lint:examples && npm run lint:test",
"test": "mocha"
},
"repository": {
"type": "git",
"url": "https://github.com/StDako/node-email-verification"
"url": "https://github.com/SaintDako/node-email-verification"
},

@@ -19,11 +27,13 @@ "keywords": [

],
"author": "Dakota St. Laurent <hello@stdako.com> (http://stdako.com/)",
"author": "Dakota St. Laurent <hello@saintdako.com> (http://saintdako.com/)",
"license": "ISC",
"bugs": {
"url": "https://github.com/StDako/node-email-verification/issues"
"url": "https://github.com/SaintDako/node-email-verification/issues"
},
"homepage": "https://github.com/StDako/node-email-verification",
"homepage": "https://github.com/SaintDako/node-email-verification",
"dependencies": {
"async": "^1.4.2",
"mongoose": "^3.8.19",
"nodemailer": "^1.3.0",
"nodemailer-mandrill-transport": "^0.3.0",
"rand-token": "^0.2.1"

@@ -34,6 +44,10 @@ },

"body-parser": "^1.9.3",
"chai": "*",
"express": "^4.10.4",
"mocha" : "*",
"chai" : "*"
"js-beautify": "^1.5.10",
"jshint": "^2.8.0",
"jshint-stylish": "^2.0.1",
"mocha": "*",
"nodemailer-stub-transport": "^1.0.0"
}
}
# node email verification
[![NPM](https://nodei.co/npm/email-verification.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/email-verification/)
verify user signup with node and mongodb
Verify user signup with Node and MongoDB!
the way this works is as follows:
The way this works is as follows:
- temporary user is created with a randomly generated URL assigned to it and then saved to a mongoDB collection
- temporary user is created with a randomly generated URL assigned to it and then saved to a MongoDB collection
- email is sent to the email address the user signed up with
- when the URL is accessed, the user's data is transferred to the real collection
a temporary user document has a TTL of 24 hours by default, but this (as well as many other things) can be configured. see the options section for more details. it is also possible to resend the verification email if needed.
A temporary user document has a TTL of 24 hours by default, but this (as well as many other things) can be configured. See the options section for more details. It is also possible to resend the verification email if needed.
## installation
## Installation
via npm:

@@ -21,4 +21,4 @@

## examples
this little guide of sorts assumes you have a directory structure like so:
## Examples
This little guide of sorts assumes you have a directory structure like so:

@@ -33,3 +33,3 @@ ```

all of the code in this section takes place in server.js.
All of the code in this section takes place in server.js.

@@ -43,3 +43,3 @@ ```javascript

before doing anything, make sure to configure the options (see the section below for more extensive detail on this):
Before doing anything, make sure to configure the options (see the section below for more extensive detail on this):

@@ -68,5 +68,5 @@ ```javascript

any options not included in the object you pass will take on the default value specified in the section below. calling `configure` multiple times with new options will simply change the previously defined options.
Any options not included in the object you pass will take on the default value specified in the section below. Calling `configure` multiple times with new options will simply change the previously defined options.
to create a temporary user model, you can either generate it using a built-in function, or you can predefine it in a separate file. if you are pre-defining it, it must be IDENTICAL to the user model with an extra field for the URL; the default one is `GENERATED_VERIFYING_URL: String`. **you're just better off generating a model**.
To create a temporary user model, you can either generate it using a built-in function, or you can predefine it in a separate file. If you are pre-defining it, it must be IDENTICAL to the user model with an extra field for the URL; the default one is `GENERATED_VERIFYING_URL: String`. **You're just better off generating a model**.

@@ -86,3 +86,3 @@ ```javascript

then, create an instance of the User model, and then pass it as well as a custom callback to `createTempUser`, one that makes use of the function `registerTempUser` and, if you want, handles the case where the temporary user is already in the collection:
Then, create an instance of the User model, and then pass it as well as a custom callback to `createTempUser`, one that makes use of the function `registerTempUser` and, if you want, handles the case where the temporary user is already in the collection:

@@ -112,5 +112,5 @@ ```javascript

an email will be sent to the email address that the user signed up with. note that this does not handle hashing passwords - that must be done on your own terms. to see how to do this, check the Express example.
An email will be sent to the email address that the user signed up with. Note that this does not handle hashing passwords - that must be done on your own terms. To see how to do this, check the Express example.
to move a user from the temporary storage to 'persistent' storage (e.g. when they actually access the URL we sent them), we call `confirmTempUser`, which takes the URL as well as a callback with one argument (the instance of the User model, or null) as arguments. if the callback's argument is null, it is most likely because their data expired.
To move a user from the temporary storage to 'persistent' storage (e.g. when they actually access the URL we sent them), we call `confirmTempUser`, which takes the URL as well as a callback with one argument (the instance of the User model, or null) as arguments. If the callback's argument is null, it is most likely because their data expired.

@@ -127,3 +127,3 @@ ```javascript

if you want the user to be able to request another verification email, simply call `resendVerificationEmail`, which takes the user's email address and a callback with one argument (again, whether or not the user was found) as arguments:
If you want the user to be able to request another verification email, simply call `resendVerificationEmail`, which takes the user's email address and a callback with one argument (again, whether or not the user was found) as arguments:

@@ -140,10 +140,10 @@ ```javascript

to see a fully functioning example that uses Express as the backend, check out the [**examples section**](https://github.com/StDako/node-email-verification/tree/master/examples/express).
To see a fully functioning example that uses Express as the backend, check out the [**examples section**](https://github.com/StDako/node-email-verification/tree/master/examples/express).
## API
#### `configure(options)`
changes the default configuration by passing an object of options; see the section below for a list of all options.
Changes the default configuration by passing an object of options; see the section below for a list of all options.
#### `generateTempUserModel(UserModel)`
generates a Mongoose Model for the temporary user based off of `UserModel`, the persistent user model. the temporary model is essentially a duplicate of the persistent model except that it has the field `{GENERATED_VERIFYING_URL: String}` for the randomly generated URL by default (the field name can be changed in the options). if the persistent model has the field `createdAt`, then an expiration time (`expires`) is added to it with a default value of 24 hours; otherwise, the field is created as such:
Generates a Mongoose Model for the temporary user based off of `UserModel`, the persistent user model. The temporary model is essentially a duplicate of the persistent model except that it has the field `{GENERATED_VERIFYING_URL: String}` for the randomly generated URL by default (the field name can be changed in the options). If the persistent model has the field `createdAt`, then an expiration time (`expires`) is added to it with a default value of 24 hours; otherwise, the field is created as such:

@@ -162,21 +162,22 @@ ```

note that `createdAt` will not be transferred to persistent storage (yet?).
Note that `createdAt` will not be transferred to persistent storage (yet?).
#### `createTempUser(user, callback(tempuser))`
attempts to create an instance of a temporary user model based off of an instance of a persistent user, `user`. `tempuser` is the temporary user instance if the user doesn't exist in the temporary collection, or `null` otherwise. it is most convenient to call `registerTempUser` in the "success" case (i.e. not `null`) of the callback.
#### `createTempUser(user, callback(err, tempuser))`
Attempts to create an instance of a temporary user model based off of an instance of a persistent user, `user`. `tempuser` is the temporary user instance if the user doesn't exist in the temporary collection, or `null` otherwise. If there are no errors, `err` is `null`. It is most convenient to call `registerTempUser` in the "success" case (i.e. not `null`) of the callback.
if a temporary user model hasn't yet been defined (generated or otherwise), a TypeError will be thrown.
If a temporary user model hasn't yet been defined (generated or otherwise), a TypeError will be thrown.
#### `registerTempUser(tempuser)`
saves the instance of the temporary user model, `tempuser`, to the temporary collection, and then sends an email to the user requesting verification.
#### `registerTempUser(tempuser, callback(err))`
Saves the instance of the temporary user model, `tempuser`, to the temporary collection, and then sends an email to the user requesting verification. If there are no errors, `err` is `null`.
#### `confirmTempUser(url, callback(user))`
transfers a temporary user (found by `url`) from the temporary collection to the persistent collection and remove the URL assigned to the user. `userTransferred` is the persistent user instance if the user has been successfully transferred (i.e. the user accessed URL before expiration) and `null` otherwise; this can be used for redirection and what not.
#### `confirmTempUser(url, callback(err, userTransferred))`
Transfers a temporary user (found by `url`) from the temporary collection to the persistent collection and removes the URL assigned with the user. `userTransferred` is the persistent user instance if the user has been successfully transferred (i.e. the user accessed URL before expiration) and `null` otherwise; this can be used for redirection and what not. If there are no errors, `err` is `null`.
#### `resendVerificationEmail(email, callback(userFound))`
resends the verification email to a user, given their email. `userFound` is `true` if the user has been found in the temporary collection (i.e. their data hasn't expired yet) and `false` otherwise.
#### `resendVerificationEmail(email, callback(err, userFound))`
Resends the verification email to a user, given their email. `userFound` is `true` if the user has been found in the temporary collection (i.e. their data hasn't expired yet) and `false` otherwise. If there are no errors, `err` is `null`.
### options
here are the default options:
### Options
Here are the default options:
```javascript

@@ -243,3 +244,28 @@ var options = {

### todo
### Developer-Related Stuff
To beautify the code:
```
npm run format:main
npm run format:examples
npm run format:test
npm run format # runs all
```
To lint the code (will error if there are any warnings):
```
npm run lint:main
npm run lint:examples
npm run lint:test
npm run lint # runs all
```
To test:
```
npm test
```
### TODO
- **development**: add a task runner WE NEED TESTS

@@ -249,3 +275,3 @@ - **development**: throw more errors

### acknowledgements
### Acknowledgements
thanks to [Frank Cash](https://github.com/frankcash) for looking over my code.

@@ -252,0 +278,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc