Ajout initial des fichiers de la version mysal

This commit is contained in:
Rampeur
2025-08-08 18:34:15 +02:00
parent 29635cdf83
commit 9a534d5a17
30 changed files with 1381 additions and 0 deletions
+265
View File
@@ -0,0 +1,265 @@
const { where } = require("sequelize");
const asyncHandler = require("../middlewares/asyncHandler");
const Article = require("../models/Article");
const Tag = require("../models/Tag");
const User = require("../models/User");
const ErrorResponse = require("../util/errorResponse");
const slugify = require("slugify");
const {
appendFollowers,
appendFavorites,
appendTagList,
} = require("../util/helpers");
const includeOptions = [
{
model: Tag,
as: "tagLists",
attributes: ["name"],
through: { attributes: [] },
},
{ model: User, as: "author", attributes: { exclude: ["email", "password"] } },
];
module.exports.getArticles = asyncHandler(async (req, res, next) => {
const { tag, author, favorited, limit = 20, offset = 0 } = req.query;
const { loggedUser } = req;
const searchOptions = {
include: [
{
model: Tag,
as: "tagLists",
attributes: ["name"],
through: { attributes: [] }, // ? this will remove the rows from the join table
// where: tag ? { name: tag } : {},
...(tag && { where: { name: tag } }),
},
{
model: User,
as: "author",
attributes: { exclude: ["password", "email"] },
// where: author ? { username: author } : {},
...(author && { where: { username: author } }),
},
],
limit: parseInt(limit),
offset: parseInt(offset),
order: [["createdAt", "DESC"]],
distinct: true,
};
let articles = { rows: [], count: 0 };
if (favorited) {
const user = await User.findOne({ where: { username: favorited } });
articles.rows = await user.getFavorites(searchOptions);
articles.count = await user.countFavorites();
} else {
articles = await Article.findAndCountAll(searchOptions);
}
for (let article of articles.rows) {
const articleTags = await article.getTagLists();
// const articleTags = article.tagLists;
appendTagList(articleTags, article);
await appendFollowers(loggedUser, article);
await appendFavorites(loggedUser, article);
delete article.dataValues.Favorites;
}
res
.status(200)
.json({ articles: articles.rows, articlesCount: articles.count });
});
module.exports.createArticle = asyncHandler(async (req, res, next) => {
const { loggedUser } = req;
fieldValidation(req.body.article.title, next);
fieldValidation(req.body.article.description, next);
fieldValidation(req.body.article.body, next);
const { title, description, body, tagList } = req.body.article;
const slug = slugify(title, { lower: true });
const slugInDB = await Article.findOne({ where: { slug: slug } });
if (slugInDB) next(new ErrorResponse("Title already exists", 400));
const article = await Article.create({
title: title,
description: description,
body: body,
});
for (const tag of tagList) {
const tagInDB = await Tag.findByPk(tag.trim());
if (tagInDB) {
await article.addTagList(tagInDB);
} else if (tag.length > 2) {
const newTag = await Tag.create({ name: tag.trim() });
await article.addTagList(newTag);
}
}
delete loggedUser.dataValues.token;
article.dataValues.tagList = tagList;
article.setAuthor(loggedUser);
article.dataValues.author = loggedUser;
await appendFollowers(loggedUser, loggedUser);
await appendFavorites(loggedUser, article);
res.status(201).json({ article });
});
module.exports.deleteArticle = asyncHandler(async (req, res, next) => {
const { slug } = req.params;
const { loggedUser } = req;
const article = await Article.findOne({
where: { slug: slug },
include: includeOptions,
});
if (!article) next(new ErrorResponse("Article not found", 404));
if (article.authorId !== loggedUser.id)
return next(new ErrorResponse("Unauthorized", 401));
await article.destroy();
res.status(200).json({ article });
});
module.exports.updateArticle = asyncHandler(async (req, res, next) => {
const { slug } = req.params;
const { loggedUser } = req;
const article = await Article.findOne({
where: { slug: slug },
include: includeOptions,
});
if (!article) next(new ErrorResponse("Article not found", 404));
if (article.authorId !== loggedUser.id)
return next(new ErrorResponse("Unauthorized", 401));
const { title, description, body } = req.body.article;
const slugInDB = await Article.findOne({
where: { slug: slugify(title ? title : article.title, { lower: true }) },
});
if (slugInDB && slugInDB.slug !== slug)
return next(new ErrorResponse("Title already exists", 400));
await article.update({
title: title ? title : article.title,
description: description ? description : article.description,
body: body ? body : article.body,
});
const articleTags = await article.getTagLists();
appendTagList(articleTags, article);
await appendFollowers(loggedUser, article);
await appendFavorites(loggedUser, article);
res.status(200).json({ article });
});
module.exports.articlesFeed = asyncHandler(async (req, res, next) => {
const { loggedUser } = req;
const { limit = 3, offset = 0 } = req.query;
const authors = await loggedUser.getFollowing();
const articles = await Article.findAndCountAll({
include: includeOptions,
limit: parseInt(limit),
offset: offset * limit,
order: [["createdAt", "DESC"]],
where: { authorId: authors.map((author) => author.id) },
distinct: true,
});
for (const article of articles.rows) {
const articleTags = await article.getTagLists();
appendTagList(articleTags, article);
await appendFollowers(loggedUser, article);
await appendFavorites(loggedUser, article);
}
res.json({ articles: articles.rows, articlesCount: articles.count });
});
module.exports.getArticle = asyncHandler(async (req, res, next) => {
const { loggedUser } = req;
const { slug } = req.params;
const article = await Article.findOne({
where: { slug: slug },
include: includeOptions,
});
if (!article) return next(new ErrorResponse("Article not found", 404));
const articleTags = await article.getTagLists();
appendTagList(articleTags, article);
await appendFollowers(loggedUser, article);
await appendFavorites(loggedUser, article);
res.status(200).json({ article });
});
module.exports.addFavoriteArticle = asyncHandler(async (req, res, next) => {
const { loggedUser } = req;
const { slug } = req.params;
const article = await Article.findOne({
where: { slug: slug },
include: includeOptions,
});
if (!article) return next(new ErrorResponse("Article not found", 404));
await loggedUser.addFavorite(article);
const articleTags = await article.getTagLists();
appendTagList(articleTags, article);
await appendFollowers(loggedUser, article);
await appendFavorites(loggedUser, article);
res.status(200).json({ article });
});
module.exports.deleteFavoriteArticle = asyncHandler(async (req, res, next) => {
const { loggedUser } = req;
const { slug } = req.params;
const article = await Article.findOne({
where: { slug: slug },
include: includeOptions,
});
if (!article) return next(new ErrorResponse("Article not found", 404));
await loggedUser.removeFavorite(article);
const articleTags = await article.getTagLists();
appendTagList(articleTags, article);
await appendFollowers(loggedUser, article);
await appendFavorites(loggedUser, article);
res.status(200).json({ article });
});
const fieldValidation = (field, next) => {
if (!field) {
return next(new ErrorResponse(`Missing fields`, 400));
}
};
+120
View File
@@ -0,0 +1,120 @@
const Comment = require("../models/Comment");
const Article = require("../models/Article");
const User = require("../models/User");
const asyncHandler = require("../middlewares/asyncHandler");
const { appendFollowers } = require("../util/helpers");
const ErrorResponse = require("../util/errorResponse");
module.exports.getComments = asyncHandler(async (req, res, next) => {
const { slug } = req.params;
const { loggedUser } = req;
const article = await Article.findOne({
where: { slug: slug },
});
if (!article) return next(new ErrorResponse("Article not found", 404));
const comments = await article.getComments({
include: [
{
model: User,
as: "author",
attributes: ["username", "bio", "image"],
},
],
});
for (let comment of comments) {
await appendFollowers(loggedUser, comment);
}
res.status(200).json({ comments });
});
module.exports.getComment = asyncHandler(async (req, res, next) => {
const { slug, id } = req.params;
const { loggedUser } = req;
const article = await Article.findOne({
where: { slug: slug },
});
if (!article) return next(new ErrorResponse("Article not found", 404));
const comment = await Comment.findOne({
where: { id: id },
include: [
{
model: User,
as: "author",
attributes: ["username", "bio", "image"],
},
],
});
if (!comment) return next(new ErrorResponse("Comment not found", 404));
await appendFollowers(loggedUser, comment);
res.status(200).json({ comment });
});
module.exports.createComment = asyncHandler(async (req, res, next) => {
const { body } = req.body.comment;
const { slug } = req.params;
const { loggedUser } = req;
fieldValidation(body, next);
const article = await Article.findOne({
where: { slug: slug },
include: [
{ model: User, as: "author", attributes: ["username", "bio", "image"] },
],
});
if (!article) return next(new ErrorResponse("Article not found", 404));
const comment = await Comment.create({
body: body,
articleId: article.id,
authorId: loggedUser.id,
});
delete loggedUser.dataValues.token;
await appendFollowers(loggedUser, loggedUser);
comment.dataValues.author = loggedUser;
res.status(201).json({ comment });
});
module.exports.deleteComment = asyncHandler(async (req, res, next) => {
const { slug, id } = req.params;
const { loggedUser } = req;
const article = await Article.findOne({
where: { slug: slug },
});
if (!article) return next(new ErrorResponse("Article not found", 404));
const comment = await Comment.findOne({
where: { id: id },
});
if (!comment) return next(new ErrorResponse("Comment not found", 404));
if (comment.authorId !== loggedUser.id)
return next(new ErrorResponse("Unauthorized", 401));
await comment.destroy();
res.status(200).json({ comment });
});
const fieldValidation = (field, next) => {
if (!field) {
return next(new ErrorResponse(`Missing fields`, 400));
}
};
+74
View File
@@ -0,0 +1,74 @@
const User = require("../models/User");
const asyncHandler = require("../middlewares/asyncHandler");
const ErrorResponse = require("../util/errorResponse");
module.exports.getProfile = asyncHandler(async (req, res, next) => {
const username = req.params.username;
const { loggedUser } = req;
const user = await User.findOne({ where: { username: username } });
if (!user) {
return next(new ErrorResponse(`User not found`, 404));
}
let isFollowing = false;
if (loggedUser) {
const followers = await user.getFollowers();
isFollowing = followers.some((user) => user.id === loggedUser.id);
}
const profile = {
username,
bio: user.bio,
image: user.image,
following: isFollowing,
};
res.status(200).json({ profile });
});
module.exports.followUser = asyncHandler(async (req, res, next) => {
const username = req.params.username;
const { loggedUser } = req;
const userToFollow = await User.findOne({ where: { username: username } });
if (!userToFollow) {
return next(new ErrorResponse(`User not found`, 404));
}
const currentUser = await User.findByPk(loggedUser.id);
await userToFollow.addFollower(currentUser);
const profile = {
username: username,
bio: userToFollow.dataValues.bio,
image: userToFollow.dataValues.image,
following: true,
};
res.status(200).json({ profile });
});
module.exports.unfollowUser = asyncHandler(async (req, res, next) => {
const username = req.params.username;
const { loggedUser } = req;
const userToUnfollow = await User.findOne({ where: { username: username } });
if (!userToUnfollow) {
return next(new ErrorResponse(`User not found`, 404));
}
const currentUser = await User.findByPk(loggedUser.id);
await userToUnfollow.removeFollower(currentUser);
const profile = {
username: username,
bio: userToUnfollow.dataValues.bio,
image: userToUnfollow.dataValues.image,
following: false,
};
res.status(200).json({ profile });
});
+12
View File
@@ -0,0 +1,12 @@
const Tag = require("../models/Tag");
const { appendTagList } = require("../util/helpers");
module.exports.getTags = async (req, res, next) => {
let tags = await Tag.findAll({
attributes: ["name"],
});
tags = tags.map((tag) => tag.name);
res.status(200).json({ tags });
};
+93
View File
@@ -0,0 +1,93 @@
const asyncHandler = require("../middlewares/asyncHandler");
const User = require("../models/User");
const ErrorResponse = require("../util/errorResponse");
const { sign } = require("../util/jwt");
module.exports.createUser = asyncHandler(async (req, res, next) => {
const { email, password, username } = req.body.user;
fieldValidation(email, next);
fieldValidation(password, next);
fieldValidation(username, next);
const user = await User.create({
email: email,
password: password,
username: username,
});
if (user.dataValues.password) {
delete user.dataValues.password;
}
user.dataValues.token = await sign(user);
user.dataValues.bio = null;
user.dataValues.image = null;
res.status(201).json({ user });
});
module.exports.loginUser = asyncHandler(async (req, res, next) => {
const { email, password } = req.body.user;
fieldValidation(email, next);
fieldValidation(password, next);
const user = await User.findOne({
where: {
email: email,
},
});
if (!user) {
return next(new ErrorResponse(`User not found`, 404));
}
const isMatch = user.matchPassword(password);
if (!isMatch) {
return next(new ErrorResponse("Wrong password", 401));
}
delete user.dataValues.password;
user.dataValues.token = await sign(user);
user.dataValues.bio = null;
user.dataValues.image = null;
res.status(200).json({ user });
});
module.exports.getCurrentUser = asyncHandler(async (req, res, next) => {
const { loggedUser } = req;
const user = await User.findByPk(loggedUser.id);
if (!user) {
return next(new ErrorResponse(`User not found`, 404));
}
user.dataValues.token = req.headers.authorization.split(" ")[1];
res.status(200).json({ user });
});
module.exports.updateUser = asyncHandler(async (req, res, next) => {
await User.update(req.body.user, {
where: {
id: req.user.id,
},
});
const user = await User.findByPk(req.user.id);
user.dataValues.token = req.headers.authorization.split(" ")[1];
res.status(200).json({ user });
});
const fieldValidation = (field, next) => {
if (!field) {
return next(new ErrorResponse(`Missing fields`, 400));
}
};