Skip to content

Commit

Permalink
Functioning API part that sends and verify the token.
Browse files Browse the repository at this point in the history
  • Loading branch information
bharaninb authored and vipulrawat committed Oct 15, 2018
1 parent b702d34 commit 7db9817
Show file tree
Hide file tree
Showing 60 changed files with 11,439 additions and 2 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#Build
build
dist

# Logs
logs
*.log
Expand Down
5 changes: 5 additions & 0 deletions .huskyrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"hooks": {
"pre-commit": "lint-staged"
}
}
7 changes: 7 additions & 0 deletions .lintstagedrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"linters": {
"*.js": [
"eslint"
]
}
}
28 changes: 28 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
language: node_js
node_js:
- '9'
services:
- mongodb
matrix:
include:
- name: Delta Students
env: PACKAGE_LOCATION=packages/students PACKAGE_NAME=deltapesto
- name: Delta API
env: PACKAGE_LOCATION=packages/api PACKAGE_NAME=deltapesto-api
- name: Delta Instructors
env: PACKAGE_LOCATION=packages/instructors PACKAGE_NAME=deltapesto-instructors

script:
- cd $PACKAGE_LOCATION
- yarn test

before_deploy:
- yarn run build

deploy:
provider: heroku
api_key:
secure: MPFBXdZ7jtWuPn6sJHHwMSh7cJBjqxzRJ4PB8TzQV6CAnf0Nk7XpYv56BfWbJYmiSaJw76XK7vZYVNYUsombhu1xQYhCl8W7VKFrctiRZxU+qlUCRBq5KixY3FYaoV62L5Z8RnDAl5K7tga/DBPWndmY8XkMkblmBfEeJs9jx3ORFBh4bOrWlzfTLbDNKRDyKN8hrJTzWWWfGDSb/HxzVQL4dTVFwbvJ2rdCGBiaLLTfcp8oyxf4CSaGZll66ja9vJYhPvhnXYbuMrUBgRBaKsAxKUPYG71u+qoCsYpGaXhXhutI0dlw6aNIZk+gesaOfiXRM3Vk7ydXeVJ3Ps7ngn0R7KkKKXoI1ZNIEU1A6OosdntQ4HtLsRrcp4dy7+A7zxqcuhRfDfrFtF67Gfjek3ugP4tXwO60hf3jsqzz5fCH3CCSXpMdbNDiuQlx9xu5jdmfTl7iuk7oMEh1U0ACjSSt5djnt7mFr0ixziO/+AQkpRxFXrwYm08erPgeAybbpaDH86WeuaWQqdCT18Q0EyRGN+5kQGx3kmW45gSDWD5YIzTaMKpwdinqWsbzMu31rIYqhjzxugEuhwcxLDbaq/9Nsz9yRWUzuruWde5gYs1wLQSO8w0ud/xWwdM9/xpAZHd1e0l73RJJQXETb1JVq6ptLV6Hwyv/JzEMbJWwOLI=
skip_cleanup: true
app:
master: "$PACKAGE_NAME"
40 changes: 38 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,38 @@
# project-delta
Tracking Growth
# Project Delta
Project Delta is an attempt to provide Pesto’s instructors visibility into how effectively the student body is learning the curriculum.

