Привет всем, добро пожаловать в сквозной проект полного стека (бэкэнд, фронтенд) с искусственным интеллектом и машинным обучением и серией этических хакеров. В этом посте мы собираемся построить бэкэнд проекта.

Для создания внутреннего API я буду использовать Express.js, который представляет собой инфраструктуру Node.js, предназначенную для создания RESTFUL API. Чтобы упростить задачу, давайте разобьем проект на части и запишем шаги в точечной форме.

Я уже объяснял проект в посте основной серии. Проверьте это.



О проекте — (внутренняя часть)

Наша цель — создать RESTFUL API с потрясающим количеством функций, которые будут иметь современное приложение. Этот API основан на блогах. Где пользователи смогут зарегистрироваться и войти в свою учетную запись и создать сообщение, отредактировать сообщение, если они хотят улучшить свое сообщение, а также удалить его, если оно им не нравится. Также вы сможете просматривать и читать сообщения других пользователей и лайкать сообщение, если оно вам нравится, а также подписываться на пользователя, если вы хотите обновлять его.

Что вы узнаете?

  • Структура файлов и папок
  • Настроить переменные среды
  • Подключить и создать схемы базы данных
  • Заполнение схем базы данных с использованием виртуальных машин мангуста
  • Создать экспресс-сервер
  • Создавайте различные типы маршрутов
  • Обработка аутентификации
  • Логика и реализация потрясающих функций
  • Тестировать API

Функции которые мы собираемся реализовать:

  • аутентификация — пользователь может войти и зарегистрироваться
    — пользователь сможет зарегистрироваться, а затем войти в систему
    — просмотреть любой профиль пользователя — аутентификация не требуется
    — подтвердить вход пользователя — требуется аутентификация
  • CRUD — пользователи смогут создавать, читать, обновлять и удалять сообщения
    — пользователи могут просматривать все сообщения — аутентификация не требуется
    — пользователи могут фильтровать сообщения по подписчикам — требуется аутентификация
    — пользователь может создать новую публикацию — требуется аутентификация
    — пользователь может редактировать свою публикацию — требуется аутентификация
    — пользователь может удалить свою публикацию — требуется аутентификация
  • Подписаться и отписаться от целевого пользователя — требуется аутентификация
  • Ссылка и в отличие от поста — требуется аутентификация

Примечание. Я буду улучшать этот API по мере продвижения вперед. Будут добавлены дополнительные функции, и мы сделаем весь API более безопасным, добавив больше периметров безопасности и исправив существующие ошибки, как только мы доработаем хакерскую часть ряд. На данный момент основной целью является создание версии 1 внутреннего API.

Этапы, которым мы будем следовать:

Установите необходимые компоненты и настройте среду

Прежде чем мы начнем, мы должны установить необходимые программы и настроить среду. На этом этапе нам нужно убедиться в трех вещах: установлена ​​ли наша среда выполнения, доступна ли база данных и есть ли способ протестировать API.

В качестве среды выполнения мы будем использовать Node.js, поэтому убедитесь, что он установлен, его можно скачать здесь: https://nodejs.org.

Для тестирования API мы будем использовать почтальонов, которые вы можете получить здесь: https://www.postman.com. также у вас должен быть редактор кода, который я использую vscode, который я предпочитаю использовать, вы можете получить его здесь: https://code.visualstudio.com

И в качестве базы данных мы будем использовать атлас MongoDB, поэтому нам не нужно ничего устанавливать, но вам нужно создать учетную запись и получить URI подключения.

Шаги по настройке базы данных:

  1. Посетите https://www.mongodb.com/cloud/atlas/register и создайте бесплатную учетную запись. И завершите процесс регистрации, выбрав модель бесплатной общей подписки.
  2. Шаг 1 направит вас на страницу Создание общего кластера, здесь выберите AWS › выберите любой регион› оставьте оба Cluster Tire и Настройки добавления и перейдите к Имя кластера, которое по умолчанию равно 'Cluster0', и я оставлю его как есть и создам кластер.
  3. Шаг 2 приведет вас на страницу быстрого запуска. Здесь вы должны указать имя пользователя и пароль и нажать «Создать пользователя».
  4. Далее необходимо настроить список доступа IP. здесь вы должны оставить IP-адрес вашего текущего устройства или IP-адрес сервера, на котором вы собираетесь развернуть этот API. Но в целях разработки я оставлю все это открытым для себя, добавив 0.0.0.0 в качестве IP-адреса и "для всех" в качестве описания, и нажмите "Готово". и закрыть. Вы должны изменить его при развертывании API, иначе другие пользователи будут иметь доступ к вашей базе данных.
  5. На шаге 4 вы попадете на страницу Развертывания базы данных, где вы можете увидеть Cluster0, нажмите подключить> подключить новое приложение, это покажет вам URI, который мы будем использовать для подключения базы данных к API. теперь замените пароль и имя пользователя паролем и именем пользователя, созданными на шаге 3. Пример URI:
    mongodb+srv://‹username›:‹password›@cluster0 .h8milvy.mongodb.net/?retryWrites=true&w=большинство

