@@ -11,6 +11,7 @@ authRoutes.post('/register/', 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 isVerified: boolean = false; | const isVerified: boolean = false; | ||||
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 | ||||
@@ -4,10 +4,10 @@ export interface Category { | |||||
_id: string, | _id: string, | ||||
name: string, | name: string, | ||||
icon: string, | icon: string, | ||||
shelves: Array<Shelf>, | |||||
shelves?: Array<Shelf>, | |||||
isArchived: boolean, | isArchived: boolean, | ||||
} | } | ||||
export interface MongoCategory extends Omit<Category, 'shelves'> { | export interface MongoCategory extends Omit<Category, 'shelves'> { | ||||
shelves: Array<string>, // Ids | |||||
shelves?: Array<string>, // Shelf IDs | |||||
} | } |
@@ -1,16 +1,14 @@ | |||||
import { LanguageType } from "./variables"; | import { LanguageType } from "./variables"; | ||||
import { Word } from "./word"; | import { Word } from "./word"; | ||||
export interface Library { | export interface Library { | ||||
_id: string, | _id: string, | ||||
languageType: LanguageType, | languageType: LanguageType, | ||||
isArchived: boolean, | isArchived: boolean, | ||||
allWords: Array<{ | |||||
word: Word, | |||||
isArchived: boolean, | |||||
wordStats: { | |||||
favouriteCount: number, // Total users who liked this word | |||||
addCount: number, // Total users have added this word to their shelf | |||||
} | |||||
}>, | |||||
allWords: Array<Word>, | |||||
} | |||||
export interface MongoLibrary extends Omit<Library, "allWords"> { | |||||
allWords: Array<string> // Word IDs | |||||
} | } |
@@ -1,24 +1,17 @@ | |||||
import { Category } from "./category"; | import { Category } from "./category"; | ||||
import { Shelf } from "./shelf"; | import { Shelf } from "./shelf"; | ||||
export interface IUser { | |||||
export interface User { | |||||
_id: string, | _id: string, | ||||
name: string, | name: string, | ||||
email: string, | email: string, | ||||
password: string, | password: string, | ||||
isVerified: boolean, | isVerified: boolean, | ||||
otp: number, | otp: number, | ||||
categories: Array<Category>, | |||||
uncategorised: Shelf, | |||||
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 | |||||
export interface MongoUser extends Omit<User, "categories"> { | |||||
categories?: Array<string> // Category IDs | |||||
} | } |
@@ -1,16 +1,27 @@ | |||||
import { grammarType } from "./variables"; | import { grammarType } from "./variables"; | ||||
interface gramaticalDetail { | |||||
type: grammarType, | |||||
description: string, | |||||
examples: Array<string>, | |||||
} | |||||
export interface Word { | export interface Word { | ||||
_id: string, | _id: string, | ||||
name: string, | name: string, | ||||
pronounciation: { | pronounciation: { | ||||
text: string, | text: string, | ||||
audio: string, | |||||
audio?: string, | |||||
}, | |||||
similarWords?: Array<Word>, | |||||
grammaticalDetails: Array<gramaticalDetail>, | |||||
wordStats: { | |||||
favouriteCount: number, // Total users who liked this word | |||||
addCount: number, // Total users have added this word to their shelf | |||||
}, | }, | ||||
similarWords: Array<Word>, | |||||
grammaticalDetails: Array<{ | |||||
type: grammarType, | |||||
description: string, | |||||
examples: Array<string>, | |||||
}> | |||||
isArchived: boolean, | |||||
} | |||||
export interface MongoWord extends Omit<Word, "similarWords"> { | |||||
similarWords: Array<string> | |||||
} | } |
@@ -1,13 +1,13 @@ | |||||
import express from 'express'; | import express from 'express'; | ||||
import passport from 'passport'; | import passport from 'passport'; | ||||
import { IUser } from '../models/user'; | |||||
import { User } from '../models/user'; | |||||
export const revisionRoutes = express.Router(); | export const revisionRoutes = express.Router(); | ||||
export const jwtAuthentication = passport.authenticate('jwt', { session: false }); | export const jwtAuthentication = passport.authenticate('jwt', { session: false }); | ||||
revisionRoutes.get('/revision-questions/', jwtAuthentication, async (request, response) => { | revisionRoutes.get('/revision-questions/', jwtAuthentication, async (request, response) => { | ||||
const user: IUser = (request.user as any); | |||||
const user: User = (request.user as any); | |||||
// TODO: Revision logic | // TODO: Revision logic | ||||
@@ -1,17 +1,17 @@ | |||||
import express from 'express'; | 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 passport, { use } from 'passport'; | |||||
import { MongoUser } from '../models/user'; | |||||
import { Category, MongoCategory } from '../models/category'; | |||||
import { DB_NAME } from '../db-utils'; | import { DB_NAME } from '../db-utils'; | ||||
import { getDatabaseClient } from '../db-utils'; | import { getDatabaseClient } from '../db-utils'; | ||||
import { ObjectId } from 'bson'; | |||||
export const userProfileRoutes = express.Router(); | export const userProfileRoutes = express.Router(); | ||||
export const jwtAuthentication = passport.authenticate('jwt', { session: false }); | 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: MongoUser = (request.user as any); | |||||
response.json({ | response.json({ | ||||
_id: user._id, | _id: user._id, | ||||
name: user.name, | name: user.name, | ||||
@@ -23,21 +23,91 @@ userProfileRoutes.get('/profile/', jwtAuthentication, async (request, response) | |||||
return; | return; | ||||
}); | }); | ||||
userProfileRoutes.post('/category/', jwtAuthentication, async (request, response) => { | userProfileRoutes.post('/category/', jwtAuthentication, async (request, response) => { | ||||
const user: IUser = (request.user as any); | |||||
const user: MongoUser = (request.user as any); | |||||
const userCollection = getDatabaseClient().db(DB_NAME).collection('categories'); | |||||
const categoryCollection = getDatabaseClient().db(DB_NAME).collection('categories'); | |||||
const userCollection = getDatabaseClient().db(DB_NAME).collection('users'); | |||||
const newCategory: Category = { | |||||
_id: uuidv4(), | |||||
name: request.body.name, | |||||
icon: request.body.icon, | |||||
shelves: [], | |||||
isArchived: false, | |||||
if (!request.body.name || !request.body.icon) { | |||||
response.status(400); | |||||
response.send("Category Name or icon(base64) missing"); | |||||
return; | |||||
} | } | ||||
response.status(200); | |||||
try { | |||||
const newCategory = await categoryCollection.insertOne({ | |||||
name: request.body.name, | |||||
icon: request.body.icon, | |||||
isArchived: false, | |||||
}); | |||||
if (!user.categories) { | |||||
user.categories = []; | |||||
} | |||||
user.categories.push(newCategory.insertedId.toHexString()); | |||||
await userCollection.updateOne({ | |||||
_id: user._id | |||||
}, { | |||||
$set: { | |||||
categories: user.categories | |||||
} | |||||
}); | |||||
response.sendStatus(200); | |||||
} catch(e) { | |||||
response.sendStatus(500); | |||||
return; | |||||
} | |||||
return; | |||||
}); | |||||
userProfileRoutes.put('/category/', jwtAuthentication, async (request, response) => { | |||||
const categoryCollection = getDatabaseClient().db(DB_NAME).collection('categories'); | |||||
let currentCategory; | |||||
try { | |||||
currentCategory = await categoryCollection.findOne({ | |||||
_id: new ObjectId(request.body._id) | |||||
}); | |||||
} catch { | |||||
if (!currentCategory) { | |||||
response.status(400); | |||||
response.send("Category ID did not match"); | |||||
return; | |||||
} | |||||
} | |||||
if (request.body.isArchived) { | |||||
if (typeof request.body.isArchived !== "boolean") { | |||||
response.status(400); | |||||
response.send("Archived should be a boolean flag"); | |||||
return; | |||||
} | |||||
} | |||||
try { | |||||
await categoryCollection.updateOne({ | |||||
_id: new ObjectId(request.body._id), | |||||
}, { | |||||
$set: { | |||||
name: request.body.name ? request.body.name : currentCategory.name, | |||||
icon: request.body.icon ? request.body.icon : currentCategory.icon, | |||||
isArchived: request.body.isArchived !== undefined ? request.body.isArchived : currentCategory.isArchived | |||||
} | |||||
}); | |||||
response.sendStatus(200); | |||||
} catch (e) { | |||||
response.status(400); | |||||
response.json(e); | |||||
} | |||||
return; | return; | ||||
}); | }); |