Skip to content

Commit

Permalink
Merge pull request #41 from two-factor/index
Browse files Browse the repository at this point in the history
fixed config object formatting in index.js
  • Loading branch information
Dnaganog committed Jul 9, 2019
2 parents b672cc0 + 95ce70c commit c50b761
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 8 deletions.
28 changes: 25 additions & 3 deletions ReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,37 @@ In your application's backend, likely in an Express middleware controller (or wh
const twoAuth = require('two-auth');
const client = twoAuth(*ACC_SID*, *AUTH_TOKEN*);

> Optionally: you may pass a third parameter Mongo database connection URI so that your Twilio SID, your application's Twilio registered user IDs, their phone numbers are persistent inside your Mongo database. Initialize like so: `twoAuth(*ACC_SID*, *AUTH_TOKEN*, *MONGO_DB_URI*)`. `twoAuth` stores your SID, registered user IDs and phone numbers inside a collection on your passed in Mongo database under the name `two auth users`
> Optionally: you may pass a third parameter `options` object with the following syntax:
The function will return an instance of a Two-Auth `client`. That `client` will have the `create`, `send`, and `verify` methods.
const twoAuth = require('two-auth');
const options = {
appName: "*YOUR_APP_NAME*",
isPostgres: boolean,
connectionURI: "*MONGO_URI or POSTGRES_URI*",
}
const client = twoAuth(*ACC_SID*, *AUTH_TOKEN*, options);

> Based on your options object, your users will be sent sms with your `appName`. We currently support Mongo and Postgres databases.
>
> If `isPostgres` is set to `false` we store your SID, registered user IDs and phone numbers inside a collection on your passed in Mongo database under the name `two auth users`.
>
> If `isPostgres` is set to `true` we store your SID, registered user
> IDs and phone numbers inside a table on your passed in Postgres
> database under the name `twoauthusers`.
The initialization function will return an instance of a Two-Auth `client`. That `client` will have the `create`, `send`, and `verify` methods.

## Two-Auth Methods

> Note: each of these methods are fully asynchronous and should occur at different points in your express middleware controller pattern. The methods each return a promise.
### `create()`

Provide two-auth with a user ID and a phone number associated with that user.

client.create(*USER_ID*, *PHONE_NUMBER*);

> Warning: Two-Auth currently only supports US phone numbers.
> Warning: Two-Auth currently only supports US phone numbers. They must be formatted as a string to match +1XXXXXXXXXX
`create` registers a new verification service with Twilio, which will allow your application to later send and verify codes to and from that phone number and user.

Expand All @@ -54,3 +72,7 @@ Once your user inputs their six digit code, pass it into the verification method
> Make sure that the *code* you pass is a `string`! NOT a `number`.
`verify` will properly identify and `return` `true` if the code is valid, `false` if the code is invalid.

#### Authors

Sierra Swaby, Ryan Dang, Giuseppe Valentino, Ian Geckeler, & Daniel Nagano-Gerace
3 changes: 1 addition & 2 deletions functions/databases/mongoose/verify.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ function verify(userID, code) {
)
);

return this.client.verify
.services(sid)
return this.client.verify.services(sid)
.verificationChecks.create({
to: phone,
code
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "two-auth",
"version": "2.0.0",
"version": "2.0.1",
"description": "Implement two-factor SMS authentication with the Twilio API in three lines of code.",
"main": "index.js",
"scripts": {
Expand Down Expand Up @@ -39,4 +39,4 @@
"dotenv": "^8.0.0",
"jest": "^24.8.0"
}
}
}
14 changes: 14 additions & 0 deletions tests/create.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const client = require("../index")(process.env.SID, process.env.AUTH, {
isPostgres: true,
appName:'DATABASE two-factor',
connectionURI: "postgres://zepvalue:linux@localhost/twoauthtests"
});

//client.create("ian", "+17604207520");
//client.send("ian")
client.verify("ian", '851701')
// console.log("client is", Client);

// Client.create("ian", "17604207520")
// .then(user => console.log(user))
// .catch(err => console.log(err));
113 changes: 113 additions & 0 deletions tests/tests-list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// Here we will be unit testing the 3 main database functions from server/db/markets.js
const fs = require('fs');
const path = require('path');
const db = require('../server/db/markets.js');

const testJsonFile = path.resolve(__dirname, '../server/db/markets.test.json');

/**
* Like many testing frameworks, in Jest we use the "describe" function to
* separate our tests into sections. They make your test outputs readable.
*
* You can place "beforeAll", "beforeEach", "afterAll", and "afterEach"
* functions inside of "describe" blocks and they will only run for tests
* inside that describe block. You can even nest describes within describes!
*/
describe('db unit tests', () => {
/**
* Jest runs the "beforeAll" function once, before any tests are executed.
* Here, we write to the file and then reset our database model. Then, we
* invoke the "done" callback to tell Jest our async operations have
* completed. This way, the tests won't start until the "database" has been
* reset to an empty Array!
*/
beforeAll((done) => {
fs.writeFile(testJsonFile, JSON.stringify([]), () => {
db.reset();
done();
});
});

afterAll((done) => {
fs.writeFile(testJsonFile, JSON.stringify([]), done);
});

describe('#sync', () => {
it('writes a valid marketList to the JSON file', () => {
const marketList = [{ location: 'here', cards: 11 }, { location: 'there', cards: 0 }];
const result = db.sync(marketList);
expect(result).not.toBeInstanceOf(Error);
const table = JSON.parse(fs.readFileSync(testJsonFile));
expect(table).toEqual(marketList);
});

// TODO: Finish unit testing the sync function

it('overwrites previously existing markets', () => {
// if we pass an empty array than we expect length 0
const result = db.sync([
{ location: 'Australia',
cards: 32
}
]);

expect(result.length).toBe(1);
});

it('returns an error when location and/or cards fields are not provided', () => {

const result = db.sync([
{ location: 'Australia',
cards: 32
}
]);
// // expect(result[0].location).toBeDefined()
expect(result[0].location).toBeDefined()
expect(result[0].cards).toBeDefined()
});

/**
* TODO: Type validation is not yet correctly implemented! Follow the TDD
* (test driven development) approach:
* 1. Write a tes[t describing the desired feature (db.sync returns a
* TypeError when the types are wrong)
* 2. Confirm that your tests fail
* 3. Follow the errors to implement your new functionality
*/
it('returns an error when location value is not a string', () => {

const result = db.sync([
{ location: 'Australia',
cards: 32
}
]);

expect(typeof result[0].location).toBe('string')
});

it('returns an error when cards value is not a number', () => {

const result = db.sync([
{ location: 'Australia',
cards: 32
}
]);

expect(typeof result[0].cards).toBe('number')
});
});

// Extension TODO: Unit test the #find and #drop functions
describe('#find', () => {
xit('returns list of all markets from the json file', () => {
});

xit('works if the list of markets is empty', () => {
});
});

describe('#drop', () => {
xit('writes an empty array to the json file', () => {
});
});
});

0 comments on commit c50b761

Please sign in to comment.