Что ж, пока давайте сохраним его в надежном месте, мы вернемся к нему, когда начнем создавать API.

Создайте проект узла и установите необходимые пакеты

Давайте откроем наш терминал и создадим папку с именем «бэкэнд» и создадим новый проект узла внутри этой папки, который будет инициализировать файл package.json.

mkdir backend
cd backend
npm init -y

Прежде чем мы изучим и добавим дополнительные скрипты в файл package.json, давайте установим все необходимые пакеты и поймем, какую роль они играют в нашем API.

npm i express mongoose dotenv cors bcryptjs morgan jsonwebtoken

express — для управления сервером и маршрутами.
mongoose — для подключения к MongoDB
dotenv — для загрузки переменных среды из файла .env
cors — чтобы разрешить доступ API из разных доменов
bcryptjs — для хеширования паролей
morgan — для регистрации HTTP-запросов и ошибок
jsonwebtoken— для аутентификации.

Здесь мы можем видеть все пакеты, которые мы установили в зависимостях, а также вы можете видеть, что я добавил два скрипта, и один из них использует nodemon, но здесь вы не можете видеть установленный nodemon, потому что я установил его глобально, поэтому вы либо устанавливаете его глобально или как dev-зависимость.

npm i nodemon -D
//Or
npm install -g nodemon

Nodemon — с помощью nodemon нам не нужно перезапускать наш сервер каждый раз, когда он выходит из строя, он будет запускаться автоматически.

Создавать и структурировать папки и файлы

Ну, объяснять каждый файл на этом этапе будет бесполезно, поэтому на этом этапе позвольте мне просто показать вам структуру папок и файлов и, пожалуйста, создайте файлы как есть, и я уверен, что на данный момент у вас уже есть package.json, package -lock.json и папку node_modules.

Создайте все папки и файлы соответствующим образом.
Итак, мы установили все необходимые пакеты и создали файлы, необходимые для начала работы.

Давайте создадим и запустим сервер и подключимся к базе данных

Надеюсь, вы уже создали файл index.js в корневом каталоге, если нет
создайте его сейчас. Внутри этого файла мы импортируем express, dotenv, cors и morgan и настроим промежуточное программное обеспечение, маршруты, а также установим соединение с базой данных. Чтобы упростить понимание, мы создадим соединение с базой данных в другом файле (Db.js) и импортируем этот файл на сервер. Этот файл находится в папке config. Кроме того, прежде чем мы продолжим, мы должны настроить переменные среды, которые также находятся в папке конфигурации.

config/config.env

MONGO_URI=mongodb+srv://<username>:<password>@cluster0.h8milvy.mongodb.net/?retryWrites=true&w=majority
JWT_SECTET=sdfsnisdnjsnfjsdnfjsdnfjk
PORT=5000

Убедитесь, что вы используете URI подключения к базе данных в качестве MONG_URI.

config/Db.js

const mongoose = require('mongoose')
mongoose.connect(process.env.MONGO_URI)
 .then(() => console.log('DATABASE CONNECTED'))
 .catch(err => {
  console.log('DATABASE CONNECTION ERROR', err)
  process.exit(1)
})

Этот файл будет использоваться для подключения к базе данных.

Открыть файл index.js

Вот как будет выглядеть ваш файл index.js: вы импортировали пакеты и создали экспресс-сервер как приложение,настроили все промежуточное ПО и подключились к базе данных.