- [Students Portal](https://deltapesto.herokuapp.com/)
- [Instructors Portal](https://deltapesto-instructors.herokuapp.com/)
- [Api Portal](https://deltapesto-api.herokuapp.com/)

## Description
Project Delta enables tracking:
1. How confident students are that they have mastered topics covered in the lectures
2. Student's performance in exercises

… and presenting instructors with visualizations that will allow easy identification of:
1. Struggling students
2. Insufficiently-explained topics
3. Unreasonably difficult exercises

For more details, refer [Delta - Project Spec](__specs__/Delta-ProjectSpec.pdf)

## Getting started

```shell
yarn install
```

To start app, follow below links
- [Students App](packages/students)
- [Instructors App](packages/instructors)
- [Api](packages/api)

## Contributors
[![Bharani](https://github.com/bharaninb.png?size=100)](https://github.com/bharaninb) | [![Anirudh](https://github.com/ackinc.png?size=100)](https://github.com/ackinc) | [![Vipul](https://github.com/vipulrawat.png?size=100)](https://github.com/monisahmad)
---|---|---
[Bharani](https://github.com/bharaninb) | [Anirudh](https://github.com/ackinc) | [Vipul](https://github.com/vipulrawat)

## LICENSE

MIT
Binary file added __specs__/Delta-ProjectSpec.pdf
Binary file not shown.
21 changes: 21 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "monorepo",
"version": "1.0.0",
"description": "Project Delta",
"main": "index.js",
"private": true,
"scripts": {
"test": "yarn wsrun test"
},
"workspaces": [
"packages/*"
],
"devDependencies": {
"babel-eslint": "^10.0.1",
"eslint": "^5.6.1",
"eslint-config-airbnb": "^17.1.0",
"husky": "^1.1.1",
"lint-staged": "^7.3.0",
"wsrun": "^2.2.1"
}
}
11 changes: 11 additions & 0 deletions packages/api/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"parser": "babel-eslint",
"extends": "airbnb",
"rules": {
"import/prefer-default-export": 0
},
"env": {
"jest": true,
"node": true
}
}
1 change: 1 addition & 0 deletions packages/api/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sendgrid.env
17 changes: 17 additions & 0 deletions packages/api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# API Portal
Backend sub-repository for api.

[https://deltapesto-api.herokuapp.com/](https://deltapesto-api.herokuapp.com/)

## Getting started

To start dev app
```shell
yarn start:dev
```

## Test

```shell
yarn test
```
186 changes: 186 additions & 0 deletions packages/api/__tests__/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
import mongoose from 'mongoose';
import request from 'request-promise-native';

import app from '../src';
import { PORT, DB_URL } from '../config';
import tokenService from '../src/services/token';
import { User } from '../src/db';

let savedUsers;
const dummyUsers = [
{
firstName: 'Anirudh',
lastName: 'Nimmagadd',
email: '[email protected]',
role: 'student',
batchId: mongoose.Types.ObjectId('111111111111111111111111'),
},
{
firstName: 'Bharani',
lastName: 'Dharani',
email: '[email protected]',
role: 'student',
batchId: mongoose.Types.ObjectId('111111111111111111111112'),
},
{
firstName: 'Vipul',
lastName: 'Rawat',
email: '[email protected]',
role: 'student',
batchId: mongoose.Types.ObjectId('111111111111111111111113'),
},
];

let server;
const serverUrl = `http://localhost:${PORT}`;

beforeAll((done) => {
mongoose.connect(DB_URL, { useNewUrlParser: true }, () => {
server = app.listen(PORT, () => {
// save current contents of users collection, and insert some dummy users
User.find({})
.then((users) => {
savedUsers = users;
return Promise.resolve(true);
})
.then(() => User.deleteMany({}))
.then(() => User.insertMany(dummyUsers))
// do not pass 'done' directly to 'then'
// it will get an argument, and that will cause tests to fail!
.then(() => done());
});
});
});

afterAll((done) => {
// restore previous content of users collection
User.deleteMany({})
.then(() => User.insertMany(savedUsers))
.then(() => mongoose.connection.close())
.then(() => server.close(done));
});

describe('/generateToken', () => {
const url = `${serverUrl}/generateToken`;

it('should send a 400 response when request contains no email', (done) => {
request({
url,
method: 'POST',
}).catch((e) => {
expect(e.statusCode).toBe(400);
done();
});
});

it('should send a 400 response when request contains an invalid email', (done) => {
request({
url,
method: 'POST',
body: { email: 'abc' },
json: true,
}).catch((e) => {
expect(e.statusCode).toBe(400);
done();
});
});

it('should send a 200 response when request contains a valid email', (done) => {
request({
url,
method: 'POST',
body: { email: '[email protected]' },
json: true,
resolveWithFullResponse: true,
}).then((res) => {
expect(res.statusCode).toBe(200);
done();
});
});
});

describe('/verifyToken', () => {
const url = `${serverUrl}/verifyToken`;

it('should send a 400 response when request contains no token', (done) => {
request({
url,
method: 'POST',
}).catch((e) => {
expect(e.statusCode).toBe(400);
done();
});
});

it('should send a 400 response when request contains invalid token', (done) => {
request({
url,
method: 'POST',
body: { token: 'abc' },
json: true,
}).catch((e) => {
expect(e.statusCode).toBe(400);
done();
});
});

it('should send a 200 response with set-cookie header and isNewUser false when token has valid email that is already in DB', (done) => {
tokenService.generate({
email: '[email protected]',
tokenType: 'EMAIL_VERIFICATION',
})
.then((token) => {
request({
url,
method: 'POST',
body: { token },
json: true,
resolveWithFullResponse: true,
}).then((res) => {
expect(res.statusCode).toBe(200);
expect(/^token=/.test(res.headers['set-cookie'])).toBe(true);
expect(res.body.isNewUser).toBe(false);
done();
});
});
});

it('should send a 200 response with set-cookie header and isNewUser true when token has valid email that is not already in DB', (done) => {
tokenService.generate({
email: '[email protected]',
tokenType: 'EMAIL_VERIFICATION',
})
.then((token) => {
request({
url,
method: 'POST',
body: { token },
json: true,
resolveWithFullResponse: true,
}).then((res) => {
expect(res.statusCode).toBe(200);
expect(/^token=/.test(res.headers['set-cookie'])).toBe(true);
expect(res.body.isNewUser).toBe(true);
done();
});
});
});

it('should not try to set another cookie when provided a LOGIN token', (done) => {
tokenService.generate({ email: '[email protected]', tokenType: 'LOGIN' })
.then((token) => {
request({
url,
method: 'POST',
body: { token },
json: true,
resolveWithFullResponse: true,
}).then((res) => {
expect(res.statusCode).toBe(200);
expect(Reflect.has(res.headers, 'set-cookie')).toBe(false);
expect(res.body.isNewUser).toBe(false);
done();
});
});
});
});
13 changes: 13 additions & 0 deletions packages/api/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module.exports = {
presets: [
[
'@babel/preset-env',
{
targets: {
node: '9',
},
},
],
],
ignore: ['node_modules', 'build'],
};
7 changes: 7 additions & 0 deletions packages/api/config/ci.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
PORT: 5000,
DB_URL: 'mongodb://localhost:27017/test-delta',
EMAIL_VERIFICATION_TOKEN_EXPIRY: 15 * 60, // 15 minutes
LOGIN_TOKEN_EXPIRY: '28d',
LOGIN_COOKIE_EXPIRY: 4 * 7 * 24 * 60 * 60 * 1000, // 4 weeks
};
7 changes: 7 additions & 0 deletions packages/api/config/dev.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
PORT: 5000,
DB_URL: 'mongodb://localhost:27017/test-delta',
EMAIL_VERIFICATION_TOKEN_EXPIRY: 15 * 60, // 15 minutes
LOGIN_TOKEN_EXPIRY: '28d',
LOGIN_COOKIE_EXPIRY: 4 * 7 * 24 * 60 * 60 * 1000, // 4 weeks
};
5 changes: 5 additions & 0 deletions packages/api/config/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// The env var 'MODE' should be in ['PROD', 'DEV', 'CI']
const mode = process.env.MODE || 'DEV';

// eslint-disable-next-line import/no-dynamic-require
module.exports = require(`./${mode.toLowerCase()}`);
7 changes: 7 additions & 0 deletions packages/api/config/prod.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
PORT: 5000,
DB_URL: 'mongodb://localhost:27017/test-delta',
EMAIL_VERIFICATION_TOKEN_EXPIRY: 15 * 60, // 15 minutes
LOGIN_TOKEN_EXPIRY: '28d',
LOGIN_COOKIE_EXPIRY: 4 * 7 * 24 * 60 * 60 * 1000, // 4 weeks
};
9 changes: 9 additions & 0 deletions packages/api/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module.exports = {
verbose: true,
collectCoverageFrom: [
'src/**/*',
],
transform: {
'.js$': 'babel-jest',
},
};
Loading

0 comments on commit 7db9817

Please sign in to comment.