-
Notifications
You must be signed in to change notification settings - Fork 89
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #54 from therahulchaurasia/issue-53
Done [New API] : User Data #53
- Loading branch information
Showing
20 changed files
with
3,695 additions
and
6 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 |
---|---|---|
@@ -1,7 +1,71 @@ | ||
# **Let's built something new together!** | ||
# Lets build a User Data API using NodeJS, ExpressJS, MongoDB and Mongoose | ||
|
||
| Name of API | Description of API | | ||
|---|---| | ||
|[BASIC CRUD API](https://github.com/developer-student-clubs/APIVerse/tree/master/New_APIs/Demo_CRUD_API)| It explains us how can we perform basic CRUD operations.| | ||
|[MOVIE TV SHOWS API](https://github.com/developer-student-clubs/APIVerse/tree/master/New_APIs/Movie_Tv_Show_API)| Rest API to fetch data of movie and tv-show with filter options of page, limit, search, and type.| | ||
|[JSON API](https://github.com/developer-student-clubs/APIVerse/tree/master/New_APIs/JsonServer_API)| Give Json data of your choice and get all request ready to work by json server.| | ||
## Table of contents | ||
|
||
- [Getting Started](#getting-started) | ||
- [Prerequisites](#prerequisites) | ||
- [Installation](#installation) | ||
- [Built With](#built-with) | ||
- [Author](#author) | ||
|
||
## Getting Started | ||
|
||
### Prerequisites | ||
|
||
- NodeJS | ||
- MongoDB | ||
- Postman | ||
|
||
### Installation | ||
|
||
- Clone the repository | ||
- Type in the following command in the terminal | ||
|
||
```bash | ||
cd UserDataAPI | ||
npm install | ||
``` | ||
|
||
- Create a .env file in the root directory and add the following | ||
- Add your MongoDB connection string and desired port number | ||
|
||
```bash | ||
MONGO_URI = <YOUR_MONGODB_CONNECTION_STRING> | ||
PORT = <YOUR_DESIRED_PORT_NUMBER> | ||
``` | ||
|
||
- Populate the database by running the following command in the terminal | ||
|
||
```bash | ||
node populate.js | ||
``` | ||
|
||
- Run the following command in the terminal | ||
|
||
```bash | ||
npm start | ||
``` | ||
|
||
- Open Postman and test the API by sending requests to the following endpoints | ||
|
||
```bash | ||
GET http://localhost:3000/api/v1/users | ||
POST http://localhost:3000/api/v1/users | ||
GET http://localhost:3000/api/v1/users/:id(enter your own) | ||
PATCH http://localhost:3000/api/v1/users/:id(enter your own) | ||
DELETE http://localhost:3000/api/v1/users/:id(enter your own) | ||
``` | ||
|
||
## Built With | ||
|
||
- [NodeJS](https://nodejs.org/en/) | ||
- [ExpressJS](https://expressjs.com/) | ||
- [MongoDB](https://www.mongodb.com/) | ||
- [Mongoose](https://mongoosejs.com/) | ||
- [Postman](https://www.postman.com/) | ||
- [VS Code](https://code.visualstudio.com/) | ||
- [Git](https://git-scm.com/) | ||
|
||
## Author | ||
|
||
- Github - [therahulchaurasia](https://github.com/therahulchaurasia) |
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 @@ | ||
MONGO_URI = mongodb+srv://<username>:<password>@nodeexpressprojects.ajshdj.mongodb.net/<YOUR_COLLECTION_NAME>?retryWrites=true&w=majority | ||
PORT = Enter a port number or it will use the default 3000 specified in app.js |
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,41 @@ | ||
require("dotenv").config() | ||
require("express-async-errors") | ||
|
||
const express = require("express") | ||
const app = express() | ||
const fileUpload = require("express-fileupload") | ||
|
||
const connectDB = require("./db/connect") | ||
const userRouter = require("./routes/userRoutes") | ||
|
||
const notFoundMiddleware = require("./middleware/not-found") | ||
const errorMiddleware = require("./middleware/error-handler") | ||
|
||
// middleware | ||
app.use(express.json()) | ||
app.use(express.static("./public")) | ||
app.use(fileUpload()) | ||
// routes | ||
|
||
app.get("/", (req, res) => { | ||
res.send('<h1>User Data API </h1><a href="/api/v1/users">User Routes</a>') | ||
}) | ||
|
||
app.use("/api/v1/users", userRouter) | ||
|
||
app.use(notFoundMiddleware) | ||
app.use(errorMiddleware) | ||
|
||
const port = process.env.PORT || 3000 | ||
|
||
const start = async () => { | ||
try { | ||
// connectDB | ||
await connectDB(process.env.MONGO_URI) | ||
app.listen(port, () => console.log(`Server is listening port ${port}...`)) | ||
} catch (error) { | ||
console.log(error) | ||
} | ||
} | ||
|
||
start() |
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,73 @@ | ||
const User = require("../models/User") | ||
const CustomError = require("../errors/index") | ||
|
||
const getAllUsers = async (req, res) => { | ||
const users = await User.find({}) | ||
res.status(200).json({ users, count: users.length }) | ||
} | ||
|
||
const getSingleUser = async (req, res) => { | ||
const { id: userId } = req.params | ||
const user = await User.findOne({ _id: userId }) | ||
if (!user) { | ||
throw new CustomError.NotFoundError(`No user found with the id ${userId}`) | ||
} | ||
res.status(200).json({ user }) | ||
} | ||
|
||
const postUser = async (req, res) => { | ||
const { firstName, lastName, gender, address, timeZone } = req.body | ||
if ((!firstName, !lastName, !address)) { | ||
throw new CustomError.BadRequestError("Please provide valid values") | ||
} | ||
if (!["Male", "Female"].includes(gender)) { | ||
throw new CustomError.BadRequestError("Gender can only be male or female") | ||
} | ||
|
||
// When you create a user you get an image avatar generated using the combination of your firstname, lastname and address | ||
const imageAvatar = Math.ceil(Math.random() * 4) | ||
const image = `https://robohash.org/${firstName.split(" ").join("")}${address | ||
.split(" ") | ||
.join("")}${lastName | ||
.split(" ") | ||
.join("")}.png?size=200x200&set=set${imageAvatar}` | ||
const user = await User.create({ | ||
firstName, | ||
lastName, | ||
gender, | ||
address, | ||
timeZone, | ||
image, | ||
}) | ||
res.status(201).json({ user }) | ||
} | ||
|
||
const updateUser = async (req, res) => { | ||
const { id: userId } = req.params | ||
const user = await User.findOneAndUpdate({ _id: userId }, req.body, { | ||
new: true, | ||
runValidators: true, | ||
}) | ||
if (!user) { | ||
throw new CustomError.NotFoundError(`No user found with the id ${userId}`) | ||
} | ||
res.status(StatusCodes.OK).json({ user }) | ||
} | ||
|
||
const deleteUser = async (req, res) => { | ||
const { id: userId } = req.params | ||
const user = await User.findOne({ _id: userId }) | ||
if (!user) { | ||
throw new CustomError.NotFoundError(`No user found with the id ${userId}`) | ||
} | ||
await user.remove() | ||
res.status(200).json({ msg: `Success! User Removed` }) | ||
} | ||
|
||
module.exports = { | ||
getAllUsers, | ||
getSingleUser, | ||
deleteUser, | ||
postUser, | ||
updateUser, | ||
} |
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,7 @@ | ||
const mongoose = require("mongoose") | ||
|
||
const connectDB = (url) => { | ||
return mongoose.connect(url) | ||
} | ||
|
||
module.exports = connectDB |
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,11 @@ | ||
const { StatusCodes } = require('http-status-codes'); | ||
const CustomAPIError = require('./custom-api'); | ||
|
||
class BadRequestError extends CustomAPIError { | ||
constructor(message) { | ||
super(message); | ||
this.statusCode = StatusCodes.BAD_REQUEST; | ||
} | ||
} | ||
|
||
module.exports = BadRequestError; |
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,12 @@ | ||
const CustomAPIError = require('./custom-api') | ||
const UnauthenticatedError = require('./unauthenticated') | ||
const NotFoundError = require('./not-found') | ||
const BadRequestError = require('./bad-request') | ||
const UnauthorizedError = require('./unauthorized') | ||
module.exports = { | ||
CustomAPIError, | ||
UnauthenticatedError, | ||
NotFoundError, | ||
BadRequestError, | ||
UnauthorizedError, | ||
} |
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,11 @@ | ||
const { StatusCodes } = require('http-status-codes'); | ||
const CustomAPIError = require('./custom-api'); | ||
|
||
class NotFoundError extends CustomAPIError { | ||
constructor(message) { | ||
super(message); | ||
this.statusCode = StatusCodes.NOT_FOUND; | ||
} | ||
} | ||
|
||
module.exports = NotFoundError; |
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,28 @@ | ||
const { StatusCodes } = require('http-status-codes'); | ||
const errorHandlerMiddleware = (err, req, res, next) => { | ||
let customError = { | ||
// set default | ||
statusCode: err.statusCode || StatusCodes.INTERNAL_SERVER_ERROR, | ||
msg: err.message || 'Something went wrong try again later', | ||
}; | ||
if (err.name === 'ValidationError') { | ||
customError.msg = Object.values(err.errors) | ||
.map((item) => item.message) | ||
.join(','); | ||
customError.statusCode = 400; | ||
} | ||
if (err.code && err.code === 11000) { | ||
customError.msg = `Duplicate value entered for ${Object.keys( | ||
err.keyValue | ||
)} field, please choose another value`; | ||
customError.statusCode = 400; | ||
} | ||
if (err.name === 'CastError') { | ||
customError.msg = `No item found with id : ${err.value}`; | ||
customError.statusCode = 404; | ||
} | ||
|
||
return res.status(customError.statusCode).json({ msg: customError.msg }); | ||
}; | ||
|
||
module.exports = errorHandlerMiddleware; |
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,3 @@ | ||
const notFound = (req, res) => res.status(404).send('Route does not exist') | ||
|
||
module.exports = notFound |
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,35 @@ | ||
const mongoose = require("mongoose") | ||
|
||
const UserSchema = new mongoose.Schema( | ||
{ | ||
firstName: { | ||
type: String, | ||
required: [true, "Please provide first name"], | ||
maxlength: 50, | ||
}, | ||
lastName: { | ||
type: String, | ||
required: [true, "Please provide last name"], | ||
maxlength: 50, | ||
}, | ||
gender: { | ||
type: String, | ||
required: [true, "Please provide gender"], | ||
enum: ["Male", "Female"], | ||
}, | ||
address: { | ||
type: String, | ||
required: [true, "Please provide address"], | ||
}, | ||
timeZone: { | ||
type: String, | ||
}, | ||
image: { | ||
type: String, | ||
default: "/uploads/example.jpeg", | ||
}, | ||
}, | ||
{ timestamps: true } | ||
) | ||
|
||
module.exports = mongoose.model("User", UserSchema) |
Oops, something went wrong.