Примечание: помните, что это завершенная версия (v1) файла index.js, поэтому, если вы попытаетесь запустить сервер в таком виде, вы получите сообщение об ошибке. Помните, что из-за маршрутов мы еще не создали никаких маршрутов. Итак, если вы хотите запустить сервер сейчас, вы можете прокомментировать 3 строки маршрутов, и вы можете запустить сервер и продолжать раскомментировать соответствующий маршрут по мере продвижения.

index.js

const express = require('express')
const app = express()
const dotenv = require('dotenv')
const cors = require('cors')
const morgan = require('morgan')
// MIDDLEWEARES
dotenv.config({ path: './config/config.env' })
require('./config/Db')
app.use(cors())
app.use(express.json())
app.use(morgan('dev')) // for logging
// ROUTES
app.use('/api/v1', require('./routes/posts'))
app.use('/api/v1', require('./routes/auth'))
app.use('/api/v1', require('./routes/features'))

PORT  = process.env.PORT || 5000
app.listen(PORT, console.log(`SERVER RUNNING ON PORT: ${PORT}`))

Используйте скрипты для запуска сервера.

npm run dev

Сервер будет работать на порту 5000, убедитесь, что у вас ничего не запущено на порту 5000.

Примечание. В маршрутах вы можете увидеть /api/v1, что означает, что это первые два каталога перед любым каталогом маршрута, который мы указываем в маршрутах в папке маршрутов. Пример: маршрут входа будет следующим: http://127.0.0.1:5000/api/v1/login, так как мы используем номер порта 5000.

Аутентификация

Откройте файл User.js в папке моделей. Здесь мы собираемся создать схему мангуста для наших пользовательских моделей, а также определим некоторые другие функции для форматирования текущей даты, как мы хотим, а также для заполнения сообщений, которые позволят нам получать все сообщения, опубликованные пользователем, в то время как мы получаем профиль пользователя, который облегчит задачу в долгосрочной перспективе.

модели/User.js

const mongoose = require('mongoose')
let UserSchema = new mongoose.Schema({
 name:{
  type: String,
  required: true,
  index:true
 },
 email: {
  type: String,
  required: true,
  unique: true,
  match: [/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/]
 },
 password:{
  type: String,
  required: true,
  select: false
 },
 following: {
  type: Array
 },
 followers: {
  type: Array
 },
 created_at:{
  type: String,
 }
}, {
 toJSON: { virtuals: true },
 toObject: { virtuals: true }
})
UserSchema.pre('save', async function (next) {
 let date_info = new Date
 let date_into = date_info.getDate() + '/' + (date_info.getMonth()+1) + '/' +  date_info.getFullYear()
 this.created_at = await date_into
})
UserSchema.virtual('posts', {
 ref: 'post',
 localField: '_id',
 foreignField: 'UserId',
 justOne: false
})
module.exports = mongoose.model('user', UserSchema)

Теперь откройте файл auth.js, если у вас его нет, создайте файл auth.js в папке маршрутов. Здесь мы собираемся создать три маршрута. Регистрация, вход и маршруты пользователей. Мы все знаем, что делают маршруты регистрации и входа в систему, поэтому позвольте мне рассказать вам о маршруте пользователя. Маршрут пользователя используется для проверки вошедшего в систему пользователя.

Также нам нужно защитить некоторые маршруты, чтобы убедиться, что только вошедшие в систему пользователи могут использовать маршрут, чтобы это произошло, мы создадим промежуточное программное обеспечение для проверки заголовков запроса на наличие токена доступа. Теперь создайте verifyAuth.js в папке middleware, мы вернемся к этому после создания маршрута регистрации и входа.

Примечание. не забудьте раскомментировать маршрут авторизации из файла index.js, если он был прокомментирован.

Давайте приступим к коду, сначала импортируйте необходимые библиотеки, такие как jsonwebtoken, bcryptjs, экспресс и настройте маршрутизатор с помощью экспресс и экспортируйте его. Здесь вы увидите, что я импортировал модель пользователя как User, а также файл verifyAuth.js как verifyAuth. Если вы сейчас запустите сервер, вы будет получено сообщение об ошибке, связанное с тем, что сейчас в файле verifyAuth.js ничего нет, поэтому, чтобы избежать ошибки, давайте закодируем этот файл и вернемся к Auth.js.

middleware/verifyAuth.js
Здесь мы ищем значение «x-токен» в заголовке. Который будет содержать токен доступа, сгенерированный JWT, и проверять токен с помощью jwt.verify().

