| @@ -1,5 +1,5 @@ | |||||
| { | { | ||||
| "name": "job-portal", | |||||
| "name": "anamnesis", | |||||
| "version": "1.0.0", | "version": "1.0.0", | ||||
| "lockfileVersion": 1, | "lockfileVersion": 1, | ||||
| "requires": true, | "requires": true, | ||||
| @@ -30,6 +30,19 @@ | |||||
| "js-tokens": "^4.0.0" | "js-tokens": "^4.0.0" | ||||
| } | } | ||||
| }, | }, | ||||
| "@cspotcode/source-map-consumer": { | |||||
| "version": "0.8.0", | |||||
| "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", | |||||
| "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==" | |||||
| }, | |||||
| "@cspotcode/source-map-support": { | |||||
| "version": "0.7.0", | |||||
| "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", | |||||
| "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", | |||||
| "requires": { | |||||
| "@cspotcode/source-map-consumer": "0.8.0" | |||||
| } | |||||
| }, | |||||
| "@mapbox/node-pre-gyp": { | "@mapbox/node-pre-gyp": { | ||||
| "version": "1.0.5", | "version": "1.0.5", | ||||
| "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.5.tgz", | "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.5.tgz", | ||||
| @@ -103,6 +116,26 @@ | |||||
| "defer-to-connect": "^1.0.1" | "defer-to-connect": "^1.0.1" | ||||
| } | } | ||||
| }, | }, | ||||
| "@tsconfig/node10": { | |||||
| "version": "1.0.8", | |||||
| "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", | |||||
| "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==" | |||||
| }, | |||||
| "@tsconfig/node12": { | |||||
| "version": "1.0.9", | |||||
| "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", | |||||
| "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==" | |||||
| }, | |||||
| "@tsconfig/node14": { | |||||
| "version": "1.0.1", | |||||
| "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", | |||||
| "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==" | |||||
| }, | |||||
| "@tsconfig/node16": { | |||||
| "version": "1.0.2", | |||||
| "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", | |||||
| "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==" | |||||
| }, | |||||
| "@types/bcrypt": { | "@types/bcrypt": { | ||||
| "version": "5.0.0", | "version": "5.0.0", | ||||
| "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.0.tgz", | "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.0.tgz", | ||||
| @@ -266,6 +299,16 @@ | |||||
| "negotiator": "0.6.2" | "negotiator": "0.6.2" | ||||
| } | } | ||||
| }, | }, | ||||
| "acorn": { | |||||
| "version": "8.5.0", | |||||
| "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.5.0.tgz", | |||||
| "integrity": "sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==" | |||||
| }, | |||||
| "acorn-walk": { | |||||
| "version": "8.2.0", | |||||
| "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", | |||||
| "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" | |||||
| }, | |||||
| "agent-base": { | "agent-base": { | ||||
| "version": "6.0.2", | "version": "6.0.2", | ||||
| "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", | ||||
| @@ -346,6 +389,11 @@ | |||||
| "readable-stream": "^2.0.6" | "readable-stream": "^2.0.6" | ||||
| } | } | ||||
| }, | }, | ||||
| "arg": { | |||||
| "version": "4.1.3", | |||||
| "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", | |||||
| "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" | |||||
| }, | |||||
| "argparse": { | "argparse": { | ||||
| "version": "1.0.10", | "version": "1.0.10", | ||||
| "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", | ||||
| @@ -688,6 +736,11 @@ | |||||
| "vary": "^1" | "vary": "^1" | ||||
| } | } | ||||
| }, | }, | ||||
| "create-require": { | |||||
| "version": "1.1.1", | |||||
| "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", | |||||
| "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" | |||||
| }, | |||||
| "crypto-random-string": { | "crypto-random-string": { | ||||
| "version": "2.0.0", | "version": "2.0.0", | ||||
| "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", | "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", | ||||
| @@ -752,8 +805,7 @@ | |||||
| "diff": { | "diff": { | ||||
| "version": "4.0.2", | "version": "4.0.2", | ||||
| "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", | ||||
| "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", | |||||
| "dev": true | |||||
| "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" | |||||
| }, | }, | ||||
| "dot-prop": { | "dot-prop": { | ||||
| "version": "5.3.0", | "version": "5.3.0", | ||||
| @@ -1380,6 +1432,11 @@ | |||||
| } | } | ||||
| } | } | ||||
| }, | }, | ||||
| "make-error": { | |||||
| "version": "1.3.6", | |||||
| "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", | |||||
| "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" | |||||
| }, | |||||
| "media-typer": { | "media-typer": { | ||||
| "version": "0.3.0", | "version": "0.3.0", | ||||
| "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", | ||||
| @@ -2068,6 +2125,25 @@ | |||||
| "punycode": "^2.1.1" | "punycode": "^2.1.1" | ||||
| } | } | ||||
| }, | }, | ||||
| "ts-node": { | |||||
| "version": "10.3.0", | |||||
| "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.3.0.tgz", | |||||
| "integrity": "sha512-RYIy3i8IgpFH45AX4fQHExrT8BxDeKTdC83QFJkNzkvt8uFB6QJ8XMyhynYiKMLxt9a7yuXaDBZNOYS3XjDcYw==", | |||||
| "requires": { | |||||
| "@cspotcode/source-map-support": "0.7.0", | |||||
| "@tsconfig/node10": "^1.0.7", | |||||
| "@tsconfig/node12": "^1.0.7", | |||||
| "@tsconfig/node14": "^1.0.0", | |||||
| "@tsconfig/node16": "^1.0.2", | |||||
| "acorn": "^8.4.1", | |||||
| "acorn-walk": "^8.1.1", | |||||
| "arg": "^4.1.0", | |||||
| "create-require": "^1.1.0", | |||||
| "diff": "^4.0.1", | |||||
| "make-error": "^1.1.1", | |||||
| "yn": "3.1.1" | |||||
| } | |||||
| }, | |||||
| "tslib": { | "tslib": { | ||||
| "version": "1.14.1", | "version": "1.14.1", | ||||
| "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", | ||||
| @@ -2325,6 +2401,11 @@ | |||||
| "version": "4.0.0", | "version": "4.0.0", | ||||
| "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", | ||||
| "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" | ||||
| }, | |||||
| "yn": { | |||||
| "version": "3.1.1", | |||||
| "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", | |||||
| "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==" | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -20,6 +20,7 @@ | |||||
| "nodemon": "^2.0.12", | "nodemon": "^2.0.12", | ||||
| "passport": "^0.5.0", | "passport": "^0.5.0", | ||||
| "passport-jwt": "^4.0.0", | "passport-jwt": "^4.0.0", | ||||
| "ts-node": "^10.3.0", | |||||
| "uuid": "^8.3.2" | "uuid": "^8.3.2" | ||||
| }, | }, | ||||
| "devDependencies": { | "devDependencies": { | ||||
| @@ -3,27 +3,14 @@ import { DB_NAME, getDatabaseClient } from '../db-utils'; | |||||
| import bcrypt from 'bcrypt'; | import bcrypt from 'bcrypt'; | ||||
| import { generateJWT, SALT_ROUNDS } from './auth'; | import { generateJWT, SALT_ROUNDS } from './auth'; | ||||
| import sendGridMail, { MailDataRequired } from '@sendgrid/mail'; | import sendGridMail, { MailDataRequired } from '@sendgrid/mail'; | ||||
| import { Category } from '../models/category'; | |||||
| import { Shelf } from '..//models/shelf'; | |||||
| import { v4 as uuidv4 } from 'uuid'; | |||||
| const authRoutes = express.Router(); | const authRoutes = express.Router(); | ||||
| authRoutes.post('/register-applicant/', async (request, response) => { | |||||
| authRoutes.post('/register/', async (request, response) => { | |||||
| const name: string = request.body.name; | const name: string = request.body.name; | ||||
| const email: string = request.body.email; | const email: string = request.body.email; | ||||
| const password: string = request.body.password; | const password: string = request.body.password; | ||||
| const isVerified: boolean = false; | const isVerified: boolean = false; | ||||
| const categories: Array<Category> = []; | |||||
| const uncategorised: Shelf = { | |||||
| _id: uuidv4(), | |||||
| name: 'Uncategorised', | |||||
| description: '', | |||||
| viewType: 'PRIVATE', | |||||
| isArchived: false, | |||||
| addedWords: [] | |||||
| } | |||||
| const userCollection = getDatabaseClient().db(DB_NAME).collection('users'); | const userCollection = getDatabaseClient().db(DB_NAME).collection('users'); | ||||
| // Check if form is filled | // Check if form is filled | ||||
| @@ -59,8 +46,6 @@ authRoutes.post('/register-applicant/', async (request, response) => { | |||||
| email, | email, | ||||
| password: hashedPassword, | password: hashedPassword, | ||||
| isVerified, | isVerified, | ||||
| categories, | |||||
| uncategorised | |||||
| }); | }); | ||||
| }); | }); | ||||
| @@ -180,9 +165,8 @@ authRoutes.post('/verify-user/', async (request, response) => { | |||||
| authRoutes.post('/api-auth/', async (request, response) => { | authRoutes.post('/api-auth/', async (request, response) => { | ||||
| const email: string = request.body.email; | const email: string = request.body.email; | ||||
| const password: string = request.body.password; | const password: string = request.body.password; | ||||
| const userType: string = request.body.userType; | |||||
| if (!email || !password || !userType) { | |||||
| if (!email || !password) { | |||||
| response.status(400); | response.status(400); | ||||
| response.send("Please field the required fields"); | response.send("Please field the required fields"); | ||||
| return; | return; | ||||
| @@ -192,7 +176,6 @@ authRoutes.post('/api-auth/', async (request, response) => { | |||||
| let users = await userCollection.find({ | let users = await userCollection.find({ | ||||
| email, | email, | ||||
| userType, | |||||
| }).toArray(); | }).toArray(); | ||||
| const matchedUser = users[0]; | const matchedUser = users[0]; | ||||
| @@ -5,6 +5,7 @@ import authRoutes from './authentication/routes'; | |||||
| import { connectToDatabaseServer } from './db-utils'; | import { connectToDatabaseServer } from './db-utils'; | ||||
| import sendGridMail from '@sendgrid/mail'; | import sendGridMail from '@sendgrid/mail'; | ||||
| import { userProfileRoutes } from './user-profile/routes'; | import { userProfileRoutes } from './user-profile/routes'; | ||||
| import { revisionRoutes } from './revision/routes'; | |||||
| const SENDGRID_API_KEY = process.env.SENDGRID_API_KEY || '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'; | const SENDGRID_API_KEY = process.env.SENDGRID_API_KEY || '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'; | ||||
| @@ -17,6 +18,7 @@ app.use(passport.initialize()); | |||||
| app.set('port', process.env.PORT || 8001); | app.set('port', process.env.PORT || 8001); | ||||
| app.use('/', authRoutes); | app.use('/', authRoutes); | ||||
| app.use('/', userProfileRoutes); | app.use('/', userProfileRoutes); | ||||
| app.use('/', revisionRoutes); | |||||
| app.get('/', (request, response) => { | app.get('/', (request, response) => { | ||||
| response.send('Server running @ port' + app.get('port')); | response.send('Server running @ port' + app.get('port')); | ||||
| @@ -6,4 +6,8 @@ export interface Category { | |||||
| icon: string, | icon: string, | ||||
| shelves: Array<Shelf>, | shelves: Array<Shelf>, | ||||
| isArchived: boolean, | isArchived: boolean, | ||||
| } | |||||
| export interface MongoCategory extends Omit<Category, 'shelves'> { | |||||
| shelves: Array<string>, // Ids | |||||
| } | } | ||||
| @@ -12,6 +12,26 @@ export interface Shelf { | |||||
| notes: Array<string>, | notes: Array<string>, | ||||
| isFavourite: boolean, | isFavourite: boolean, | ||||
| nextRevisionDateTime: Date, | nextRevisionDateTime: Date, | ||||
| spaceBetweenRecall: number, // in Days | |||||
| revisionHistory : Array<{ | |||||
| day: Date, | |||||
| wasRecallSuccessful: boolean, | |||||
| }> | |||||
| }> | |||||
| } | |||||
| export interface MongoShelf { | |||||
| _id: string, | |||||
| name: string, | |||||
| description: string, | |||||
| viewType: viewPermissionType, | |||||
| isArchived: boolean, | |||||
| addedWords: Array<{ | |||||
| word: Word, | |||||
| notes: Array<string>, | |||||
| isFavourite: boolean, | |||||
| nextRevisionDateTime: Date, | |||||
| spaceBetweenRecall: number, // in Days | |||||
| revisionHistory : Array<{ | revisionHistory : Array<{ | ||||
| day: Date, | day: Date, | ||||
| wasRecallSuccessful: boolean, | wasRecallSuccessful: boolean, | ||||
| @@ -1,7 +1,7 @@ | |||||
| import { Category } from "./category"; | import { Category } from "./category"; | ||||
| import { Shelf } from "./shelf"; | import { Shelf } from "./shelf"; | ||||
| export type IUser = { | |||||
| export interface IUser { | |||||
| _id: string, | _id: string, | ||||
| name: string, | name: string, | ||||
| email: string, | email: string, | ||||
| @@ -10,4 +10,15 @@ export type IUser = { | |||||
| otp: number, | otp: number, | ||||
| categories: Array<Category>, | categories: Array<Category>, | ||||
| uncategorised: Shelf, | uncategorised: Shelf, | ||||
| } | |||||
| export interface MongoIUser { | |||||
| _id: string, | |||||
| name: string, | |||||
| email: string, | |||||
| password: string, | |||||
| isVerified: boolean, | |||||
| otp: number, | |||||
| categories: Array<string>, //Array of IDs | |||||
| uncategorised: string, // Shelf ID | |||||
| } | } | ||||
| @@ -0,0 +1,15 @@ | |||||
| import express from 'express'; | |||||
| import passport from 'passport'; | |||||
| import { IUser } from '../models/user'; | |||||
| export const revisionRoutes = express.Router(); | |||||
| export const jwtAuthentication = passport.authenticate('jwt', { session: false }); | |||||
| revisionRoutes.get('/revision-questions/', jwtAuthentication, async (request, response) => { | |||||
| const user: IUser = (request.user as any); | |||||
| // TODO: Revision logic | |||||
| return; | |||||
| }); | |||||
| @@ -1,6 +1,10 @@ | |||||
| import express from 'express'; | import express from 'express'; | ||||
| import passport from 'passport'; | import passport from 'passport'; | ||||
| import { IUser } from '../models/user'; | import { IUser } from '../models/user'; | ||||
| import { v4 as uuidv4 } from 'uuid'; | |||||
| import { Category } from '../models/category'; | |||||
| import { DB_NAME } from '../db-utils'; | |||||
| import { getDatabaseClient } from '../db-utils'; | |||||
| export const userProfileRoutes = express.Router(); | export const userProfileRoutes = express.Router(); | ||||
| @@ -8,6 +12,32 @@ export const jwtAuthentication = passport.authenticate('jwt', { session: false } | |||||
| userProfileRoutes.get('/profile/', jwtAuthentication, async (request, response) => { | userProfileRoutes.get('/profile/', jwtAuthentication, async (request, response) => { | ||||
| const user: IUser = (request.user as any); | const user: IUser = (request.user as any); | ||||
| response.json(user); | |||||
| response.json({ | |||||
| _id: user._id, | |||||
| name: user.name, | |||||
| email: user.email, | |||||
| isVerified: user.isVerified, | |||||
| categories: user.categories, | |||||
| uncategorised: user.uncategorised | |||||
| }); | |||||
| return; | return; | ||||
| }); | |||||
| }); | |||||
| userProfileRoutes.post('/category/', jwtAuthentication, async (request, response) => { | |||||
| const user: IUser = (request.user as any); | |||||
| const userCollection = getDatabaseClient().db(DB_NAME).collection('categories'); | |||||
| const newCategory: Category = { | |||||
| _id: uuidv4(), | |||||
| name: request.body.name, | |||||
| icon: request.body.icon, | |||||
| shelves: [], | |||||
| isArchived: false, | |||||
| } | |||||
| response.status(200); | |||||
| return; | |||||
| }); | |||||