├── .gitignore ├── .gitattributes ├── config └── mongoConfig.js ├── routes ├── usersRouter.js ├── blogsRouter.js └── authRouter.js ├── README.md ├── models ├── userSchema.js └── blogSchema.js ├── package.json └── server.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | node_modules/ 3 | .env -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /config/mongoConfig.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | 3 | module.exports = async () => { 4 | try { 5 | await mongoose.connect(process.env.MONGODB_URI) 6 | mongoose.connection 7 | console.log('MongoDB Connected'); 8 | } catch (error) { 9 | console.log(error); 10 | } 11 | } -------------------------------------------------------------------------------- /routes/usersRouter.js: -------------------------------------------------------------------------------- 1 | /* 2 | const express = require('express') 3 | 4 | 5 | const UserModel = require('../models/userSchema') 6 | 7 | const router = express.Router() 8 | 9 | router.post('/', async (req, res) => { 10 | const userData = req.body 11 | try { 12 | const user = await UserModel.findOne({email: userData.email}) 13 | } catch (error) { 14 | console.log(error); 15 | res.status(500).json('Server Error') 16 | } 17 | } ) 18 | */ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Blog API 2 | 3 | - This is an example of a Blog API. 4 | 5 | - The application is contained within "BLOGAPI" folder. 6 | 7 | ### Install 8 | 9 | - Doesn't need installation 10 | 11 | ### Run app 12 | 13 | - Install and launch 'Postman Application'. 14 | 15 | - Use command "nodemon server.js" in VS Code. 16 | 17 | ### NPM packages used 18 | 19 | - "bcrypt", 20 | "dotenv", 21 | "express", 22 | "express-validator", 23 | "helmet", 24 | "jsonwebtoken", 25 | "mongoose", 26 | "morgan" 27 | -------------------------------------------------------------------------------- /models/userSchema.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | const userSchema = mongoose.Schema({ 3 | username: { 4 | type: String, 5 | required: true, 6 | unique: true 7 | }, 8 | 9 | email: { 10 | type: String, 11 | required: true, 12 | unique: true 13 | }, 14 | 15 | birthday: { 16 | type: Date, 17 | required: true 18 | }, 19 | 20 | age: { 21 | type: Number 22 | }, 23 | 24 | password: { 25 | type: String, 26 | required: true 27 | } 28 | 29 | }) 30 | 31 | module.exports = mongoose.model('User', userSchema) -------------------------------------------------------------------------------- /models/blogSchema.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | 3 | const blogSchema = mongoose.Schema({ 4 | 5 | created_by: { 6 | type: String, 7 | required: true 8 | }, 9 | 10 | created_at: { 11 | type: Date, 12 | default: Date.now(), 13 | required: true 14 | }, 15 | 16 | blog_title: { 17 | type: String, 18 | required: true 19 | }, 20 | 21 | blog_content: { 22 | type: String, 23 | required: true 24 | }, 25 | 26 | private: { 27 | type: Boolean, 28 | required: true 29 | } 30 | 31 | }) 32 | 33 | module.exports = mongoose.model('Blog', blogSchema) -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "blogapi", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node server.js" 9 | }, 10 | "keywords": [], 11 | "author": "Shain Aliiev", 12 | "license": "ISC", 13 | "dependencies": { 14 | "bcrypt": "^5.0.1", 15 | "dotenv": "^16.0.1", 16 | "express": "^4.18.1", 17 | "express-validator": "^6.14.1", 18 | "helmet": "^5.1.0", 19 | "jsonwebtoken": "^8.5.1", 20 | "mongoose": "^6.3.8", 21 | "morgan": "^1.10.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | require('dotenv').config() 3 | const morgan = require('morgan') 4 | 5 | 6 | const mongoConfig = require('./config/mongoConfig') 7 | const authRouter = require('./routes/authRouter') 8 | const blogsRouter = require('./routes/blogsRouter') 9 | // const usersRouter = require('./routes/usersRouter') 10 | 11 | 12 | 13 | const app = express(); 14 | const PORT = process.env.PORT || 2001; 15 | 16 | 17 | app.use(express.json()) 18 | app.use(morgan('dev')) 19 | 20 | // app.use('/users', usersRouter) 21 | app.use('/auth', authRouter) 22 | app.use('/blogs', blogsRouter) 23 | 24 | app.get('/', (req, res) => { 25 | res.status(200).json('Welcome to my API') 26 | }) 27 | 28 | app.listen(PORT, () => { 29 | console.log(`Server is running on PORT ${PORT}`); 30 | mongoConfig() 31 | }) -------------------------------------------------------------------------------- /routes/blogsRouter.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const { model } = require('mongoose') 3 | const BlogModel = require('../models/blogSchema') 4 | 5 | const router = express.Router() 6 | 7 | router.post('/', async (req, res) => { 8 | const blogData = req.body 9 | 10 | try { 11 | const blog = await BlogModel.create(blogData) 12 | res.status(201).json(blog) 13 | } catch (error) { 14 | console.log(error); 15 | res.status(400).json("Bad request") 16 | } 17 | }) 18 | 19 | router.get('/', async (req, res) => { 20 | try { 21 | const blogs = await BlogModel.find() 22 | res.status(200).json(blogs) 23 | } catch (error) { 24 | console.log(error); 25 | } 26 | }) 27 | 28 | router.get('/:id', async (req, res) => { 29 | const id = req.params.id 30 | 31 | try { 32 | const blog = await BlogModel.findById(id) 33 | res.status(200).json(blog) 34 | } catch (error) { 35 | console.log(error); 36 | } 37 | }) 38 | 39 | router.put('/:id', async (req, res) => { 40 | const id = req.params.id 41 | const newBlogData = req.body 42 | try { 43 | const blog = await BlogModel.findByIdAndUpdate(id, newBlogData, { 44 | new: true 45 | }) 46 | res.status(202).json(blog) 47 | } catch (error) { 48 | console.log(error); 49 | } 50 | }) 51 | 52 | router.delete('/:id', async (req, res) => { 53 | const id = req.params.id 54 | 55 | try { 56 | const blog = await BlogModel.findByIdAndDelete(id) 57 | res.status(200).json({ 58 | msg: "Blog was deleted" 59 | }) 60 | } catch (error) { 61 | console.log(error); 62 | } 63 | }) 64 | 65 | module.exports = router -------------------------------------------------------------------------------- /routes/authRouter.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const UserModel = require('../models/userSchema') 3 | 4 | const {check, validationResult} = require("express-validator") 5 | const bcrypt = require('bcrypt') 6 | const jwt = require('jsonwebtoken') 7 | 8 | const router = express.Router() 9 | 10 | router.post('/registration', [ 11 | check('username', "Username is requied!").notEmpty(), 12 | check('email', "Please use a valid email").isEmail(), 13 | check('password', "Please enter a password").notEmpty(), 14 | check("password", "Please enter a password with six or more characters").isLength({ 15 | min: 6 16 | }) 17 | ], async (req,res) => { 18 | const userData = req.body 19 | const errors = validationResult(req) 20 | 21 | if (!errors.isEmpty()) { 22 | return res.json(errors.array()) 23 | } 24 | try { 25 | const userExist = await UserModel.findOne({email: userData.email}) 26 | 27 | if (userExist) { 28 | return res.json({ 29 | msg: 'User already exists!' 30 | }) 31 | } 32 | 33 | 34 | const SALT = await bcrypt.genSalt(10) 35 | const hashedPassword = await bcrypt.hash(userData.password, SALT) 36 | userData.password = hashedPassword 37 | 38 | 39 | const user = await UserModel.create(userData) 40 | 41 | const payload = { 42 | id: user._id, 43 | email: user.email 44 | } 45 | 46 | const TOKEN = jwt.sign(payload, process.env.SECRET_KEY) 47 | 48 | res.status(201).json({ 49 | user:user, 50 | token: TOKEN 51 | }) 52 | 53 | } catch (error) { 54 | console.log(error); 55 | res.status(400).json('Bad request') 56 | } 57 | }) 58 | 59 | router.post('/login',[ 60 | check('email', "Please provide a valid email").isEmail(), 61 | check("password", "Check your password").notEmpty() 62 | ] ,async (req, res) => { 63 | const userData = req.body 64 | const errors = validationResult(req) 65 | 66 | if (!errors.isEmpty()) { 67 | return res.json(errors.array()) 68 | } 69 | 70 | try { 71 | const user = await UserModel.findOne({ 72 | email:userData.email, 73 | // password: userData.password 74 | 75 | }) 76 | 77 | if (!user) { 78 | return res.json('User not found') 79 | } 80 | 81 | 82 | const isMatch = await bcrypt.compare(userData.password, user.password) 83 | 84 | if (!isMatch) { 85 | return res.json('Password is not a match') 86 | } 87 | 88 | const payload = { 89 | id: user._id, 90 | email: user.email 91 | } 92 | 93 | const TOKEN = jwt.sign(payload, process.env.SECRET_KEY) 94 | 95 | res.status(201).json({ 96 | user:user, 97 | token: TOKEN 98 | }) 99 | 100 | } catch (error) { 101 | console.log(error); 102 | res.status(500).json('Server Error') 103 | 104 | } 105 | 106 | 107 | }) 108 | 109 | module.exports = router --------------------------------------------------------------------------------