const jwt = require('jsonwebtoken')
module.exports = (req, res,next) => {
 const token = req.header('x-token')
 if(!token){
  return res.status(401).json({
   msg: 'no Token, access denied',
   success: false
  })
 }
try {
  const decoded  = jwt.verify(token, process.env.JWT_SECTET)
  req.user = decoded
  next()
 } catch (err) {
  res.status(400).json({
   msg: 'no Token, access denied',
   success: false
  })
 }
}

маршруты/auth.js

Здесь мы должны создать 3 маршрута. Позвольте мне объяснить, что делает каждый маршрут
/register: это запрос POST, который будет иметь 3 поля ввода: имя, адрес электронной почты, пароль, и эти 3 поля являются обязательными. Затем мы проверим, существует ли пользователь уже или нет, используя входной адрес электронной почты. Как? если электронная почта уже существует в базе данных, то пользователь уже существует, а если нет, то мы будем считать нового пользователя и создадим нового пользователя, и перед сохранением пользователя в пользователе в базе данных мы зашифруем пароль с помощью bcrypt, а затем мы сохранит пользователя и вернет токен jWT, необходимый для аутентификации.
/login: также является POST-запросом, который ожидает 2 поля ввода: адрес электронной почты и пароль. Затем мы проверим, существует ли пользователь или нет, и если нет, мы вернем сообщение о недопустимых учетных данных, и если это так, мы сравним пароль, используя bcrypt, и в случае успеха он вернет токен jWT, который требуется для аутентификации.
/user: это запрос GET, который защищен с помощью промежуточного программного обеспечения, которое мы создали ранее. Этот запрос найдет текущего вошедшего в систему пользователя с помощью токена доступа и вернет информацию/профиль пользователя.

const router = require('express').Router()
const bcrypt = require('bcryptjs')
const jwt = require('jsonwebtoken')
const User = require('../models/User')
const verifyAuth = require('../middleware/verifyAuth')
// POST | /api/v1/register | public | register user
router.post('/register', async (req, res) => {
    try {
        const {name, email, password} = req.body
        
        
        if(!name || !email || !password) {
            res.status(400).json({
                msg: 'please fill the required fields',
                success: false
            })
        }
        
        let user = await User.findOne({email})
        if(user){
            return res.status(400).json({ 
                msg: 'user already exists',
                success: false
            })
        }
        
        
        user = new User({
            name,
            email,
            password
        })
        
        const slat = await bcrypt.genSalt(10)
        user.password = await bcrypt.hash(password, slat)
        await user.save()
        
        
        // paylaod || {id: user._id}
        jwt.sign({id: user._id}, process.env.JWT_SECTET, {
            expiresIn: 36000 
        }, (err, token) => {
            if(err) throw err
            res.status(200).json({
                token
            })
        })
} catch (err) {
        console.log(err)
        res.status(400).json({success: false})
    }
})
// POST api/v1/login | public | login exixting user
router.post('/login', async (req, res) => {
    try {
        const {email, password} = req.body
        if( !email || !password){
            return res.status(400).json({ 
                msg: 'invalid credentials',
                success: false 
            })
        }
let user = await User.findOne({email}).select('+password')
        if(!user ) return res.status(400).json({
            msg: 'invalid credentials',
            success: false 
        })
const isMatch = await bcrypt.compare(password, user.password)
        if(!isMatch ) return res.status(400).json({ 
            msg: 'invalid credentials',
            success: false 
        })
jwt.sign({id: user._id}, process.env.JWT_SECTET, {
            expiresIn: 36000 
        }, (err, token) => {
            if(err) throw err
            res.status(200).json({
                token
            })
        })
} catch (err) {
        console.log(err)
        res.status(400).json({success: false})
    }
})
// GET api/v1/user | private | get logged in user for the process of auth
router.get('/user', verifyAuth,  async (req, res) => {
    try {
        const user = await User.findById(req.user.id).populate('posts')
        res.status(200).json({
            user,
            success: true
        }) 
    } catch (err) {
        console.error(err.message)
        res.status(500).json({ msg:'SERVER ERROR'})
    }
})
module.exports = router

Теперь, когда мы успешно создали файл authentication. Пришло время создавать посты.

Сообщения

