@@ -1,5 +1,5 @@ | |||
{ | |||
"name": "job-portal", | |||
"name": "anamnesis", | |||
"version": "1.0.0", | |||
"lockfileVersion": 1, | |||
"requires": true, | |||
@@ -30,6 +30,19 @@ | |||
"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": { | |||
"version": "1.0.5", | |||
"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" | |||
} | |||
}, | |||
"@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": { | |||
"version": "5.0.0", | |||
"resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.0.tgz", | |||
@@ -266,6 +299,16 @@ | |||
"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": { | |||
"version": "6.0.2", | |||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", | |||
@@ -346,6 +389,11 @@ | |||
"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": { | |||
"version": "1.0.10", | |||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", | |||
@@ -688,6 +736,11 @@ | |||
"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": { | |||
"version": "2.0.0", | |||
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", | |||
@@ -752,8 +805,7 @@ | |||
"diff": { | |||
"version": "4.0.2", | |||
"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": { | |||
"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": { | |||
"version": "0.3.0", | |||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", | |||
@@ -2068,6 +2125,25 @@ | |||
"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": { | |||
"version": "1.14.1", | |||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", | |||
@@ -2325,6 +2401,11 @@ | |||
"version": "4.0.0", | |||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", | |||
"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", | |||
"passport": "^0.5.0", | |||
"passport-jwt": "^4.0.0", | |||
"ts-node": "^10.3.0", | |||
"uuid": "^8.3.2" | |||
}, | |||
"devDependencies": { | |||
@@ -3,27 +3,14 @@ import { DB_NAME, getDatabaseClient } from '../db-utils'; | |||
import bcrypt from 'bcrypt'; | |||
import { generateJWT, SALT_ROUNDS } from './auth'; | |||
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(); | |||
authRoutes.post('/register-applicant/', async (request, response) => { | |||
authRoutes.post('/register/', async (request, response) => { | |||
const name: string = request.body.name; | |||
const email: string = request.body.email; | |||
const password: string = request.body.password; | |||
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'); | |||
// Check if form is filled | |||
@@ -59,8 +46,6 @@ authRoutes.post('/register-applicant/', async (request, response) => { | |||
email, | |||
password: hashedPassword, | |||
isVerified, | |||
categories, | |||
uncategorised | |||
}); | |||
}); | |||
@@ -180,9 +165,8 @@ authRoutes.post('/verify-user/', async (request, response) => { | |||
authRoutes.post('/api-auth/', async (request, response) => { | |||
const email: string = request.body.email; | |||
const password: string = request.body.password; | |||
const userType: string = request.body.userType; | |||
if (!email || !password || !userType) { | |||
if (!email || !password) { | |||
response.status(400); | |||
response.send("Please field the required fields"); | |||
return; | |||
@@ -192,7 +176,6 @@ authRoutes.post('/api-auth/', async (request, response) => { | |||
let users = await userCollection.find({ | |||
email, | |||
userType, | |||
}).toArray(); | |||
const matchedUser = users[0]; | |||
@@ -5,6 +5,7 @@ import authRoutes from './authentication/routes'; | |||
import { connectToDatabaseServer } from './db-utils'; | |||
import sendGridMail from '@sendgrid/mail'; | |||
import { userProfileRoutes } from './user-profile/routes'; | |||
import { revisionRoutes } from './revision/routes'; | |||
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.use('/', authRoutes); | |||
app.use('/', userProfileRoutes); | |||
app.use('/', revisionRoutes); | |||
app.get('/', (request, response) => { | |||
response.send('Server running @ port' + app.get('port')); | |||
@@ -6,4 +6,8 @@ export interface Category { | |||
icon: string, | |||
shelves: Array<Shelf>, | |||
isArchived: boolean, | |||
} | |||
export interface MongoCategory extends Omit<Category, 'shelves'> { | |||
shelves: Array<string>, // Ids | |||
} |
@@ -12,6 +12,26 @@ export interface Shelf { | |||
notes: Array<string>, | |||
isFavourite: boolean, | |||
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<{ | |||
day: Date, | |||
wasRecallSuccessful: boolean, | |||
@@ -1,7 +1,7 @@ | |||
import { Category } from "./category"; | |||
import { Shelf } from "./shelf"; | |||
export type IUser = { | |||
export interface IUser { | |||
_id: string, | |||
name: string, | |||
email: string, | |||
@@ -10,4 +10,15 @@ export type IUser = { | |||
otp: number, | |||
categories: Array<Category>, | |||
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 passport from 'passport'; | |||
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(); | |||
@@ -8,6 +12,32 @@ export const jwtAuthentication = passport.authenticate('jwt', { session: false } | |||
userProfileRoutes.get('/profile/', jwtAuthentication, async (request, response) => { | |||
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; | |||
}); | |||
}); | |||
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; | |||
}); |