coders gyan(rest api) ---> book library(1.2)
api creation —>(user —>register and login)
postman—> elib(collection)—>user(folder)—>Register
Register
—> post —> localhost:5513/api/users/register
—>body—>raw—>json
{
"name":"",
"email":"",
"password":""
}
feature wise seperation of code
// src/user/userRouter.ts
import express from "express";
import { createUser, loginUser } from "./userController";
const userRouter = express.Router();
// routes
userRouter.post("/register", createUser);
userRouter.post("/login", loginUser);
export default userRouter;
// app.ts
import express, { NextFunction, Request, Response } from "express";
import globalErrorHandler from "./middlewares/globalErrorHandler";
import userRouter from "./user/userRouter";
import { config } from "./config/config";
const app = express();
app.use(express.json()); // help to parse data(sent from client/user) from req.body
// Routes
// Http methods: GET, POST, PUT, PATCH, DELETE
app.get("/", (req, res, next) => {
res.json({ message: "Welcome to elib apis" });
});
app.use("/api/users", userRouter);
// Global error handler
app.use(globalErrorHandler);
export default app;
// src/user/userTypes.ts
export interface User {
_id: string;
name: string;
email: string;
password: string;
}
// src/user/userModel.ts
import mongoose from "mongoose";
import { User } from "./userTypes";
const userSchema = new mongoose.Schema<User>(
{
name: {
type: String,
required: true,
},
email: {
type: String,
unique: true,
required: true,
},
password: {
type: String,
required: true,
},
},
{ timestamps: true }
);
// default collection in plural and converted into smallcase-->(User -> users)
export default mongoose.model<User>("User", userSchema);
npm i bcrypt # to hash password before storing to db
npm i -D @types/bcrypt
npm i jsonwebtoken # to create token, only token user will be able to access data and certain feature
npm i -D @types/jsonwebtoken
// src/user/userController.ts
import { NextFunction, Request, Response } from "express";
import createHttpError from "http-errors";
import bcrypt from "bcrypt";
import userModel from "./userModel";
import { sign } from "jsonwebtoken";
import { config } from "../config/config";
import { User } from "./userTypes";
const createUser = async (req: Request, res: Response, next: NextFunction) => {
const { name, email, password } = req.body;
// Validation
if (!name || !email || !password) {
const error = createHttpError(400, "All fields are required");
return next(error);
}
// Database call.
try {
const user = await userModel.findOne({ email });
if (user) {
const error = createHttpError(
400,
"User already exists with this email."
);
return next(error);
}
} catch (err) {
return next(createHttpError(500, "Error while getting user"));
}
/// password -> hash
// password + salt (salt No) --> random string
const hashedPassword = await bcrypt.hash(password, 10);
let newUser: User;
try {
newUser = await userModel.create({
name,
email,
password: hashedPassword,
});
} catch (err) {
return next(createHttpError(500, "Error while creating user."));
}
try {
// Token generation JWT
const token = sign({ sub: newUser._id }, config.jwtSecret as string, {
expiresIn: "7d",
algorithm: "HS256",
});
// Response
res.status(201).json({ accessToken: token });
} catch (err) {
return next(createHttpError(500, "Error while signing the jwt token"));
}
};
const loginUser = async (req: Request, res: Response, next: NextFunction) => {
const { email, password } = req.body;
if (!email || !password) {
return next(createHttpError(400, "All fields are required"));
}
// todo: wrap in try catch.
const user = await userModel.findOne({ email });
if (!user) {
return next(createHttpError(404, "User not found."));
}
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return next(createHttpError(400, "Username or password incorrect!"));
}
// todo: handle errors
// Create accesstoken
const token = sign({ sub: user._id }, config.jwtSecret as string, {
expiresIn: "7d",
algorithm: "HS256",
});
res.json({ accessToken: token });
};
export { createUser, loginUser };
Login
—> post —> localhost:5513/api/users/login
—>body—>raw—>json
{
"email":"",
"password":""
}