Мы начнем с создания схемы данных для постов. Откройте Post.js в папке моделей и закодируйте схему здесь, также мы создадим функцию для форматирования даты и заполнения пользователя, создавшего сообщение.

модели/Post.js

const mongoose = require('mongoose')
let PostSchema = new mongoose.Schema({
    UserId: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'user',
        required: true
    },
    post_image: {
        type: String,
    },
    description: {
        type: String,
    },
    title: {
        type: String,
    },
    likes: {
        type: Array
    },
    post_emotion: {
        // this will be filled by AI/ML later
        type: String,
        default: null
    },
    created_at:{
        type: String,
    }
}, {
    toJSON: { virtuals: true },
    toObject: { virtuals: true }
})
PostSchema.pre('save', async function (next) {
    let date_info = new Date
    let date_into = date_info.getDate() + '/' + (date_info.getMonth()+1) + '/' +  date_info.getFullYear()
    this.created_at = await date_into
})
PostSchema.virtual('posted_by', {
    ref: 'user',
    localField: 'UserId',
    foreignField: '_id',
    justOne: true
})
module.exports = mongoose.model('post', PostSchema)

Теперь откройте файл posts.js, если у вас его нет, создайте файл posts.js в папке маршрутов. Здесь мы собираемся создать шесть маршрутов. Прежде чем я начну перечислять и объяснять маршруты, давайте импортируем необходимые библиотеки и файлы, импортируем экспресс, создаем маршрутизатор и экспортируем его. Мы также должны импортировать две модели Post и User. Модель User будет использоваться для фильтрации сообщений следующих пользователей, и давайте не будем забывать о verifyAuth, так как здесь нам нужно защитить некоторые маршруты.

Примечание. раскомментируйте маршрут сообщения из index.js, если он был прокомментирован.

/posts: это запрос GET для получения всех сообщений из базы данных
/followers-posts: запрос GET для получения сообщений только из пользователи, на которых вы подписаны, должны войти в систему, чтобы сделать запрос
/post/:id: запрос GET получит одно сообщение по идентификатору
/add-new : запрос POST, который позволит вошедшему в систему пользователю создать новую публикацию. Полями ввода являются заголовок сообщения, сообщение (описание) и URL-адрес изображения для показа изображения (image_url) в базе данных, изображение будет сохранено как post_image
/edit-post/:id
: запрос PUT позволит вошедшему в систему пользователю редактировать собственный опубликованный пост пользователя. Функция гарантирует, что пользователи могут редактировать только свои собственные сообщения, а поля ввода такие же, как при создании нового сообщения.
/delete-post/:id: запрос DELETE, который позволит войти в систему пользователям удалить собственный пост по id. Функция проверит владельца сообщения, проверив, принадлежит ли сообщение вошедшему в систему пользователю или нет.

маршруты/posts.js

const router = require('express').Router()
// Models
const Post = require('../models/Post')
const User = require('../models/User')
// MIDDLEWARE
const verifyAuth = require('../middleware/verifyAuth')
// GET | /api/v1/posts | public | get all posts 
router.get('/posts', async (req, res) => {
    try {
        const posts = await Post.find()
        return res.status(200).json({
            data: posts,
            success: true
        })
    } catch (error) {
        console.log(err)
        res.status(400).json({success: false})
    }
})
// GET | /api/v1/followers-posts | private | get all posts from the users that logged in user follow
router.get('/followers-posts', verifyAuth, async (req, res) => {
try {
        const get_user = await User.findById(req.user.id)
const posts  = await Post.find({UserId: get_user.following}).populate('posted_by')
     
        res.status(200).json({
            data: posts,
            success: true
        })
    } catch (err) {
        console.log(err)
        res.status(400).json({success: false})
    }
})
// GET | /api/v1/post/:id | public | get a single post by id
router.get('/post/:id', async (req, res) => {
    try {
        const post  = await Post.findById(req.params.id)
if(!post){
            res.status(400).json({success: false})
        }
        
        res.status(200).json({
            data: post,
            success: true
        })
} catch (err) {
        console.log(err)
        res.status(400).json({success: false})
    }
})
// POST | /api/v1/add-new| private | add a new post
router.post('/add-new', verifyAuth, async (req, res) => {
    try {
const newPost = await Post.create({
            UserId: req.user.id,
            title: req.body.title,
            description: req.body.description,
            post_image: req.body.image_url,
        })
res.status(200).json({
            data: newPost,
            success: true
        })
    } catch (err) {
        console.log(err)
        res.status(400).json({success: false})
    }
})
// PUT | /api/v1/post/edit-post/:id| Private | Edit a post
router.put('/edit-post/:id', verifyAuth, async (req, res) =>{
    try {
        const post = await Post.findById(req.params.id)
        if (!post) {
            return res.status(400).json({
                success: false
            })
        }
if(!post.UserId == req.user.id){
            return res.status(400).json({
                success: false
            })
        }else{
            await post.update({   
                UserId: req.user.id,
                title: req.body.title,
                description: req.body.description,
                post_image: req.body.image_url,
            })
        }
res.status(200).json({ 
            success: true,
            data: {}
        })
    } catch (err) {
        console.log(err)
        res.status(400).json({success: false})
    }
})
// DELETE | /api/v1/post/delete-post/:id | Private | delete a post
router.delete('/delete-post/:id',verifyAuth, async (req, res) =>{
    try {
        const post = await Post.findById(req.params.id)
        if (!post) {
            return res.status(400).json({
                success: false
            })
        }
        
        if(!post.UserId == req.user.id){
            return res.status(400).json({
                success: false
            })
        }else{
            await post.delete()
        }
        
        res.status(200).json({ 
            success: true,
            data: {}
        })
    } catch (err) {
        console.log(err)
        res.status(400).json({success: false})
    }
})
module.exports = router

