diff --git a/package-lock.json b/package-lock.json index ce97ce0..f217d6d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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==" } } } diff --git a/package.json b/package.json index 24762ff..92a531d 100644 --- a/package.json +++ b/package.json @@ -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": { diff --git a/src/authentication/routes.ts b/src/authentication/routes.ts index 71e038e..b03d381 100644 --- a/src/authentication/routes.ts +++ b/src/authentication/routes.ts @@ -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 = []; - 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]; diff --git a/src/index.ts b/src/index.ts index 9d88f30..1d42273 100644 --- a/src/index.ts +++ b/src/index.ts @@ -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')); diff --git a/src/models/category.ts b/src/models/category.ts index 2f52384..f801033 100644 --- a/src/models/category.ts +++ b/src/models/category.ts @@ -6,4 +6,8 @@ export interface Category { icon: string, shelves: Array, isArchived: boolean, +} + +export interface MongoCategory extends Omit { + shelves: Array, // Ids } \ No newline at end of file diff --git a/src/models/shelf.ts b/src/models/shelf.ts index b4f51a3..e3ad642 100644 --- a/src/models/shelf.ts +++ b/src/models/shelf.ts @@ -12,6 +12,26 @@ export interface Shelf { notes: Array, 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, + isFavourite: boolean, + nextRevisionDateTime: Date, + spaceBetweenRecall: number, // in Days revisionHistory : Array<{ day: Date, wasRecallSuccessful: boolean, diff --git a/src/models/user.ts b/src/models/user.ts index bd0f206..ebcba4e 100644 --- a/src/models/user.ts +++ b/src/models/user.ts @@ -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, uncategorised: Shelf, +} + +export interface MongoIUser { + _id: string, + name: string, + email: string, + password: string, + isVerified: boolean, + otp: number, + categories: Array, //Array of IDs + uncategorised: string, // Shelf ID } \ No newline at end of file diff --git a/src/revision/routes.ts b/src/revision/routes.ts new file mode 100644 index 0000000..231aecd --- /dev/null +++ b/src/revision/routes.ts @@ -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; +}); \ No newline at end of file diff --git a/src/user-profile/routes.ts b/src/user-profile/routes.ts index aa11d38..f2c11ae 100644 --- a/src/user-profile/routes.ts +++ b/src/user-profile/routes.ts @@ -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; -}); \ No newline at end of file +}); + + +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; +});