const express = require("express")
const cors = require("cors")
const bcrypt = require("bcrypt")
const jwt = require("jsonwebtoken")
const Sequelize = require("sequelize")
require("dotenv").config()
const PORT = 5050
// Initialize the express app
const app = express()
// Enable CORS
app.use(cors())
// parse application/x-www-form-urlencoded
app.use(express.urlencoded({extended: true}))
// parse application/json
app.use(express.json())
// Connect to the database
const sequelize = new Sequelize(process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASSWORD, {
host: process.env.DB_HOST,
dialect: "mysql",
define: {
underscored: true,
},
})
// Define the User model
const Users = sequelize.define("users", {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
google_id: {
type: Sequelize.STRING,
},
google_token: {
type: Sequelize.STRING,
},
email: {
type: Sequelize.STRING,
unique: true,
},
password: {
type: Sequelize.STRING,
},
fullname: {
type: Sequelize.STRING,
},
created_at: {
type: Sequelize.DATE,
defaultValue: Sequelize.NOW,
},
updated_at: {
type: Sequelize.DATE,
defaultValue: Sequelize.NOW,
},
})
app.post("/register", async (req, res) => {
try {
// Extract email, password, and other user details from the request body
const {email, password, first_name, last_name} = req.body
// Check if a user with the same email already exists
const existingUser = await Users.findOne({where: {email: email}})
if (existingUser) {
return res.status(400).json({message: "A user with this email already exists"})
}
// Hash the user"s password
const hashedPassword = await bcrypt.hash(password, 10)
// Create a new user in the database
const newUser = await Users.create({
email: email,
password: hashedPassword,
first_name: first_name,
last_name: last_name,
})
// Generate a JSON web token with the user"s id and a secret key
const api_token = jwt.sign({id: newUser.id}, process.env.JWT_SECRET)
// Return the JSON web token and a status code of 201 Created
return res.status(201).json({api_token})
} catch (error) {
console.error(error)
// Return a 500 Internal Server Error if there is any error while creating the user
return res.status(500).json({message: "Error creating user. Please try again later."})
}
})
app.post("/login", async (req, res) => {
// Extract email, and password from the request body
const {email, password} = req.body
try {
// Find the user with the same email in the database
const user = await Users.findOne({where: {email: email}})
// Return a 401 Unauthorized if the user with the email is not found or if the password is invalid
if (!user || !bcrypt.compareSync(password, user.password)) {
return res.status(401).json({message: "Invalid email or password"})
}
// Generate a JSON web token with the user"s id and a secret key
const api_token = jwt.sign({id: user.id}, process.env.JWT_SECRET)
// Return the JSON web token and a status code of 200 OK
return res.status(200).json({api_token})
} catch (error) {
console.error(error)
// Return a 500 Internal Server Error if there is any error while logging in
return res.status(500).json({message: "Error logging in. Please try again later."})
}
})
app.post("/verify_token", async (req, res) => {
// Extract token from the request body
const {api_token} = req.body
try {
// Verify the token with a secret key
const decoded = jwt.verify(api_token, process.env.JWT_SECRET)
const user = await Users.findOne({where: {id: decoded.id}})
if (!user) {
return res.status(401).json({message: "Invalid token"})
}
return res.status(200).json({user})
} catch (error) {
console.error(error)
// Return a 401 Unauthorized if the token is invalid or expired
return res.status(401).json({message: "Invalid token"})
}
})
app.use((req, res) => {
res.status(404).json({message: "Not found"})
})
app.listen(PORT, () => {
console.log("Server is running on port ${PORT}.")
})