Теперь, когда мы создали и сообщения, и аутентификацию, давайте добавим некоторые дополнительные функции в API.

Функции

Примечание. раскомментируйте маршрут сообщения из index.js, если он был прокомментирован.

ну, подумайте об этом.. Давайте разрешим пользователям подписываться друг на друга и держать их в курсе событий, а также разрешим им лайкать публикации. Это будет полезно для анализа данных на последних этапах этой серии, когда мы начнем внедрять модели данных для улучшения API. Давайте без лишних слов приступим к делу.

Откройте файл features.js в папке маршрутов и импортируйте необходимые ресурсы, как и раньше. Здесь мы собираемся создать 5 маршрутов, которые должны получить профиль пользователя по идентификатору, понравиться и отклонить сообщение, а также подписаться на пользователя и отписаться от него. Позвольте мне объяснить, как каждый из его работ.

/like/:id: запрос GET, который добавит лайк сообщению по идентификатору. как это работает, отправляя идентификатор пользователя, отправившего запрос, в массив лайков этого сообщения, мы создали это при создании модели данных сообщения.
/unlike/:id: GET запрос, который в отличие от поста по id. Этот маршрут удалит идентификатор пользователя из массива лайков этого сообщения
/follow/:id: запрос GET. Этот маршрут позволит текущему вошедшему в систему пользователю следовать за другим пользователем. Это работает путем добавления идентификатора текущего пользователя в массив подписчиков целевого пользователя и идентификатора целевого пользователя в следующий массив вошедшего в систему пользователя.
/unfollow/:id: GET запрос, используемый для отмены подписки на пользователя, на которого вы подписаны. Это работает противоположно следующему запросу
/profile/:id: запрос GET, который получит пользователя по идентификатору. Для этого маршрута аутентификация не требуется

Предупреждение о безопасности: в функциях лайков и подписок есть ошибка, из-за которой вы можете добавить столько лайков, сколько хотите, а также можете подписаться на 1 пользователя более одного раза. Мы можем исправить это с помощью простого оператора if else, но я оставлю это так, потому что я планирую большую серию, и в конечном итоге это может привести к введению уровня взлома.

маршруты/features.js

const router = require('express').Router()
const Post = require('../models/Post')
const User = require('../models/User')
const verifyAuth = require('../middleware/verifyAuth')
// GET | /api/v1/post/like/:id| Private | Like a post
router.get('/like/:id', verifyAuth, async (req, res) => {
    try {
        const liked = await Post.updateOne(
            {
                _id: req.params.id
            },
            {
                $push: {
                    likes:  req.user.id 
                }
            }
            )
            
            
            if(!liked){
                return res.status(401).json({success: false})
            }
            
            res.status(200).json({success: true})
            
        } catch (err) {
            console.log(err)
            res.status(400).json({success: false})
        }
    })
    
