diff --git a/Pradyuman_Agrawal/Week-0/README.md b/Pradyuman_Agrawal/Week-0/README.md new file mode 100644 index 00000000..2ea1a585 --- /dev/null +++ b/Pradyuman_Agrawal/Week-0/README.md @@ -0,0 +1,7 @@ +To spin up MYSQL server as a container (what i ended up using for setting up Mysql on my laptop) + +```docker run -p 3306:3306 --name nodejs-mysql -e MYSQL_ROOT_PASSWORD=pass -e MYSQL_DATABASE=user_db -d mysql:5.7``` + +To open it with an interactive shell + +```docker exec -it bash``` \ No newline at end of file diff --git a/Pradyuman_Agrawal/Week-0/array.js b/Pradyuman_Agrawal/Week-0/array.js new file mode 100644 index 00000000..99746de6 --- /dev/null +++ b/Pradyuman_Agrawal/Week-0/array.js @@ -0,0 +1,29 @@ +let arr=[34,56,76,54,60] + +let min=arr[0],max=arr[0],sum=0,totalFail=0,totalPass=0 + +for(const a of arr){ + console.log(a) + if(amax) + max=a; + sum+=a; + if(a>=50) + totalPass++ + else + totalFail++; +} +console.log(`Min score was ${min}`) +console.log(`Max score was ${max}`) +console.log(`Sum score was ${sum}`) +console.log(`total Pass score was ${totalPass}`) +console.log(`total Fail score was ${totalFail}`) + + +const numbers = [1, 2, 3, 4, 5] + +for (const num of numbers) { + console.log(num) +} + diff --git a/Pradyuman_Agrawal/Week-0/conditional.js b/Pradyuman_Agrawal/Week-0/conditional.js new file mode 100644 index 00000000..a03c1a92 --- /dev/null +++ b/Pradyuman_Agrawal/Week-0/conditional.js @@ -0,0 +1,17 @@ + +//day 2 + +let marks = 9 + +if(marks>=90){ + alert("Yippee you got A grade") +} +else if(marks>=80){ + alert("you got B grade") +} +else if(marks>=60){ + alert("you got C grade, more efforts required!") +} +else{ + alert("we need to have a serious talk, you got a D") +} \ No newline at end of file diff --git a/Pradyuman_Agrawal/Week-0/data.json b/Pradyuman_Agrawal/Week-0/data.json new file mode 100644 index 00000000..5c9be5be --- /dev/null +++ b/Pradyuman_Agrawal/Week-0/data.json @@ -0,0 +1,4 @@ +{ + "name": "Pradyuman Agrawal", + "address": "Po Box City" +} \ No newline at end of file diff --git a/Pradyuman_Agrawal/Week-0/db.js b/Pradyuman_Agrawal/Week-0/db.js new file mode 100644 index 00000000..af8739e5 --- /dev/null +++ b/Pradyuman_Agrawal/Week-0/db.js @@ -0,0 +1,19 @@ +const mysql = require('mysql'); + +const con = mysql.createConnection({ + host: "localhost", + user: "root", + password: "pass" +}); + +con.connect(function(err) { + if (err) throw err; + console.log("Connected!"); + con.query(`SELECT * FROM user_db.user`, function(err, result, fields) { + if (err) + console.log(err); + if (result) + console.log(result); + }); + con.end(); +}); \ No newline at end of file diff --git a/Pradyuman_Agrawal/Week-0/demo.html b/Pradyuman_Agrawal/Week-0/demo.html new file mode 100644 index 00000000..e2ad17c2 --- /dev/null +++ b/Pradyuman_Agrawal/Week-0/demo.html @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Pradyuman_Agrawal/Week-0/demo.js b/Pradyuman_Agrawal/Week-0/demo.js new file mode 100644 index 00000000..2c890b17 --- /dev/null +++ b/Pradyuman_Agrawal/Week-0/demo.js @@ -0,0 +1,22 @@ +let string = "JavasCript" +console.log(string) + +string="hello" +console.log(string) + +string[0]="a" +console.log(string) + + +let a=10; +console.log(a) +a=5 +console.log(a) + + +const num = Math.floor(Math.random () * 101) +console.log(num) + +const now = new Date() +console.log(now) +console.log(now.getTime()) diff --git a/Pradyuman_Agrawal/Week-0/es6.js b/Pradyuman_Agrawal/Week-0/es6.js new file mode 100644 index 00000000..414cc9b0 --- /dev/null +++ b/Pradyuman_Agrawal/Week-0/es6.js @@ -0,0 +1,19 @@ +// Task +const EvenOdd = num => { + if (num % 2) + console.log("Odd Number"); + else + console.log("Even Number"); + }; + + EvenOdd(10); + + const user = { + username: "Pradyuman", + password: "pass", + }; + + let { username, password } = user; + + console.log(username); + console.log(password); \ No newline at end of file diff --git a/Pradyuman_Agrawal/Week-0/fun.js b/Pradyuman_Agrawal/Week-0/fun.js new file mode 100644 index 00000000..4892a9b9 --- /dev/null +++ b/Pradyuman_Agrawal/Week-0/fun.js @@ -0,0 +1,16 @@ +const square = function() { + let n=1 + return n * n + } + + console.log(square()) + +const arrFun = (name)=>{ +console.log(`hello there, ${name}`) +} + +arrFun("Pradyuman"); + +(function(name) { + console.log(name) +})("pradyuman") \ No newline at end of file diff --git a/Pradyuman_Agrawal/Week-0/package-lock.json b/Pradyuman_Agrawal/Week-0/package-lock.json new file mode 100644 index 00000000..2726e290 --- /dev/null +++ b/Pradyuman_Agrawal/Week-0/package-lock.json @@ -0,0 +1,169 @@ +{ + "name": "Pradyuman_Agrawal", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "dependencies": { + "mysql": "^2.18.1" + } + }, + "node_modules/bignumber.js": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", + "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==", + "engines": { + "node": "*" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/mysql": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", + "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", + "dependencies": { + "bignumber.js": "9.0.0", + "readable-stream": "2.3.7", + "safe-buffer": "5.1.2", + "sqlstring": "2.3.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/sqlstring": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", + "integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + } + }, + "dependencies": { + "bignumber.js": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", + "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==" + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "mysql": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", + "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", + "requires": { + "bignumber.js": "9.0.0", + "readable-stream": "2.3.7", + "safe-buffer": "5.1.2", + "sqlstring": "2.3.1" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "sqlstring": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", + "integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + } + } +} diff --git a/Pradyuman_Agrawal/Week-0/package.json b/Pradyuman_Agrawal/Week-0/package.json new file mode 100644 index 00000000..49ed5f99 --- /dev/null +++ b/Pradyuman_Agrawal/Week-0/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "mysql": "^2.18.1" + } +} diff --git a/Pradyuman_Agrawal/Week-0/readJson.js b/Pradyuman_Agrawal/Week-0/readJson.js new file mode 100644 index 00000000..307a9bae --- /dev/null +++ b/Pradyuman_Agrawal/Week-0/readJson.js @@ -0,0 +1,23 @@ +const fs =require("fs") + +function jsonReader(filePath, cb) { + fs.readFile(filePath, (err, fileData) => { + if (err) { + return cb(err) + } + try { + const object = JSON.parse(fileData) + return cb(null, object) + } catch(err) { + return cb(err) + } + }) +} + +jsonReader('./data.json', (err, user) => { + if (err) { + console.log(err) + return + } + console.log(user.address) +}) \ No newline at end of file diff --git a/Pradyuman_Agrawal/Week-0/writeJson.js b/Pradyuman_Agrawal/Week-0/writeJson.js new file mode 100644 index 00000000..039978c9 --- /dev/null +++ b/Pradyuman_Agrawal/Week-0/writeJson.js @@ -0,0 +1,15 @@ +const fs = require("fs") + +const user = { + name: "Pradyuman Agrawal", + address: "Po Box City", +} + +const jsonString = JSON.stringify(user,null,2) +fs.writeFile('./data.json', jsonString, err => { + if (err) { + console.log('Error writing file', err) + } else { + console.log('Successfully wrote file') + } +}) \ No newline at end of file diff --git a/Pradyuman_Agrawal/teams_app/.gitignore b/Pradyuman_Agrawal/teams_app/.gitignore new file mode 100644 index 00000000..6fe20f0f --- /dev/null +++ b/Pradyuman_Agrawal/teams_app/.gitignore @@ -0,0 +1,3 @@ +node_modules +.env +package-lock.json \ No newline at end of file diff --git a/Pradyuman_Agrawal/teams_app/README.md b/Pradyuman_Agrawal/teams_app/README.md new file mode 100644 index 00000000..b4ea55cf --- /dev/null +++ b/Pradyuman_Agrawal/teams_app/README.md @@ -0,0 +1,131 @@ +# Teams application + +- This repository consists of the codes for the backend of an application to help and manage meetings for a user. + +Features: +- User Registration +- Get all user info +- Update user info +- Login +- Schedule a Meeting +- Edit a Meeting +- Drop off a user from a meeting +- Create Meeting Invite Link (with different access level) +- Join Meeting with the Invite Link + +## Setting up environment +- Download the code to your local system using git clone. +- Have a local instance of MYSQL server running on you laptop. + - You can also spin up a docker container with the official MySQL image to avoid a confusing MySQL setup. + +To spin up MYSQL server as a container + +``` +docker run -p 3306:3306 --name nodejs-mysql +-e MYSQL_ROOT_PASSWORD=pass +-e MYSQL_DATABASE=user_db +-d mysql:5.7 +``` + +To open the container with an interactive shell + +``` +docker exec -it bash +``` + +- Install the npm modules +``` + npm install + ``` +- Start the server using the command +``` + node server.js + ``` +- With this, the server starts listening for requests and API is up and working to test around + +## Endpoints +### User related endpoints +### `POST: /users/` +Result: +Register a new user and login the user with proper json web token +#### Payload + ```json + { + "email":"ns26@iitbbs.ac.in", + "password":"pass", + "name":"nikhil" + } + ``` + +### `GET: /users/` +Result: +Get all users infor + +### `GET: /users/:id` +Result: +Find a user with UserId + +### `PUT: /users/id` +Result: +Update user info by UserId + +### `DELETE: /users/id` +Result: +Delete User by UserId + +### Auth endpoints +### `POST: /auth/login` +Result: +Login a new user along with Json web token +#### Payload + ```json + { + "email":"ns26@iitbbs.ac.in", + "password":"pass" + } + ``` +### Meetings related endpoints + +### `POST: /meetings/` +Result: +Create a new meeting +#### Payload + ```json + { + "startTime":"09/01/22 6:45:00", + "endTime":"09/01/22 9:45:00", + "description":"first test meeting", + "members":[2,6], + "inviteLinkAccess":true + } + ``` + +### `GET: /meetings/` +Result: +Get all meetings info + +### `GET: /meetings/:id` +Result: +Find a meeting with meetingId + +### `GET: /meetings/withCreatorId/:id` +Result: +Find all the meetings created by a UserID + +### `GET: /meetings/withMemberId/:id` +Result: +Find all the meeting having a specific userId as a member + +### `DELETE: /meetings/:id` +Result: +Delete meeting with ID + +### `DELETE: /meetings/dropoff/:id` +Result: +Delete table entry for dropoff request + +### `GET: /meetings/creatInviteLink/:id` +Result: create a meeting invite Link based on the access level defined by the meeting creator + +### `GET: /meetings/joinWithInviteLink/:encryptedMeetingId` +Result: join a meeting's member list by the following the invite link \ No newline at end of file diff --git a/Pradyuman_Agrawal/teams_app/config/db.js b/Pradyuman_Agrawal/teams_app/config/db.js new file mode 100644 index 00000000..69b62cd6 --- /dev/null +++ b/Pradyuman_Agrawal/teams_app/config/db.js @@ -0,0 +1,22 @@ +const mysql = require("mysql"); + +const pool = mysql.createPool({ + host:process.env.SQL_ENDPOINT, + user: process.env.DB_USERNAME, + password: process.env.DB_PASSWORD, + database: process.env.DB, + connectionLimit : 10, + multipleStatements: true +}) + +pool.promise = (sql,args) => { + return new Promise((resolve, reject) => { + pool.query(sql, args,(err, result) => { + if(err){reject(err);} + else{resolve(result);} + }); + }); +}; + +module.exports = pool; + diff --git a/Pradyuman_Agrawal/teams_app/config/populate.sql b/Pradyuman_Agrawal/teams_app/config/populate.sql new file mode 100644 index 00000000..b3a9626d --- /dev/null +++ b/Pradyuman_Agrawal/teams_app/config/populate.sql @@ -0,0 +1,31 @@ +create database teams_db; +use teams_db; + +drop table meetingMembers; +drop table meetings; +drop table users; + +CREATE TABLE users( +userId INT PRIMARY KEY AUTO_INCREMENT, +email varchar(40) UNIQUE, +password VARCHAR(200) NOT NULL, +name VARCHAR(40) NOT NULL +); + +CREATE TABLE meetings( +meetingId INT PRIMARY KEY AUTO_INCREMENT, +creatorId INT NOT NULL, +startTime TIMESTAMP NOT NULL, +endTime TIMESTAMP DEFAULT "2000-01-01T12:00:00", +description varchar(200), +inviteLinkAccess BOOLEAN DEFAULT FALSE, +FOREIGN KEY (creatorId) REFERENCES users(userId) +); + +CREATE TABLE meetingMembers( + meetingId INT NOT NULL, + userId INT NOT NULL, + CONSTRAINT PK_meetingMembers PRIMARY KEY (meetingId,userId), + FOREIGN KEY (userId) REFERENCES users(userId), + FOREIGN KEY (meetingId) REFERENCES meetings(meetingId) +); diff --git a/Pradyuman_Agrawal/teams_app/controllers/auth.js b/Pradyuman_Agrawal/teams_app/controllers/auth.js new file mode 100644 index 00000000..0d2728d6 --- /dev/null +++ b/Pradyuman_Agrawal/teams_app/controllers/auth.js @@ -0,0 +1,54 @@ +const User = require("../models/users.js"); +const bcrypt = require("bcryptjs"); +const jwt = require("jsonwebtoken") + +//get all user +const login =async (req,res) => { + //get user input + const {email,password}=req.body; + //validate input + if(!(email&&password)){ + return res.status(400).send("all inputs for login required"); + } + + try{ + //check if user exists with same emailId + const data = await User.findUserByEmailId(email); + if(data.user.length==0){ + return res.status(400).send(`Sorry user with email ${email} doesnt exists, Trying registering instead`); + } + const user = data.user; + if(await bcrypt.compare(password,user.password)){ + //create token + const token = jwt.sign( + {userId:user.userId,email:email}, + process.env.TOKEN_KEY, + { + expiresIn:"24h" + } + ) + console.log("User successfully logged in") + user.token=token; + return res.status(200).json(user); + } + res.status(400).send("Invalid credentials"); + } catch(e){ + res.status(500).send({ + message:"internal error" + }) + } +} + +//find user by userId +const logout = (req,res) => { + res.status(404).send("Endpoint yet to be implemented"); +} + +module.exports = { + login, + logout +}; + + + + diff --git a/Pradyuman_Agrawal/teams_app/controllers/meetings.js b/Pradyuman_Agrawal/teams_app/controllers/meetings.js new file mode 100644 index 00000000..17e687c0 --- /dev/null +++ b/Pradyuman_Agrawal/teams_app/controllers/meetings.js @@ -0,0 +1,245 @@ +const Meeting = require("../models/meetings.js") +const Cryptr=require('cryptr'); +const cryptr = new Cryptr(process.env.CIPHER_KEY); +//util function to make members array for a meeting from an array +const createMembersArray=(data)=>{ + const result=[] + let meetingObj={} + meetingObj.meetingId=data[0].meetingId; + meetingObj.startTime=data[0].startTime; + meetingObj.creatorId=data[0].creatorId; + meetingObj.members=new Array() + data.forEach(element => { + if(meetingObj.meetingId!=element.meetingId) + { + result.push(meetingObj); + meetingObj={} + meetingObj.meetingId=element.meetingId; + meetingObj.startTime=element.startTime; + meetingObj.creatorId=element.creatorId; + meetingObj.members=[]; + } + meetingObj.members.push(element.userId); + }); + result.push(meetingObj); + return result; +} + +//Create meeting +const create = async (req,res) => { + + const creatorId=req.userId; + //get Meeting input + const {startTime,members,endTime,description,inviteLinkAccess}=req.body; + //validate Meeting input + if(!(creatorId&&startTime&&members.length)){ + return res.status(400).send("All Meeting inputs are required"); + } + + //make sure creatorId is a member of the meeting + let flag=false; + members.forEach(memberId=>{ + flag=(memberId===creatorId) + }) + if(!flag) + members.push(creatorId) + + const meeting = new Meeting({ + creatorId : creatorId, + startTime : new Date(startTime), + members: members, + endTime : new Date(endTime), + description:description, + inviteLinkAccess: inviteLinkAccess||false + }) + + try{ + const data = await Meeting.create(meeting); + res.status(201).send(data); + } catch(e){ + res.status(500).send({ + message:"internal error" + }) + } +} + +//get all meeting +const getAllMeeting = async (req,res) => { + try{ + const data = await Meeting.getAllMeeting(req.query); + const result = createMembersArray(data); + res.status(200).send(result); + } catch(e){ + console.log(e) + res.status(500).send({ + message:"internal error" + }) + } +} + +//find meeting by meetingId +const findMeetingById = async (req,res) => { + const meetingId = req.params.id; + try{ + const data = await Meeting.findMeetingById(meetingId); + if(data.length==0){ + return res.send("meeting with Id Doesnt exist"); + } + const result = createMembersArray(data); + res.status(200).send(result[0]); + } catch(e){ + res.status(500).send({ + message:"internal error" + }) + } +} + +const findMeetingByCreatorId = async (req,res) => { + const creatorId = req.params.userId; + try{ + const data = await Meeting.findMeetingByCreatorId(creatorId); + if(data.length==0){ + return res.send("No meeting made by this user"); + } + const result = createMembersArray(data); + res.status(200).send(result); + } catch(e){ + console.log(e); + res.status(500).send({ + message:"internal error" + }) + } +} + +const findMeetingByMemberId = async (req,res) => { + const userId = req.params.userId; + try{ + const data = await Meeting.findMeetingByMemberId(userId); + if(data.length==0){ + return res.status(200).send("No meeting made by this user"); + } + const result = createMembersArray(data); + res.status(200).send(result); + } catch(e){ + res.status(500).send({ + message:"internal error" + }) + } +} + +//update meeting by meetingId +const updateMeetingById = async (req,res) => { + const meetingId = req.params.id; + const updateInfo = new Meeting({ + startTime :req.body.startTime, + endTime :req.body.endTime, + description:req.bodydescription + }) + try{ + const data = await User.updateMeetingById(meetingId,updateInfo,); + res.status(200).send(data); + } catch(e){ + res.status(500).send({ + message:"internal error" + }) + } +} + +//delete meeting by meetingId +const deleteMeetingById = async (req,res) => { + const meetingId = req.params.id; + try{ + const result = await Meeting.findcreatorIdByMeetingId(meetingId) + if(result.length==0) + return res.send("meeting with Id Doesnt exist"); + else if(result[0].creatorId!==req.userId) + return res.status(403).send("user Is not authorised to delete this Meeting"); + const data = await Meeting.deleteMeetingById(meetingId); + res.status(200).send(data); + } catch(e){ + console.log(e) + res.status(500).send({ + message:"internal error" + }) + } +} + +//delete meeting by meetingId +const dropOffMeetingById = async (req,res) => { + const meetingId = req.params.id; + try{ + const data = await Meeting.dropOffMeetingById(meetingId,req.userId); + if(data.length==0){ + return res.send("meeting with Id Doesnt exist"); + } + res.status(200).send(data); + } catch(e){ + console.log(e) + res.status(500).send({ + message:"internal error" + }) + } +} + + +const createInviteLink = async (req,res) => { + const meetingId = req.params.id; + try{ + //create a encrypted invite link + const data = await Meeting.findMeetingById(meetingId); + if(data.length==0){ + return res.send("meeting with Id doesnt exist"); + } + if(data[0].inviteLinkAccess||data[0].creatorId===req.userId) + { + inviteLink="http://localhost:3000/meetings/joinWithInviteLink/" + const encryptedString = cryptr.encrypt(meetingId); + inviteLink+=encryptedString; + res.status(200).send(inviteLink); + } + else{ + res.status(403).send("Invite Link access is denied"); + } + } catch(e){ + console.log(e) + res.status(500).send({ + message:"internal error" + }) + } +} + + +const joinMeetingbyId = async (req,res) => { + try{ + const meetingId = cryptr.decrypt(req.params.encryptedMeetingId); + console.log(meetingId); + const data = await Meeting.joinMeetingbyId(req.userId,meetingId); + if(data.length==0){ + return res.send("meeting with Id Doesnt exist"); + } + res.status(200).send(data); + } catch(e){ + console.log(e) + res.status(500).send({ + message:"internal error" + }) + } +} + +module.exports = { + create, + getAllMeeting, + findMeetingById, + findMeetingByCreatorId, + findMeetingByMemberId, + updateMeetingById, + deleteMeetingById, + dropOffMeetingById, + createInviteLink, + joinMeetingbyId +}; + + + + + diff --git a/Pradyuman_Agrawal/teams_app/controllers/users.js b/Pradyuman_Agrawal/teams_app/controllers/users.js new file mode 100644 index 00000000..005ccfcc --- /dev/null +++ b/Pradyuman_Agrawal/teams_app/controllers/users.js @@ -0,0 +1,120 @@ +const User = require("../models/users.js") +const bcrypt = require("bcryptjs") +const jwt = require("jsonwebtoken") + +//signup user +const create = async (req,res) => { + + //get user input + const {name,email,password}=req.body; + + //validate user input + if(!(email&&password&&name)){ + return res.status(400).send("All user inputs are required"); + } + + try{ + //check if user exists with same emailId + const data = await User.findUserByEmailId(email); + if(data.user.userId){ + return res.status(400).send(`Sorry user with email ${email} already exists, Trying logging instead`); + } + //encrpyt user password + encryptedPassword =await bcrypt.hash(password,10) + + const user = new User({ + email:email, + password:encryptedPassword, + name:name + }) + const result = await User.create(user); + //create token + const token = jwt.sign( + {userId:result.id,email:email}, + process.env.TOKEN_KEY, + { + expiresIn:"24h" + } + ) + console.log("User successfully logged in") + result.token=token; + + res.status(201).send(result); + } catch(e){ + res.status(500).send({ + message:"internal error" + }) + } +} + +//get all user +const getAllUser = async (req,res) => { + try{ + const data = await User.getAllUser(); + res.status(200).send(data); + } catch(e){ + res.status(500).send({ + message:"internal error" + }) + } +} + +//find user by userId +const findUserById = async (req,res) => { + const userId = req.params.id; + try{ + const data = await User.findUserById(userId); + console.log(data) + return res.status(200).send(data); + } catch(e){ + res.status(500).send({ + message:"internal error" + }) + } +} + +//update user by userId +const updateUserById = async (req,res) => { + const userId = req.params.id; + const updateInfo = new User({ + email:req.body.email||"", + password:req.body.password||"", + name:req.body.name||"" + }) + if(updateInfo.password){ + updateInfo.password=await bcrypt.hash(updateInfo.password,10) + } + try{ + const data = await User.updateUserById(userId,updateInfo); + res.status(200).send(data); + } catch(e){ + res.status(500).send({ + message:"internal error" + }) + } +} + +//delete user by userId +const deleteUserById = async (req,res) => { + const userId = req.params.id; + try{ + const data = await User.deleteUserById(userId); + res.status(200).send(data); + } catch(e){ + res.status(500).send({ + message:"internal error" + }) + } +} + +module.exports = { + create, + getAllUser, + findUserById, + updateUserById, + deleteUserById +}; + + + + diff --git a/Pradyuman_Agrawal/teams_app/middleware/auth.js b/Pradyuman_Agrawal/teams_app/middleware/auth.js new file mode 100644 index 00000000..3aa032a8 --- /dev/null +++ b/Pradyuman_Agrawal/teams_app/middleware/auth.js @@ -0,0 +1,18 @@ +const jwt = require("jsonwebtoken") + +const verifyToken=(req,res,next)=>{ + try{ + const token=req.headers["x-access-token"]; + if(!token) + return res.status(403).send("Auth token is missing, restricted access"); + + const decoded=jwt.verify(token,process.env.TOKEN_KEY); + req.userId=decoded.userId + req.email=decoded.email + }catch(err){ + return res.status(403).json(err); + } + return next(); +} + +module.exports = verifyToken \ No newline at end of file diff --git a/Pradyuman_Agrawal/teams_app/middleware/utils.js b/Pradyuman_Agrawal/teams_app/middleware/utils.js new file mode 100644 index 00000000..236ea271 --- /dev/null +++ b/Pradyuman_Agrawal/teams_app/middleware/utils.js @@ -0,0 +1,22 @@ +const requestLogger = (request,response,next)=>{ + console.log("\n\n-------------------------------------------------"); + console.log("request method: "+ request.method); + console.log("request path: "+ request.path); + console.log("request body:"); + console.log(request.body); + console.log("--------------------------------------------------"); + next(); +}; +const unknownEndpoint = (req,res)=>{ + return res.status(404).send({error: 'unknown end point'}); +}; +const errorHandler = (err,req,res,next)=>{ + + console.log(err); + next(); +}; +module.exports = { + requestLogger, + unknownEndpoint, + errorHandler +}; diff --git a/Pradyuman_Agrawal/teams_app/models/meetings.js b/Pradyuman_Agrawal/teams_app/models/meetings.js new file mode 100644 index 00000000..70fdc91b --- /dev/null +++ b/Pradyuman_Agrawal/teams_app/models/meetings.js @@ -0,0 +1,188 @@ +const pool = require("../config/db") + +const Meeting = function(meeting){ + this.creatorId = meeting.creatorId; + this.startTime = meeting.startTime; + this.endTime = meeting.endTime; + this.description=meeting.description; + this.members=meeting.members; + this.inviteLinkAccess=meeting.inviteLinkAccess; +} + + +Meeting.create = async (newMeeting) => { + //console.log(newMeeting); + const resultObj ={...newMeeting}; + const {creatorId,startTime,endTime,description,members,inviteLinkAccess}=newMeeting; + try{ + const res = await pool.promise("INSERT INTO meetings SET ?; ", { creatorId: creatorId, startTime: startTime,endTime:endTime,description:description,inviteLinkAccess:inviteLinkAccess}); + console.log("meeting created",{...newMeeting}); + resultObj.id=res.insertId; + let promises=[] + members.forEach(memberId => { + promises.push(pool.promise("INSERT INTO meetingMembers SET ?; ", { meetingId: resultObj.id, userId:memberId })) + }); + + await Promise.all(promises); + return resultObj; + } + catch(err){ + console.log("error: ",err); + throw err; + } +}; + +// Meeting.getAllMeeting = async () => { +// try{ +// const res = await pool.promise("Select * from meetings natural join meetingMembers ORDER BY meetings.meetingId",[]); +// return res; +// } +// catch(err){ +// console.log("error: ",err); +// throw err; +// } +// }; + +Meeting.getAllMeeting = async (queryArgs) => { + let sqlQuery="SELECT * FROM meetings NATURAL JOIN meetingMembers" + if(queryArgs.sortBy){ + sqlQuery+=" ORDER BY " + queryArgs.sortBy + if(queryArgs.order&&queryArgs.order.toUpperCase().localeCompare("DESC")==0) + sqlQuery+=" DESC" + } + try{ + const res = await pool.promise(sqlQuery); + return res; + } + catch(err){ + console.log("error: ",err); + throw err; + } +}; + +Meeting.findMeetingById = async (meetingId) => { + try{ + const res = await pool.promise("Select * from meetings m natural join meetingMembers where m.meetingId = ? ORDER BY m.meetingId",[meetingId]); + return res; + } + catch(err){ + console.log("error: ",err); + throw err; + } +}; + +Meeting.findcreatorIdByMeetingId = async (meetingId) => { + try{ + const res = await pool.promise("Select creatorId from meetings where meetingId = ?",[meetingId]); + return res; + } + catch(err){ + console.log("error: ",err); + throw err; + } +}; + +Meeting.findMeetingByCreatorId = async (creatorId) => { + try{ + const res = await pool.promise("Select * from meetings m natural join meetingMembers where m.creatorId = ? ORDER BY m.meetingId",[creatorId]); + return res; + } + catch(err){ + console.log("error: ",err); + throw err; + } +}; + +Meeting.findMeetingByMemberId = async (userId) => { + try{ + const res = await pool.promise("Select * from meetings m natural join meetingMembers where m.meetingId in (select meetingId from meetingMembers where userId = ?) ORDER BY startTime",[userId]); + return res; + } + catch(err){ + console.log("error: ",err); + throw err; + } +}; + + +Meeting.updateMeetingById = async (meetingId,updateInfo) => { + var sql=`UPDATE meetings SET `; + var args=[] + if(updateInfo.startTime){ + sql+=`startTime=? ,`; + args.push(updateInfo.startTime); + } + if(updateInfo.endTime){ + sql+=`endTime=? `; + args.push(updateInfo.endTime); + } + if(updateInfo.description){ + sql+=`description=? `; + args.push(updateInfo.description); + } + if(updateInfo.inviteLinkAccess){ + sql+=`inviteLinkAccess=? `; + args.push(updateInfo.inviteLinkAccess); + } + sql+= `WHERE meetingId=?`; + args.push(meetingId); + + try{ + const res = await pool.promise(sql,args); + return {user:res} + } + catch(err){ + console.log("error: ",err); + throw err; + } + +}; + +Meeting.deleteMeetingById = async (meetingId) => { + try{ + await pool.promise("Delete from meetingMembers where meetingId = ?",[meetingId]); + const res = await pool.promise("Delete from meetings where meetingId = ?",[meetingId]); + return res; + } + catch(err){ + console.log("error: ",err); + throw err; + } +}; + +Meeting.dropOffMeetingById= async (meetingId,userId) => { + try{ + + console.log([meetingId,userId]); + const res = await pool.promise("Delete from meetingMembers where (meetingId = ?) AND (userId = ?)",[meetingId,userId]); + return res; + } + catch(err){ + console.log("error: ",err); + throw err; + } +}; + +Meeting.createInviteLink = async (inviteLink,meetingId) => { + try{ + const res = await pool.promise("update meetings set inviteLink = ? where meetingId =?",[inviteLink,meetingId]); + return res; + } + catch(err){ + console.log("error: ",err); + throw err; + } +}; + +Meeting.joinMeetingbyId = async (userId,meetingId) => { + try{ + const res = await pool.promise("INSERT INTO meetingMembers SET ?; ", { meetingId: meetingId, userId:userId }); + return res; + } + catch(err){ + console.log("error: ",err); + throw err; + } +}; + +module.exports = Meeting; \ No newline at end of file diff --git a/Pradyuman_Agrawal/teams_app/models/users.js b/Pradyuman_Agrawal/teams_app/models/users.js new file mode 100644 index 00000000..c8e72ede --- /dev/null +++ b/Pradyuman_Agrawal/teams_app/models/users.js @@ -0,0 +1,106 @@ +const pool = require("../config/db") + +const User = function(user){ + this.email = user.email; + this.password = user.password; + this.name=user.name; +} + +User.create = async (newUser) => { + try{ + const res = await pool.promise("INSERT INTO users SET ?",newUser); + console.log("user created",{...newUser}); + const resultObj={id:res.insertId,...newUser}; + return resultObj; + } + catch(err){ + console.log("error: ",err); + throw err; + } + +}; + +User.getAllUser =async () => { + try{ + const res = await pool.promise("Select * from users ",[]); + console.log("All users info sent"); + return {users:res}; + } + catch(err){ + console.log("error: ",err); + throw err; + } +}; + +User.findUserById = async(userId) => { + try{ + const res = await pool.promise("Select * from users where userId = ?",userId); + if(res.length){ + console.log("user found with userID",userId); + return {user:res[0]}; + } + else{ + return {user:[]}; + } + } + catch(err){ + console.log("error: ",err); + throw err; + } +}; + +User.findUserByEmailId =async (email) => { + try{ + const res = await pool.promise("Select * from users where email = ?",email); + if(res.length){ + console.log("user found with email",email); + return {user:res[0]}; + } + else{ + return {user:[]}; + } + } + catch(err){ + console.log("error: ",err); + throw err; + } +}; + +User.updateUserById =async (userId,updateInfo,) => { + var sql=`UPDATE users SET `; + var arg=[] + if(updateInfo.name){ + sql+=`name=? ,`; + arg.push(updateInfo.name); + } + if(updateInfo.password){ + sql+=`password=? `; + arg.push(updateInfo.password); + } + sql+= `WHERE userId=?`; + arg.push(userId); + + try{ + const res = await pool.promise(sql,arg); + console.log("user info update where userId is",userId); + return {user:res} + } + catch(err){ + console.log("error: ",err); + throw err; + } +}; + +User.deleteUserById = async (userId) => { + try{ + const res = await pool.promise("Delete from users where userId = ?",userId); + console.log("user deleted with userId",userId); + return {user:res} + } + catch(err){ + console.log("error: ",err); + throw err; + } +}; + +module.exports = User; \ No newline at end of file diff --git a/Pradyuman_Agrawal/teams_app/package.json b/Pradyuman_Agrawal/teams_app/package.json new file mode 100644 index 00000000..fdfb09da --- /dev/null +++ b/Pradyuman_Agrawal/teams_app/package.json @@ -0,0 +1,23 @@ +{ + "name": "teams_app", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "bcryptjs": "^2.4.3", + "cors": "^2.8.5", + "cryptr": "^6.0.2", + "dotenv": "^10.0.0", + "express": "^4.17.2", + "jsonwebtoken": "^8.5.1", + "mysql": "^2.18.1" + }, + "devDependencies": { + "nodemon": "^2.0.15" + } +} diff --git a/Pradyuman_Agrawal/teams_app/routes/auth.js b/Pradyuman_Agrawal/teams_app/routes/auth.js new file mode 100644 index 00000000..fd2fa3c0 --- /dev/null +++ b/Pradyuman_Agrawal/teams_app/routes/auth.js @@ -0,0 +1,7 @@ +const authRouter = require('express').Router(); +const auth = require("../controllers/auth.js"); + +authRouter.post("/login",auth.login); +authRouter.get("/logout",auth.logout); + +module.exports = authRouter \ No newline at end of file diff --git a/Pradyuman_Agrawal/teams_app/routes/meetings.js b/Pradyuman_Agrawal/teams_app/routes/meetings.js new file mode 100644 index 00000000..d973dd8a --- /dev/null +++ b/Pradyuman_Agrawal/teams_app/routes/meetings.js @@ -0,0 +1,15 @@ +const meetingRouter = require('express').Router(); +const meetings = require("../controllers/meetings.js"); + +meetingRouter.post("/",meetings.create); +meetingRouter.get("/",meetings.getAllMeeting); +meetingRouter.get("/:id",meetings.findMeetingById); +meetingRouter.get("/withCreatorId/:userId",meetings.findMeetingByCreatorId); +meetingRouter.get("/withMemberId/:userId",meetings.findMeetingByMemberId); +meetingRouter.put("/:id",meetings.updateMeetingById); +meetingRouter.delete("/:id",meetings.deleteMeetingById); +meetingRouter.delete("/dropoff/:id",meetings.dropOffMeetingById); + +meetingRouter.get("/creatInviteLink/:id",meetings.createInviteLink); +meetingRouter.get("/joinWithInviteLink/:encryptedMeetingId",meetings.joinMeetingbyId); +module.exports = meetingRouter; \ No newline at end of file diff --git a/Pradyuman_Agrawal/teams_app/routes/users.js b/Pradyuman_Agrawal/teams_app/routes/users.js new file mode 100644 index 00000000..7a851e2c --- /dev/null +++ b/Pradyuman_Agrawal/teams_app/routes/users.js @@ -0,0 +1,10 @@ +const userRouter = require('express').Router(); +const users = require("../controllers/users.js"); + +userRouter.post("/",users.create); +userRouter.get("/",users.getAllUser); +userRouter.get("/:id",users.findUserById); +userRouter.put("/:id",users.updateUserById); +userRouter.delete("/:id",users.deleteUserById); + +module.exports = userRouter; \ No newline at end of file diff --git a/Pradyuman_Agrawal/teams_app/server.js b/Pradyuman_Agrawal/teams_app/server.js new file mode 100644 index 00000000..d976fb93 --- /dev/null +++ b/Pradyuman_Agrawal/teams_app/server.js @@ -0,0 +1,32 @@ +const express = require("express"); +require("dotenv").config(); +const cors = require("cors"); + +const userRouter=require("./routes/users") +const authRouter=require("./routes/auth") +const meetingRouter=require("./routes/meetings") + +const middleware_utils = require('./middleware/utils'); +const auth =require("./middleware/auth") + +const app = express(); + +var corsOptions = { + origin:"*" +} + +app.use(cors(corsOptions)); +app.use(express.json()); +app.use(middleware_utils.requestLogger); + +app.use('/users', userRouter); +app.use('/auth', authRouter); +app.use('/meetings',auth,meetingRouter); + +app.use(middleware_utils.unknownEndpoint); +app.use(middleware_utils.errorHandler); + +const PORT = process.env.PORT||3000 +app.listen(PORT,() => { + console.log(`server running on port: ${PORT}`); +}); \ No newline at end of file