forked from iiitl/MERN_AUTH
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 50a9b8b
Showing
37 changed files
with
32,052 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
## Description | ||
|
||
This is MERN auth application | ||
|
||
|
||
It includes the following: | ||
|
||
- Backend API with Express & MongoDB | ||
- Routes for auth, logout, register. | ||
- JWT authentication stored in HTTP-only cookie | ||
- Protected routes and endpoints | ||
- Custom middleware to check JSON web token and store in cookie | ||
- React frontend to register, login, logout. | ||
|
||
## Usage | ||
|
||
- Create a MongoDB database and obtain your `MongoDB URI` - [MongoDB Atlas](https://www.mongodb.com/cloud/atlas/register) | ||
|
||
### Env Variables | ||
|
||
Rename the `.env.example` file to `.env` and add the following | ||
|
||
``` | ||
PORT = 4000 | ||
MONGO_URI = your mongodb uri | ||
JWT_SECRET = 'abc123' | ||
``` | ||
|
||
Change the JWT_SECRET to what you want | ||
|
||
### Install Dependencies (frontend & backend) | ||
|
||
``` | ||
cd backend | ||
npm install | ||
cd frontend | ||
npm install | ||
``` | ||
|
||
### Run | ||
|
||
``` | ||
# Run frontend (:3000) & backend (:4000) | ||
npm start | ||
``` | ||
|
||
## Build & Deploy | ||
|
||
``` | ||
# Create frontend prod build | ||
cd frontend | ||
npm run build | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
/node_modules | ||
.env |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
const Task = require('../models/taskModel') | ||
const mongoose = require('mongoose') | ||
|
||
// get all tasks | ||
const getTasks = async (req, res) => { | ||
const user_id = req.user._id | ||
|
||
const tasks = await Task.find({user_id}) | ||
|
||
res.status(200).json(tasks) | ||
} | ||
|
||
// get a single task | ||
const getTask = async (req, res) => { | ||
const { id } = req.params | ||
|
||
if (!mongoose.Types.ObjectId.isValid(id)) { | ||
return res.status(404).json({error: 'No such task'}) | ||
} | ||
|
||
const task = await Task.findById(id) | ||
|
||
if (!task) { | ||
return res.status(404).json({error: 'No such task'}) | ||
} | ||
|
||
res.status(200).json(task) | ||
} | ||
|
||
|
||
// create new task | ||
const createTask = async (req, res) => { | ||
const {title, description, progress} = req.body | ||
|
||
let emptyFields = [] | ||
|
||
if(!title) { | ||
emptyFields.push('title') | ||
} | ||
if(!description) { | ||
emptyFields.push('description') | ||
} | ||
if(!progress) { | ||
emptyFields.push('progress') | ||
} | ||
if(emptyFields.length > 0) { | ||
return res.status(400).json({ error: 'Please fill in all the fields', emptyFields }) | ||
} | ||
|
||
// add doc to db | ||
try { | ||
const user_id = req.user._id | ||
const task = await Task.create({title, description, progress, user_id}) | ||
res.status(200).json(task) | ||
} catch (error) { | ||
res.status(400).json({error: error.message}) | ||
} | ||
} | ||
|
||
// delete a task | ||
const deleteTask = async (req, res) => { | ||
const { id } = req.params | ||
|
||
if (!mongoose.Types.ObjectId.isValid(id)) { | ||
return res.status(404).json({error: 'No such task'}) | ||
} | ||
|
||
const task = await Task.findOneAndDelete({_id: id}) | ||
|
||
if (!task) { | ||
return res.status(400).json({error: 'No such task'}) | ||
} | ||
|
||
res.status(200).json(task) | ||
} | ||
|
||
// update a task | ||
const updateTask = async (req, res) => { | ||
const { id } = req.params | ||
|
||
if (!mongoose.Types.ObjectId.isValid(id)) { | ||
return res.status(404).json({error: 'No such task'}) | ||
} | ||
|
||
const task = await Task.findOneAndUpdate({_id: id}, { | ||
...req.body | ||
}) | ||
|
||
if (!task) { | ||
return res.status(400).json({error: 'No such task'}) | ||
} | ||
|
||
res.status(200).json(task) | ||
} | ||
|
||
|
||
module.exports = { | ||
getTasks, | ||
getTask, | ||
createTask, | ||
deleteTask, | ||
updateTask | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
const User = require('../models/userModel') | ||
const jwt = require('jsonwebtoken') | ||
|
||
const createToken = (_id) => { | ||
return jwt.sign({_id}, process.env.SECRET, { expiresIn: '3d' }) | ||
} | ||
|
||
// login a user | ||
const loginUser = async (req, res) => { | ||
const {email, password} = req.body | ||
|
||
try { | ||
const user = await User.login(email, password) | ||
|
||
// create a token | ||
const token = createToken(user._id) | ||
|
||
res.status(200).json({email, token}) | ||
} catch (error) { | ||
res.status(400).json({error: error.message}) | ||
} | ||
} | ||
|
||
// signup a user | ||
const signupUser = async (req, res) => { | ||
const {email, password} = req.body | ||
|
||
try { | ||
const user = await User.signup(email, password) | ||
|
||
// create a token | ||
const token = createToken(user._id) | ||
|
||
res.status(200).json({email, token}) | ||
} catch (error) { | ||
res.status(400).json({error: error.message}) | ||
} | ||
} | ||
|
||
module.exports = { signupUser, loginUser } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
const jwt = require('jsonwebtoken') | ||
const User = require('../models/userModel') | ||
|
||
const requireAuth = async (req, res, next) => { | ||
// verify user is authenticated | ||
const { authorization } = req.headers | ||
|
||
if (!authorization) { | ||
return res.status(401).json({error: 'Authorization token required'}) | ||
} | ||
|
||
const token = authorization.split(' ')[1] | ||
|
||
try { | ||
const { _id } = jwt.verify(token, process.env.SECRET) | ||
|
||
req.user = await User.findOne({ _id }).select('_id') | ||
next() | ||
|
||
} catch (error) { | ||
console.log(error) | ||
res.status(401).json({error: 'Request is not authorized'}) | ||
} | ||
} | ||
|
||
module.exports = requireAuth |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
const mongoose = require('mongoose') | ||
|
||
const Schema = mongoose.Schema | ||
|
||
const taskSchema = new Schema({ | ||
title: { | ||
type: String, | ||
required: true | ||
}, | ||
description: { | ||
type: String, | ||
required: true | ||
}, | ||
progress: { | ||
type: Number, | ||
required: true | ||
}, | ||
user_id: { | ||
type: String, | ||
required: true | ||
} | ||
}, { timestamps: true }) | ||
|
||
module.exports = mongoose.model('Task', taskSchema) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
const mongoose = require('mongoose') | ||
const bcrypt = require('bcrypt') | ||
const validator = require('validator') | ||
|
||
const Schema = mongoose.Schema | ||
|
||
const userSchema = new Schema({ | ||
email: { | ||
type: String, | ||
required: true, | ||
unique: true | ||
}, | ||
password: { | ||
type: String, | ||
required: true | ||
} | ||
}) | ||
|
||
// static signup method | ||
userSchema.statics.signup = async function(email, password) { | ||
|
||
// validation | ||
if (!email || !password) { | ||
throw Error('All fields must be filled') | ||
} | ||
if (!validator.isEmail(email)) { | ||
throw Error('Email not valid') | ||
} | ||
if (!validator.isStrongPassword(password)) { | ||
throw Error('Password not strong enough') | ||
} | ||
|
||
const exists = await this.findOne({ email }) | ||
|
||
if (exists) { | ||
throw Error('Email already in use') | ||
} | ||
|
||
const salt = await bcrypt.genSalt(10) | ||
const hash = await bcrypt.hash(password, salt) | ||
|
||
const user = await this.create({ email, password: hash }) | ||
|
||
return user | ||
} | ||
|
||
// static login method | ||
userSchema.statics.login = async function(email, password) { | ||
|
||
if (!email || !password) { | ||
throw Error('All fields must be filled') | ||
} | ||
|
||
const user = await this.findOne({ email }) | ||
if (!user) { | ||
throw Error('Incorrect email') | ||
} | ||
|
||
const match = await bcrypt.compare(password, user.password) | ||
if (!match) { | ||
throw Error('Incorrect password') | ||
} | ||
|
||
return user | ||
} | ||
|
||
module.exports = mongoose.model('User', userSchema) |
Oops, something went wrong.