// GET | /api/v1/post/unlike/:id| Private | unlike a post
router.get('/unlike/:id', verifyAuth, async (req, res) => {
    try {
        const liked = await Post.updateOne(
            {
                _id: req.params.id
            },
            {
                $pull: {
                    likes:  req.user.id 
                }
            }
            )
            
            if(!liked){
                return res.status(401).json({success: false})
            }
            
            
            res.status(200).json({success: true})
            
        } catch (err) {
            console.log(err)
            res.status(400).json({success: false})
        }
    })
    
    
    
// GET | /api/v1/post/follow/:id| Private | follow a User
router.get('/follow/:id', verifyAuth, async (req, res) => {
    try {
        const followed = await User.updateOne(
            {
                _id: req.user.id 
            },
            {
                $push: {
                    following:  req.params.id 
                }
            }
        )
    
        const followersAdded = await User.updateOne(
            {
                _id: req.params.id
            },
            {
                $push: {
                    followers:  req.user.id
                }
            }
        
        )
        
        if(!followed || !followersAdded){
            return res.status(401).json({success: false})
        }
        
        res.status(200).json({success: true})
    } catch (err) {
        console.log(err)
        res.status(400).json({success: false})
    }
})
        
        
// GET | /api/v1/post/unfollow/:id| Private | unfollow a User
router.get('/unfollow/:id', verifyAuth, async (req, res) => {
    try {
        const followFixed = await User.updateOne(
            {
                _id: req.user.id 
            },
            {
                $pull: {
                    following:  req.params.id 
                }
            }
        )
            
        const followersFixed = await User.updateOne(
            {
                _id: req.params.id
            },
            {
                $pull: {
                    followers:  req.user.id
                }
            }
)
if(!followFixed || !followersFixed){
            return res.status(401).json({success: false})
        }
res.status(200).json({success: true})
    } catch (err) {
        console.log(err)
        res.status(400).json({success: false})
    }
})
// GET | /api/v1/post/profile/:id| public | get a users profile by iD
router.get('/profile/:id', async (req, res) => {
    try {
        const user = await User.findById(req.params.id).populate('posts')
        
        if(!user){
            return res.status(401).json({success: false})
        }
        res.status(200).json({
            data: user,
            success: true
        })
    } catch (err) {
        console.log(err)
        res.status(400).json({success: false})
    }
})
module.exports = router

Давайте протестируем API

Для тестирования API мы будем использовать программу под названием postmen, если у вас ее нет, обязательно установите ее, а также мы не будем проверять, работают ли все маршруты, так как это только сделает этот пост все длиннее и длиннее. .
Обязательно запустите сервер, перейдите в папку бэкенда и используйте команду «npm run dev», это запустит сервер разработки, а также откроет приложение почтальона
Здесь мы собираемся протестировать только 4 маршрута, если вы хотите попробовать все, не стесняйтесь делать это. Мы попробуем /register, /user, /add-new и /posts.

/зарегистрироваться

Мы успешно получили токен доступа, теперь давайте проверим пользователя

/пользователь

Мы также проверили пользователя с помощью токена доступа. Давайте создадим пост

/добавить-новый

Новое, мы успешно создали сообщение, давайте посмотрим, сможем ли мы получить сообщение по маршруту /posts.

/сообщений

Да, мы тоже получили сообщения
Попробуйте протестировать все маршруты

Заключение

Что ж, это конец создания этой версии внутреннего API, надеюсь, вам понравилось. Далее, надеюсь, мы будем создавать внешний интерфейс приложения. Но прежде чем я хотел бы знать, не хотите ли вы, ребята, добавить дополнительные функции, которые помогут серии проектов.

Мы пытаемся все упростить, но лично я считаю, что добавить больше функций было бы здорово.
пример :

  • Добавляйте комментарии (отлично подойдет для ML/AI)
  • Разрешить загрузку изображений из локальной сети (публикация, изображение и профиль пользователя)

И еще, дайте мне знать и не забудьте подписаться

ссылка на репозиторий github: https://github.com/nafiu-dev/full_stack_app_with_AI-ML_models

Вы можете связаться со мной здесь:

https://www.instagram.com/nafiu.dev

Linkedin: https://www.linkedin.com/in/nafiu-nizar-93a16720b

Сообщения, связанные с сериями:



часть 2



Другие мои публикации