Skip to content

Commit

Permalink
finished section 7
Browse files Browse the repository at this point in the history
  • Loading branch information
takuyadev committed Nov 4, 2022
1 parent d6f8de3 commit da74a38
Show file tree
Hide file tree
Showing 9 changed files with 465 additions and 13 deletions.
89 changes: 89 additions & 0 deletions controllers/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
const asyncHandler = require('../middleware/async')
const ErrorResponse = require('../utils/errorResponse')
const User = require('../model/User')

// @desc Register user
// @route POST /api/v1/auth/register
// @access Public

exports.register = asyncHandler(async (req, res, next) => {
const { name, email, password, role } = req.body

// Create user
const user = await User.create({
name,
email,
password,
role
})

// Create token
sendTokenResponse(user, 200, res)
})


// @desc Login user
// @route POST /api/v1/auth/register
// @access Public

exports.login = asyncHandler(async (req, res, next) => {
const { email, password } = req.body

// Validate email & password
if (!email || !password) {
return next(new ErrorResponse('Please provide an email and password', 400))
}

// Check for user
const user = await User.findOne({ email }).select('+password')

if (!user) {
return next(new ErrorResponse('Invalid credentials', 401))
}

// Check if password matches
const isMatch = await user.matchPassword(password)

if (!isMatch) {
return next(new ErrorResponse('Invalid credentials', 401))
}

sendTokenResponse(user, 200, res)
})


// Get token from model, create cookie and send response
const sendTokenResponse = (user, statusCode, res) => {
// Create token
const token = user.getSignedJwtToken()

const options = {
expires: new Date(Date.now() + process.env.JWT_COOKIE_EXPIRE * 24 * 60 * 60 * 1000),
httpOnly: true
}

if (process.env.NODE_ENV === 'production') {
options.secure = true
}

res
.status(statusCode)
.cookie('token', token, options)
.json({
success: true,
token
})
}


// @desc Get current logged in user
// @route POST /api/v1/auth/me
// @access Private
exports.getMe = asyncHandler(async (req, res, next) => {
const user = await User.findById(req.user.id)

res.status(200).json({
success: true,
data: user
})
})
54 changes: 54 additions & 0 deletions middleware/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const jwt = require('jsonwebtoken')
const asyncHandler = require('./async')
const ErrorResponse = require('../utils/errorResponse')
const User = require('../model/User')

// Protect routes
exports.protect = asyncHandler(async (req, res, next) => {
let token
console.log(req.headers.authorization)

if (
req.headers.authorization &&
req.headers.authorization.startsWith('Bearer')
) {
// Set token from Bearer token in header
token = req.headers.authorization.split(' ')[1];
}

// Set token from cookie

// else if (req.cookies.token) {
// token = req.cookies.token
// }

// Make sure token exists

if (!token) {
return next(new ErrorResponse(`Not authorized to access this route`, 404))
}

try {
// Verify token
const decoded = jwt.verify(token, process.env.JWT_SECRET)

console.log(decoded)

req.user = await User.findById(decoded._id)

next();
} catch (err) {
return next(new ErrorResponse(`Not authorized to access this route`, 404))
}
})


// Grant access to specific roles
exports.authorize = (...roles) => {
return (req, res, next) => {
if (!roles.includes(req.user.role)) {
return next(new ErrorResponse(`User role ${req.user.role} is unauthorized to access this route`, 403))
}
next()
}
}
56 changes: 56 additions & 0 deletions model/User.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
const mongoose = require('mongoose')
const bcrypt = require('bcryptjs')
const jwt = require('jsonwebtoken')
const UserSchema = new mongoose.Schema({
name: {
type: String,
required: [true, 'Please add a name']
},
email: {
type: String,
required: [true, 'Please add an email'],
unique: true,
match: [
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
"Please use a valid email address"
]
},
role: {
type: String,
enum: ['user', 'publisher'],
default: 'user'
},
password: {
type: String,
required: [true, 'Please enter a password'],
minlength: 6,
select: false,
},
resetPasswordToken: String,
resetPasswordExpire: Date,
createdAt: {
type: Date,
default: Date.now
}
})

// Encrypt password using bcrypt
UserSchema.pre('save', async function () {
const salt = await bcrypt.genSalt(10)
this.password = await bcrypt.hash(this.password, salt)
})

// Sign JWT and return
UserSchema.methods.getSignedJwtToken = function () {
return jwt.sign({ _id: this._id }, process.env.JWT_SECRET, {
expiresIn: process.env.JWT_EXPIRE
})
}

// Match user entered password to hashed password in database
UserSchema.methods.matchPassword = async function (enteredPassword) {
return await bcrypt.compare(enteredPassword, this.password)
}


module.exports = mongoose.model('User', UserSchema)
Loading

0 comments on commit da74a38

Please sign in to comment.