diff --git a/.env.development b/.env.development index c6891bf..39a5916 100644 --- a/.env.development +++ b/.env.development @@ -3,7 +3,7 @@ NODE_ENV="development" DEBUG=false SERVER_PORT=3201 SECRET="$2b$10$2.JkQCRUa3fXESy/WyKVWO" -SESSION_LIFETIME=3600 +SESSION_LIFETIME=86400 MONGODB_URI="mongodb://localhost:27017/headupdb" SENDGRID_API_KEY="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" SENDGRID_FROM_MAIL="contact@rampeur.fr" diff --git a/app.js b/app.js index e97840b..c074089 100644 --- a/app.js +++ b/app.js @@ -62,7 +62,7 @@ app.use(require('./src/routes')); app.use(exceptionHandler.notFoundErrorHandler); app.use(exceptionHandler.logErrorHandler); -app.use(exceptionHandler.clientErrorHandler); +//app.use(exceptionHandler.clientErrorHandler); app.use(exceptionHandler.fianlErrorHandler); /* diff --git a/src/controllers/article.controller.js b/src/controllers/article.controller.js index e7b30ea..3fb5f73 100644 --- a/src/controllers/article.controller.js +++ b/src/controllers/article.controller.js @@ -1,22 +1,23 @@ const { ArticleService } = require('../services'); //const { where } = require("sequelize"); const asyncHandler = require("../middlewares/asyncHandler"); -const Article = require("../database/models/mysql/Article"); +/*const Article = require("../database/models/mysql/Article"); const Tag = require("../database/models/mysql/Tag"); -const User = require("../database/models/mysql/User"); +const User = require("../database/models/mysql/User");*/ const ErrorResponse = require("../utils/errorResponse"); const slug = require("slug"); -const { +const DB = require('../database/mysql'); +const { Article, Tag, User } = DB; +/*const { appendFollowers, appendFavorites, appendTagList, -} = require("../utils/helpers"); - +} = require("../utils/helpers");*/ const includeOptions = [ { model: Tag, - as: "tagLists", + as: "articleTags", attributes: ["name"], through: { attributes: [] }, }, @@ -31,7 +32,7 @@ module.exports.getArticle = asyncHandler(async (req, res, next) => { if (!article) { return next(new ErrorResponse("Article not found", 404)); } - let tagList = article.tagNameTagTagLists; + let tagList = article.articleTags; //let author = article.author; article = article.toJSONFor(); article.tagList = tagList; @@ -40,58 +41,70 @@ module.exports.getArticle = asyncHandler(async (req, res, next) => { res.status(200).json({ article: article }); }); -module.exports.getArticles = asyncHandler(async (req, res) => { - const { tag, author, favorited, limit = 20, offset = 0 } = req.query; - const { loggedUser } = req; +module.exports.getArticles = asyncHandler(async (req, res, next) => { + try { + const { tag, author, favorited, limit = 20, offset = 0 } = req.query; + //const { loggedUser } = req; + const loggedUser = await User.findOne({ + attributes: { exclude: ["password", "email", "hash", "salt"] }, + where: { id: req.payload.id }, + }); - 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, - }; + const searchOptions = { + include: [ + { + model: Tag, + as: "articleTags", + 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", "hash", "salt"] }, + // where: author ? { username: author } : {}, + ...(author && { where: { username: author } }), + }, + ], + limit: parseInt(limit), + offset: parseInt(offset), + order: [["createdAt", "DESC"]], + distinct: true, + }; - let articles = { rows: [], count: 0 }; + let articles = { rows: [], count: 0 }; - if (favorited) { - const user = await User.findOne({ where: { username: favorited } }); + 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); + 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(); + //console.log("articleTags: ", articleTags); + // const articleTags = article.tagLists; + ArticleService.appendTagList(articleTags, article); + await ArticleService.appendFollowers(loggedUser, article); + await ArticleService.appendFavorites(loggedUser, article); + + //delete article.dataValues.Favorites; + } + + res.status(200).json({ + data: { + articles: articles.rows, + articlesCount: articles.count + } + }); + } catch (err) { + return next(new ErrorResponse(`Something went wrong while fetching articles - ${err.message}`, 500)); } - - 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) => { @@ -128,8 +141,8 @@ module.exports.createArticle = asyncHandler(async (req, res, next) => { article.dataValues.tagList = tagList; article.setAuthor(loggedUser); article.dataValues.author = loggedUser; - await appendFollowers(loggedUser, loggedUser); - await appendFavorites(loggedUser, article); + await ArticleService.appendFollowers(loggedUser, loggedUser); + await ArticleService.appendFavorites(loggedUser, article); res.status(201).json({ article }); }); @@ -192,9 +205,9 @@ module.exports.updateArticle = asyncHandler(async (req, res, next) => { }); const articleTags = await article.getTagLists(); - appendTagList(articleTags, article); - await appendFollowers(loggedUser, article); - await appendFavorites(loggedUser, article); + ArticleService.appendTagList(articleTags, article); + await ArticleService.appendFollowers(loggedUser, article); + await ArticleService.appendFavorites(loggedUser, article); res.status(200).json({ article }); }); @@ -217,9 +230,9 @@ module.exports.articlesFeed = asyncHandler(async (req, res) => { for (const article of articles.rows) { const articleTags = await article.getTagLists(); - appendTagList(articleTags, article); - await appendFollowers(loggedUser, article); - await appendFavorites(loggedUser, article); + ArticleService.appendTagList(articleTags, article); + await ArticleService.appendFollowers(loggedUser, article); + await ArticleService.appendFavorites(loggedUser, article); } res.json({ articles: articles.rows, articlesCount: articles.count }); @@ -241,9 +254,9 @@ module.exports.addFavoriteArticle = asyncHandler(async (req, res, next) => { await loggedUser.addFavorite(article); const articleTags = await article.getTagLists(); - appendTagList(articleTags, article); - await appendFollowers(loggedUser, article); - await appendFavorites(loggedUser, article); + ArticleService.appendTagList(articleTags, article); + await ArticleService.appendFollowers(loggedUser, article); + await ArticleService.appendFavorites(loggedUser, article); res.status(200).json({ article }); }); @@ -264,9 +277,9 @@ module.exports.deleteFavoriteArticle = asyncHandler(async (req, res, next) => { await loggedUser.removeFavorite(article); const articleTags = await article.getTagLists(); - appendTagList(articleTags, article); - await appendFollowers(loggedUser, article); - await appendFavorites(loggedUser, article); + ArticleService.appendTagList(articleTags, article); + await ArticleService.appendFollowers(loggedUser, article); + await ArticleService.appendFavorites(loggedUser, article); res.status(200).json({ article }); }); diff --git a/src/controllers/clan.controller.js b/src/controllers/clan.controller.js new file mode 100644 index 0000000..814b5b4 --- /dev/null +++ b/src/controllers/clan.controller.js @@ -0,0 +1,139 @@ +const { HWClanService } = require('../services'); +const asyncHandler = require("../middlewares/asyncHandler"); +const ErrorResponse = require("../utils/errorResponse"); +var mongoose = require('mongoose'), + User = mongoose.model('User'); + +module.exports.createClan = asyncHandler(async (req, res, next) => { + try { + const { + id, title, country, description, disbanding, frameId, icon, level, members, + membersCount, minLevel, ownerId, serverId, topActivity, topDungeon + } = req.body; + + const author = await User.findById(req.payload.id).then(function (user) { + return user._id; + }); + + const clan = await HWClanService.createClan({ + id, title, country, description, disbanding, frameId, icon, level, members, + membersCount, minLevel, ownerId, serverId, topActivity, topDungeon, author + }); + //console.log(clan); + + res.status(201).json({ + message: 'Clan created successfully', + data: clan.toJSONFor(), + }); + } catch (err) { + return next(new ErrorResponse(`Something went wrong while creating clan - ${err.message}`, 500)); + } +}); + +module.exports.getAllClans = asyncHandler(async (req, res, next) => { + try { + let query = {}; + let { limit = 25, offset = 0 } = req.query; + if (typeof req.query.title !== 'undefined') { + const rgx = new RegExp(`.*${req.query.title}.*`); + query = { + $or: [ + { title: { $regex: rgx, $options: "i" } }, + { id: { $regex: rgx, $options: "i" } }, + ], + } + } + + const data = await HWClanService.getAllClans(query, limit, offset); + res.status(200).json({ + data: { + clans: data.clans.map(function (clan) { + return clan.toJSONFor(); + }), + clansCount: data.clansCount + } + }); + } catch (err) { + return next(new ErrorResponse(`Something went wrong while fetching clans - ${err.message}`, 500)); + } +}); + +module.exports.getClan = asyncHandler(async (req, res, next) => { + try { + //console.log("Clan controller getClan"); + const { clanId } = req.params; + let clan = await HWClanService.getClanById(clanId); + if (!clan) { + return next(new ErrorResponse("Clan not found", 404)); + } + + res.status(200).json({ clan: clan.toJSONFor() }); + } catch (err) { + return next(new ErrorResponse(`Something went wrong while fetching clan - ${err.message}`, 500)); + } +}); + +module.exports.updateClan = asyncHandler(async (req, res, next) => { + try { + //console.log("Clan controller updateClan", req.payload); + const { clanId } = req.params; + let clan = await HWClanService.getClanById(clanId); + //console.log(req.body.clan, clan); + + if (req.payload.id !== clan.author._id.toString()) { + return next(new ErrorResponse("Unauthorized", 401)); + } + Object.assign(clan, req.body.clan); + + let data = await HWClanService.updateClan(clan); + //res.status(200).json({ clan: data.toJSONFor() }); + res.status(200).json({ + message: 'Clan updated successfully', + clan: data.toJSONFor() + }); + } catch (err) { + return next(new ErrorResponse(`Something went wrong while updating clan - ${err.message}`, 500)); + } +}); + +module.exports.deleteClan = asyncHandler(async (req, res, next) => { + try { + const { clanId } = req.params; + let clan = await HWClanService.getClanById(clanId); + //console.log(clanId, clan.author._id.toString(), req.payload.id); + if (req.payload.id !== clan.author._id.toString()) { + return next(new ErrorResponse("Unauthorized", 401)); + } + + let data = await HWClanService.deleteClan(clan); + res.status(200).json({ + message: 'Clan deleted successfully', + data: data.id + }); + } catch (err) { + return next(new ErrorResponse(`Something went wrong while deleting clan - ${err.message}`, 500)); + } +}); +/* +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) { + return 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 }); +}); +*/ diff --git a/src/controllers/member.controller.js b/src/controllers/member.controller.js new file mode 100644 index 0000000..b55dc31 --- /dev/null +++ b/src/controllers/member.controller.js @@ -0,0 +1,110 @@ +const { HWMemberService } = require('../services'); +const asyncHandler = require("../middlewares/asyncHandler"); +const ErrorResponse = require("../utils/errorResponse"); +var mongoose = require('mongoose'), + User = mongoose.model('User'); + +module.exports.createMember = asyncHandler(async (req, res, next) => { + try { + const { + id, allowPm, avatarId, clanIcon, clanId, clanRole, clanTitle, commander, frameId, + isChatModerator, lastLoginTime, leagueId, level, name, serverId + } = req.body; + + const author = await User.findById(req.payload.id).then(function (user) { + return user._id; + }); + + const member = await HWMemberService.createMember({ + id, allowPm, avatarId, clanIcon, clanId, clanRole, clanTitle, commander, frameId, + isChatModerator, lastLoginTime, leagueId, level, name, serverId, author + }); + + res.status(201).json({ + message: 'Member created successfully', + data: member.toJSONFor(), + }); + } catch (err) { + return next(new ErrorResponse(`Something went wrong while creating member - ${err.message}`, 500)); + } +}); + +module.exports.getAllMembers = asyncHandler(async (req, res, next) => { + try { + let query = {}; + let { limit = 25, offset = 0 } = req.query; + if (typeof req.query.name !== 'undefined') { + const rgx = new RegExp(`.*${req.query.name}.*`); + query = { + $or: [ + { name: { $regex: rgx, $options: "i" } }, + { id: { $regex: rgx, $options: "i" } }, + ], + } + } + + const data = await HWMemberService.getAllMembers(query, limit, offset); + res.status(200).json({ + data: { + members: data.members.map(function (member) { + return member.toJSONFor(); + }), + membersCount: data.membersCount + } + }); + } catch (err) { + return next(new ErrorResponse(`Something went wrong while fetching members - ${err.message}`, 500)); + } +}); + +module.exports.getMember = asyncHandler(async (req, res, next) => { + try { + const { memberId } = req.params; + let member = await HWMemberService.getMemberById(memberId); + if (!member) { + return next(new ErrorResponse("Member not found", 404)); + } + + res.status(200).json({ member: member.toJSONFor() }); + } catch (err) { + return next(new ErrorResponse(`Something went wrong while updating member - ${err.message}`, 500)); + } +}); + +module.exports.updateMember = asyncHandler(async (req, res, next) => { + try { + const { memberId } = req.params; + let member = await HWMemberService.getMemberById(memberId); + + if (req.payload.id !== member.author._id.toString()) { + return next(new ErrorResponse("Unauthorized", 401)); + } + Object.assign(member, req.body.member); + + let data = await HWMemberService.updateMember(member); + res.status(200).json({ + message: 'Member updated successfully', + member: data.toJSONFor() + }); + } catch (err) { + return next(new ErrorResponse(`Something went wrong while updating member - ${err.message}`, 500)); + } +}); + +module.exports.deleteMember = asyncHandler(async (req, res, next) => { + try { + const { memberId } = req.params; + let member = await HWMemberService.getMemberById(memberId); + if (req.payload.id !== member.author._id.toString()) { + return next(new ErrorResponse("Unauthorized", 401)); + } + + let data = await HWMemberService.deleteMember(member); + res.status(200).json({ + message: 'Member deleted successfully', + data: data.id + }); + } catch (err) { + return next(new ErrorResponse(`Something went wrong while deleting member - ${err.message}`, 500)); + } +}); diff --git a/src/controllers/product.controller.js b/src/controllers/product.controller.js index 5c04750..fbfac7a 100644 --- a/src/controllers/product.controller.js +++ b/src/controllers/product.controller.js @@ -1,4 +1,4 @@ -//const { ProductService } = require('../services'); +const { ProductService } = require('../services'); //const { where } = require("sequelize"); const asyncHandler = require("../middlewares/asyncHandler"); const Product = require("../database/models/mysql/Product"); @@ -23,6 +23,41 @@ const includeOptions = [ { model: User, as: "author", attributes: { exclude: ["email", "password"] } }, ]; +module.exports.getProduct = asyncHandler(async (req, res, next) => { + /* + const { loggedUser } = req; + const { slug } = req.params; + + const product = await Product.findOne({ + where: { slug: slug }, + include: includeOptions, + }); + + if (!product) { + return next(new ErrorResponse("Product not found", 404)); + } + + const productTags = await product.getTagLists(); + appendTagList(productTags, product); + await appendFollowers(loggedUser, product); + await appendFavorites(loggedUser, product); + + res.status(200).json({ product }); + */ + const { slug } = req.params; + + let product = await ProductService.getProductBySlug(slug); + + if (!product) { + return next(new ErrorResponse("Product not found", 404)); + } + let tags = product.productTags; + product = product.toJSONFor(); + product.tags = tags; + + res.status(200).json({ product: product }); +}); + module.exports.getProducts = asyncHandler(async (req, res) => { const { tag, author, favorited, limit = 20, offset = 0 } = req.query; const { loggedUser } = req; @@ -177,52 +212,6 @@ module.exports.updateProduct = asyncHandler(async (req, res, next) => { res.status(200).json({ product }); }); -module.exports.productsFeed = asyncHandler(async (req, res) => { - const { loggedUser } = req; - - const { limit = 3, offset = 0 } = req.query; - const authors = await loggedUser.getFollowing(); - - const products = await Product.findAndCountAll({ - include: includeOptions, - limit: parseInt(limit), - offset: offset * limit, - order: [["createdAt", "DESC"]], - where: { authorId: authors.map((author) => author.id) }, - distinct: true, - }); - - for (const product of products.rows) { - const productTags = await product.getTagLists(); - - appendTagList(productTags, product); - await appendFollowers(loggedUser, product); - await appendFavorites(loggedUser, product); - } - - res.json({ products: products.rows, productsCount: products.count }); -}); - -module.exports.getProduct = asyncHandler(async (req, res, next) => { - const { loggedUser } = req; - const { slug } = req.params; - - const product = await Product.findOne({ - where: { slug: slug }, - include: includeOptions, - }); - - if (!product) { - return next(new ErrorResponse("Product not found", 404)); - } - - const productTags = await product.getTagLists(); - appendTagList(productTags, product); - await appendFollowers(loggedUser, product); - await appendFavorites(loggedUser, product); - - res.status(200).json({ product }); -}); module.exports.addFavoriteProduct = asyncHandler(async (req, res, next) => { const { loggedUser } = req; diff --git a/src/controllers/products.controller.js b/src/controllers/products.controller.js new file mode 100644 index 0000000..7d0e2fc --- /dev/null +++ b/src/controllers/products.controller.js @@ -0,0 +1,116 @@ +const { ProductService } = require('../services'); +//const { where } = require("sequelize"); +const asyncHandler = require("../middlewares/asyncHandler"); +const Product = require("../database/models/mysql/Product"); +const Tag = require("../database/models/mysql/Tag"); +const User = require("../database/models/mysql/User"); +const ErrorResponse = require("../utils/errorResponse"); + +const { + appendFollowers, + appendFavorites, + appendTagList, +} = require("../utils/helpers"); + +const includeOptions = [ + { + model: Tag, + as: "tagLists", + attributes: ["name"], + through: { attributes: [] }, + }, + { model: User, as: "author", attributes: { exclude: ["email", "password"] } }, +]; + +module.exports.getProducts = asyncHandler(async (req, res) => { + 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 products = { rows: [], count: 0 }; + + if (favorited) { + const user = await User.findOne({ where: { username: favorited } }); + + products.rows = await user.getFavorites(searchOptions); + products.count = await user.countFavorites(); + } else { + products = await Product.findAndCountAll(searchOptions); + } + + for (let product of products.rows) { + const productTags = await product.getTagLists(); + // const productTags = product.tagLists; + appendTagList(productTags, product); + await appendFollowers(loggedUser, product); + await appendFavorites(loggedUser, product); + + delete product.dataValues.Favorites; + } + + res + .status(200) + .json({ products: products.rows, productsCount: products.count }); +}); + +module.exports.getProductsByCategory = asyncHandler(async (req, res, next) => { + const { category } = req.params; + //console.log(category); + + let products = await ProductService.getProductsByCategory(category); + //console.log(products); + + if (!products) { + return next(new ErrorResponse("Products not found", 404)); + } + res.status(200).json({ category: category, count: products.count, products: products.rows }); +}); + +module.exports.productsFeed = asyncHandler(async (req, res) => { + const { loggedUser } = req; + + const { limit = 3, offset = 0 } = req.query; + const authors = await loggedUser.getFollowing(); + + const products = await Product.findAndCountAll({ + include: includeOptions, + limit: parseInt(limit), + offset: offset * limit, + order: [["createdAt", "DESC"]], + where: { authorId: authors.map((author) => author.id) }, + distinct: true, + }); + + for (const product of products.rows) { + const productTags = await product.getTagLists(); + + appendTagList(productTags, product); + await appendFollowers(loggedUser, product); + await appendFavorites(loggedUser, product); + } + + res.json({ products: products.rows, productsCount: products.count }); +}); diff --git a/src/database/models/mongo/herowars/Clan.js b/src/database/models/mongo/herowars/Clan.js new file mode 100644 index 0000000..5241489 --- /dev/null +++ b/src/database/models/mongo/herowars/Clan.js @@ -0,0 +1,55 @@ +var mongoose = require('mongoose'); +var uniqueValidator = require('mongoose-unique-validator'); + +var HWClanSchema = new mongoose.Schema({ + id: { type: String, unique: true }, + country: String, + description: String, + disbanding: Boolean, + frameId: Number, + icon: { + flagColor1: Number, + flagColor2: Number, + flagShape: Number, + iconColor: Number, + iconShape: Number, + }, + level: String, + members: [{ type: mongoose.Schema.Types.ObjectId, ref: 'HWMember' }], + membersCount: Number, + minLevel: String, + ownerId: String, + /*roleNames: { type: mongoose.Schema.Types.ObjectId, ref: 'HWClanRoles' },*/ + serverId: String, + title: String, + topActivity: String, + topDungeon: String, + author: { type: mongoose.Schema.Types.ObjectId, ref: 'User' } +}, {timestamps: true, toJSON: {virtuals: true}}); + +HWClanSchema.plugin(uniqueValidator, { message: 'is already taken' }); + +HWClanSchema.methods.toJSONFor = function() { + return { + id: this.id, + country: this.country, + description: this.description, + disbanding: this.disbanding, + frameId: this.frameId, + icon: this.icon, + level: this.level, + members: this.members, + membersCount: this.membersCount, + minLevel: this.minLevel, + ownerId: this.ownerId, + serverId: this.serverId, + title: this.title, + topActivity: this.topActivity, + topDungeon: this.topDungeon, + createdAt: this.createdAt, + updatedAt: this.updatedAt, + author: this.author.toJSONFor() + }; +}; + +mongoose.model('HWClan', HWClanSchema); diff --git a/src/database/models/mongo/herowars/ClanRoles.js b/src/database/models/mongo/herowars/ClanRoles.js new file mode 100644 index 0000000..4db7884 --- /dev/null +++ b/src/database/models/mongo/herowars/ClanRoles.js @@ -0,0 +1,22 @@ +var mongoose = require('mongoose'); +var uniqueValidator = require('mongoose-unique-validator'); + +var HWClanRolesSchema = new mongoose.Schema({ + member: String, + officer: String, + owner: String, + warlorld: String +}, {timestamps: false, toJSON: {virtuals: true}}); + +HWClanRolesSchema.plugin(uniqueValidator, { message: 'is already taken' }); + +HWClanRolesSchema.methods.toJSONFor = function() { + return { + member: this.member, + officer: this.officer, + owner: this.owner, + warlorld: this.warlorld + }; +}; + +mongoose.model('HWClanRoles', HWClanRolesSchema); diff --git a/src/database/models/mongo/herowars/Member.js b/src/database/models/mongo/herowars/Member.js new file mode 100644 index 0000000..208b8a2 --- /dev/null +++ b/src/database/models/mongo/herowars/Member.js @@ -0,0 +1,135 @@ +var mongoose = require('mongoose'); +var uniqueValidator = require('mongoose-unique-validator'); +/* +var HWMemberSchemaOld = new mongoose.Schema({ + id: { type: String, lowercase: true, unique: true }, + name: String, + lastLoginTime: String, + serverId: String, + level: String, + clanId: String, + clanRole: String, + commander: Boolean, + avatarId: String, + isChatModerator: Boolean, + frameId: Number, + leagueId: Number, + clanTitle: String, + champion: Boolean, + stat: { + activitySum: Number, + todayActivity: Number, + dungeonActivitySum: Number, + todayDungeonActivity: Number, + raidSum: Number, + wasChampion: Boolean, + todayPrestige: Number, + prestigeSum: Number, + }, + inactivity: { + daysLeft: Number, + timeLeft: Number, + dropDate: Number, + dropDelay: String, + }, + adventureSum: Number, + clanGiftsSum: Number, + clanWarSum: Number, + weekStat: { + activity: [Number], + dungeonActivity: [Number], + adventureStat: [Number], + clanWarStat: [Number], + prestigeStat: [Number], + clanGifts: [Number], + }, + score: Number, + scoreGifts: Number, + warGifts: Number, + rewards: Number, + author: { type: mongoose.Schema.Types.ObjectId, ref: 'User' } +}, {timestamps: true, toJSON: {virtuals: true}}); +*/ +var HWMemberSchema = new mongoose.Schema({ + id: { type: String, unique: true }, + allowPm: String, + avatarId: String, + clanIcon: { + flagColor1: Number, + flagColor2: Number, + flagShape: Number, + iconColor: Number, + iconShape: Number, + }, + clanId: String, + clanRole: String, + clanTitle: String, + commander: Boolean, + frameId: Number, + isChatModerator: Boolean, + lastLoginTime: String, + leagueId: Number, + level: String, + name: String, + serverId: String, + champion: Boolean, + stat: { + activitySum: Number, + todayActivity: Number, + dungeonActivitySum: Number, + todayDungeonActivity: Number, + raidSum: Number, + wasChampion: Boolean, + todayPrestige: Number, + prestigeSum: Number, + }, + inactivity: { + daysLeft: Number, + timeLeft: Number, + dropDate: Number, + dropDelay: String, + }, + adventureSum: Number, + clanGiftsSum: Number, + clanWarSum: Number, + weekStat: { + activity: [Number], + dungeonActivity: [Number], + adventureStat: [Number], + clanWarStat: [Number], + prestigeStat: [Number], + clanGifts: [Number], + }, + score: Number, + scoreGifts: Number, + warGifts: Number, + rewards: Number, + author: { type: mongoose.Schema.Types.ObjectId, ref: 'User' } +}, {timestamps: true, toJSON: {virtuals: true}}); + +HWMemberSchema.plugin(uniqueValidator, { message: 'is already taken' }); + +HWMemberSchema.methods.toJSONFor = function() { + return { + id: this.id, + allowPm: this.allowPm, + avatarId: this.avatarId, + clanIcon: this.clanIcon, + clanId: this.clanId, + clanRole: this.clanRole, + clanTitle: this.clanTitle, + commander: this.commander, + frameId: this.frameId, + isChatModerator: this.isChatModerator, + lastLoginTime: this.lastLoginTime, + leagueId: this.leagueId, + level: this.level, + name: this.name, + serverId: this.serverId, + createdAt: this.createdAt, + updatedAt: this.updatedAt, + author: this.author.toJSONFor() + }; +}; + +mongoose.model('HWMember', HWMemberSchema); diff --git a/src/database/models/mongo/herowars/index.js b/src/database/models/mongo/herowars/index.js new file mode 100644 index 0000000..3424267 --- /dev/null +++ b/src/database/models/mongo/herowars/index.js @@ -0,0 +1 @@ +exports.HWMember = require('./Member'); \ No newline at end of file diff --git a/src/database/models/mongo/index.js b/src/database/models/mongo/index.js index c15d084..37e16e4 100644 --- a/src/database/models/mongo/index.js +++ b/src/database/models/mongo/index.js @@ -13,4 +13,6 @@ exports.X2DataLog = require('./X2DataLog'); exports.Article = require('./Article'); exports.Comment = require('./Comment'); exports.Tag = require('./Tag'); +exports.HWClan = require('./herowars/Clan'); +exports.HWMember = require('./herowars/Member'); diff --git a/src/database/mysql.js b/src/database/mysql.js index 017fec9..8982401 100644 --- a/src/database/mysql.js +++ b/src/database/mysql.js @@ -1,24 +1,40 @@ var DataTypes = require("sequelize").DataTypes; const sequelize = require('./config/sequelize'); const ArticleModel = require('./models/mysql/Article'); -const ArticleTageModel = require('./models/mysql/ArticleTag'); +//const ArticleTageModel = require('./models/mysql/ArticleTag'); +const BrandModel = require('./models/mysql/Brand'); +const CategoryModel = require('./models/mysql/Category'); const CommentModel = require('./models/mysql/Comment'); const FavoriteModel = require('./models/mysql/Favorite'); const FollowerModel = require('./models/mysql/Follower'); +const PackagingModel = require('./models/mysql/Packaging'); +const ProductModel = require('./models/mysql/Product'); +const ProductCategoryXrefModel = require('./models/mysql/ProductCategoryXref'); +const ProductTagXrefModel = require('./models/mysql/ProductTagXref'); +const RoleModel = require('./models/mysql/Role'); const TagModel = require('./models/mysql/Tag'); const TagListModel = require('./models/mysql/TagList'); const UserModel = require('./models/mysql/User'); +const UserRoleXrefModel = require('./models/mysql/UserRoleXref'); const DB = { sequelize, User: UserModel(sequelize, DataTypes), Article: ArticleModel(sequelize, DataTypes), - ArticleTag: ArticleTageModel(sequelize, DataTypes), + //ArticleTag: ArticleTageModel(sequelize, DataTypes), + Brand: BrandModel(sequelize, DataTypes), + Category: CategoryModel(sequelize, DataTypes), Comment: CommentModel(sequelize, DataTypes), Favorite: FavoriteModel(sequelize, DataTypes), Follower: FollowerModel(sequelize, DataTypes), + Packaging: PackagingModel(sequelize, DataTypes), + Product: ProductModel(sequelize, DataTypes), + ProductCategoryXref: ProductCategoryXrefModel(sequelize, DataTypes), + ProductTagXref: ProductTagXrefModel(sequelize, DataTypes), + Role: RoleModel(sequelize, DataTypes), Tag: TagModel(sequelize, DataTypes), TagList: TagListModel(sequelize, DataTypes), + UserRoleXref: UserRoleXrefModel(sequelize, DataTypes), }; module.exports = DB; diff --git a/src/database/relationships/index.js b/src/database/relationships/index.js index 5db41b4..0cb2ae4 100644 --- a/src/database/relationships/index.js +++ b/src/database/relationships/index.js @@ -1,69 +1,69 @@ const DB = require('../mysql'); const associate = () => { - /* - DB.User.hasMany(DB.Article, { - foreignKey: 'authorId', - onDelete: "CASCADE" - }); - - DB.Article.belongsTo(DB.User, { - foreignKey: 'authorId', - as: 'author', - }); - */ - DB.Article.belongsToMany(DB.Tag, { as: 'tagNameTags', through: DB.ArticleTag, foreignKey: "articleId", otherKey: "tagName" }); - DB.Article.belongsToMany(DB.Tag, { as: 'tagNameTagTagLists', through: DB.TagList, foreignKey: "articleId", otherKey: "tagName" }); + DB.Article.belongsToMany(DB.Tag, { as: 'articleTags', through: DB.TagList, foreignKey: "articleId", otherKey: "tagName" }); DB.Article.belongsToMany(DB.User, { as: 'userIdUsers', through: DB.Favorite, foreignKey: "articleId", otherKey: "userId" }); - DB.Tag.belongsToMany(DB.Article, { as: 'articleIdArticles', through: DB.ArticleTag, foreignKey: "tagName", otherKey: "articleId" }); + DB.Category.belongsToMany(DB.Product, { as: 'productIdProducts', through: DB.ProductCategoryXref, foreignKey: "categoryId", otherKey: "productId" }); + DB.Product.belongsToMany(DB.Category, { as: 'productCategories', through: DB.ProductCategoryXref, foreignKey: "productId", otherKey: "categoryId" }); + DB.Product.belongsToMany(DB.Tag, { as: 'productTags', through: DB.ProductTagXref, foreignKey: "productId", otherKey: "tagName" }); + DB.Role.belongsToMany(DB.User, { as: 'userIdUserUserRoleXrefs', through: DB.UserRoleXref, foreignKey: "roleId", otherKey: "userId" }); DB.Tag.belongsToMany(DB.Article, { as: 'articleIdArticleTagLists', through: DB.TagList, foreignKey: "tagName", otherKey: "articleId" }); - DB.User.belongsToMany(DB.Article, { as: 'articleIdArticleFavorites', through: DB.Favorite, foreignKey: "userId", otherKey: "articleId" }); + DB.Tag.belongsToMany(DB.Product, { as: 'productIdProductProductTagXrefs', through: DB.ProductTagXref, foreignKey: "tagName", otherKey: "productId" }); + DB.User.belongsToMany(DB.Article, { as: 'articleIdArticles', through: DB.Favorite, foreignKey: "userId", otherKey: "articleId" }); + DB.User.belongsToMany(DB.Role, { as: 'roleIdRoles', through: DB.UserRoleXref, foreignKey: "userId", otherKey: "roleId" }); DB.User.belongsToMany(DB.User, { as: 'followerIdUsers', through: DB.Follower, foreignKey: "userId", otherKey: "followerId" }); DB.User.belongsToMany(DB.User, { as: 'userIdUserFollowers', through: DB.Follower, foreignKey: "followerId", otherKey: "userId" }); - DB.ArticleTag.belongsTo(DB.Article, { as: "article", foreignKey: "articleId" }); - DB.Article.hasMany(DB.ArticleTag, { as: "articleTags", foreignKey: "articleId" }); - DB.Comment.belongsTo(DB.Article, { as: "article", foreignKey: "articleId" }); - DB.Article.hasMany(DB.Comment, { as: "comments", foreignKey: "articleId" }); - DB.Favorite.belongsTo(DB.Article, { as: "article", foreignKey: "articleId" }); - DB.Article.hasMany(DB.Favorite, { as: "favorites", foreignKey: "articleId" }); - DB.TagList.belongsTo(DB.Article, { as: "article", foreignKey: "articleId" }); - DB.Article.hasMany(DB.TagList, { as: "tagLists", foreignKey: "articleId" }); - DB.ArticleTag.belongsTo(DB.Tag, { as: "tagNameTag", foreignKey: "tagName" }); - DB.Tag.hasMany(DB.ArticleTag, { as: "articleTags", foreignKey: "tagName" }); - DB.TagList.belongsTo(DB.Tag, { as: "tagNameTag", foreignKey: "tagName" }); - DB.Tag.hasMany(DB.TagList, { as: "tagLists", foreignKey: "tagName" }); - DB.Article.belongsTo(DB.User, { as: "author", foreignKey: "authorId" }); - DB.User.hasMany(DB.Article, { as: "articles", foreignKey: "authorId" }); - DB.Comment.belongsTo(DB.User, { as: "author", foreignKey: "authorId" }); - DB.User.hasMany(DB.Comment, { as: "comments", foreignKey: "authorId" }); - DB.Favorite.belongsTo(DB.User, { as: "user", foreignKey: "userId" }); - DB.User.hasMany(DB.Favorite, { as: "favorites", foreignKey: "userId" }); - DB.Follower.belongsTo(DB.User, { as: "user", foreignKey: "userId" }); - DB.User.hasMany(DB.Follower, { as: "followers", foreignKey: "userId" }); - DB.Follower.belongsTo(DB.User, { as: "follower", foreignKey: "followerId" }); - DB.User.hasMany(DB.Follower, { as: "followerFollowers", foreignKey: "followerId" }); - + DB.Comment.belongsTo(DB.Article, { as: "article", foreignKey: "articleId"}); + DB.Article.hasMany(DB.Comment, { as: "comments", foreignKey: "articleId"}); + DB.Favorite.belongsTo(DB.Article, { as: "article", foreignKey: "articleId"}); + DB.Article.hasMany(DB.Favorite, { as: "favorites", foreignKey: "articleId"}); + DB.TagList.belongsTo(DB.Article, { as: "article", foreignKey: "articleId"}); + DB.Article.hasMany(DB.TagList, { as: "tagLists", foreignKey: "articleId"}); + DB.Product.belongsTo(DB.Brand, { as: "brand", foreignKey: "brandId"}); + DB.Brand.hasMany(DB.Product, { as: "products", foreignKey: "brandId"}); + DB.ProductCategoryXref.belongsTo(DB.Category, { as: "category", foreignKey: "categoryId"}); + DB.Category.hasMany(DB.ProductCategoryXref, { as: "productCategoryXrefs", foreignKey: "categoryId"}); + DB.Product.belongsTo(DB.Packaging, { as: "packaging", foreignKey: "packagingId"}); + DB.Packaging.hasMany(DB.Product, { as: "products", foreignKey: "packagingId"}); + DB.ProductCategoryXref.belongsTo(DB.Product, { as: "product", foreignKey: "productId"}); + DB.Product.hasMany(DB.ProductCategoryXref, { as: "productCategoryXrefs", foreignKey: "productId"}); + DB.ProductTagXref.belongsTo(DB.Product, { as: "product", foreignKey: "productId"}); + DB.Product.hasMany(DB.ProductTagXref, { as: "productTagXrefs", foreignKey: "productId"}); + DB.UserRoleXref.belongsTo(DB.Role, { as: "role", foreignKey: "roleId"}); + DB.Role.hasMany(DB.UserRoleXref, { as: "userRoleXrefs", foreignKey: "roleId"}); + DB.ProductTagXref.belongsTo(DB.Tag, { as: "tagNameTag", foreignKey: "tagName"}); + DB.Tag.hasMany(DB.ProductTagXref, { as: "productTagXrefs", foreignKey: "tagName"}); + DB.TagList.belongsTo(DB.Tag, { as: "tagNameTag", foreignKey: "tagName"}); + DB.Tag.hasMany(DB.TagList, { as: "tagLists", foreignKey: "tagName"}); + DB.Article.belongsTo(DB.User, { as: "author", foreignKey: "authorId"}); + DB.User.hasMany(DB.Article, { as: "articles", foreignKey: "authorId"}); + DB.Comment.belongsTo(DB.User, { as: "author", foreignKey: "authorId"}); + DB.User.hasMany(DB.Comment, { as: "comments", foreignKey: "authorId"}); + DB.Favorite.belongsTo(DB.User, { as: "user", foreignKey: "userId"}); + DB.User.hasMany(DB.Favorite, { as: "favorites", foreignKey: "userId"}); + DB.Follower.belongsTo(DB.User, { as: "user", foreignKey: "userId"}); + DB.User.hasMany(DB.Follower, { as: "followers", foreignKey: "userId"}); + DB.Follower.belongsTo(DB.User, { as: "follower", foreignKey: "followerId"}); + DB.User.hasMany(DB.Follower, { as: "followerFollowers", foreignKey: "followerId"}); + DB.Product.belongsTo(DB.User, { as: "owner", foreignKey: "ownerId"}); + DB.User.hasMany(DB.Product, { as: "products", foreignKey: "ownerId"}); + DB.UserRoleXref.belongsTo(DB.User, { as: "user", foreignKey: "userId"}); + DB.User.hasMany(DB.UserRoleXref, { as: "userRoleXrefs", foreignKey: "userId"}); /* -// Relations -DB.User.belongsToMany(DB.User, { as: "followers", through: "Followers", foreignKey: "userId", timestamps: false }); -DB.User.belongsToMany(DB.User, { as: "following", through: "Followers", foreignKey: "followerId", timestamps: false }); - -DB.User.hasMany(DB.Article, { foreignKey: "authorId", onDelete: "CASCADE" }); -DB.Article.belongsTo(DB.User, { as: "author", foreignKey: "authorId" }); - -DB.User.hasMany(DB.Comment, { foreignKey: "authorId", onDelete: "CASCADE" }); -DB.Comment.belongsTo(DB.User, { as: "author", foreignKey: "authorId" }); - -DB.Article.hasMany(DB.Comment, { foreignKey: "articleId", onDelete: "CASCADE" }); -DB.Comment.belongsTo(DB.Article, { foreignKey: "articleId" }); - -DB.User.belongsToMany(DB.Article, { as: "favorites", through: "Favorites", timestamps: false }); -DB.Article.belongsToMany(DB.User, { through: "Favorites", foreignKey: "articleId", timestamps: false }); - -DB.Article.belongsToMany(DB.Tag, { through: "TagLists", as: "tagLists", foreignKey: "articleId", timestamps: false, onDelete: "CASCADE" }); -DB.Tag.belongsToMany(DB.Article, { through: "ArticleTags", uniqueKey: false, timestamps: false }); + // Relations + DB.User.belongsToMany(DB.User, { as: "followers", through: "Followers", foreignKey: "userId", timestamps: false }); + DB.User.belongsToMany(DB.User, { as: "following", through: "Followers", foreignKey: "followerId", timestamps: false }); + DB.User.hasMany(DB.Article, { foreignKey: "authorId", onDelete: "CASCADE" }); + DB.Article.belongsTo(DB.User, { as: "author", foreignKey: "authorId" }); + DB.User.hasMany(DB.Comment, { foreignKey: "authorId", onDelete: "CASCADE" }); + DB.Comment.belongsTo(DB.User, { as: "author", foreignKey: "authorId" }); + DB.Article.hasMany(DB.Comment, { foreignKey: "articleId", onDelete: "CASCADE" }); + DB.Comment.belongsTo(DB.Article, { foreignKey: "articleId" }); + DB.User.belongsToMany(DB.Article, { as: "favorites", through: "Favorites", timestamps: false }); + DB.Article.belongsToMany(DB.User, { through: "Favorites", foreignKey: "articleId", timestamps: false }); + DB.Article.belongsToMany(DB.Tag, { through: "TagLists", as: "tagLists", foreignKey: "articleId", timestamps: false, onDelete: "CASCADE" }); + DB.Tag.belongsToMany(DB.Article, { through: "ArticleTags", uniqueKey: false, timestamps: false }); */ - }; module.exports = associate; diff --git a/src/routes/auth.js b/src/middlewares/auth.js similarity index 100% rename from src/routes/auth.js rename to src/middlewares/auth.js diff --git a/src/middlewares/exceptions.handler.js b/src/middlewares/exceptions.handler.js index 9cce4cd..f6ae8dc 100644 --- a/src/middlewares/exceptions.handler.js +++ b/src/middlewares/exceptions.handler.js @@ -9,37 +9,50 @@ const isProduction = appEnv === 'production', const exceptionHandler = { notFoundErrorHandler: (req, res, next) => { let err = new Error('Not Found'); - err.status = 404; - console.log(`${utils.getDateTimeISOString()}`, chalk.yellow(`${err.status} ${err.message}`)); + err.statusCode = 404; + console.log(`${utils.getDateTimeISOString()}`, chalk.yellow(`${err.statusCode} - ${err.message}`)); next(err); + /*if (req.xhr) { + res.status(err.statusCode).json(err); + } else { + next(err); + }*/ }, logErrorHandler: (err, req, res, next) => { - console.log(`${utils.getDateTimeISOString()}`, chalk.red(`error handler : ${err.message} ${err.err}`)); + console.log(`${utils.getDateTimeISOString()}`, chalk.red(`Error handler : ${err.statusCode} - ${err.message}`)); // ${err.err} console.error(err.stack); next(err); + /*if (req.xhr) { + res.status(err.statusCode || 500).json(err); + //res.status(err.statusCode || 500).json({statusCode: err.statusCode, message: err.message}); + } else { + next(err); + }*/ }, clientErrorHandler: (err, req, res, next) => { if (req.xhr) { - res.status(err.status || 500); + res.status(err.statusCode || 500); } else { next(err); } }, // eslint-disable-next-line no-unused-vars fianlErrorHandler: (err, req, res, next) => { - res.status(err.status || 500); + res.status(err.statusCode || 500); if (!isProduction) { /* development error handler will print stacktrace */ res.json({errors: { + statusCode: err.statusCode, message: err.message, - error: err.err, + //error: err.err, stack: err.stack }}); } else { /* production error handler no stacktraces leaked to user */ res.json({errors: { + statusCode: err.statusCode, message: err.message, - error: {}, + //error: {}, stack: {} }}); } diff --git a/src/routes/api/index.js b/src/routes/api/index.js index 466ad4b..825f97e 100644 --- a/src/routes/api/index.js +++ b/src/routes/api/index.js @@ -1,23 +1,24 @@ var routes = require('express').Router(); -//routes.use('/', require('./users')); -//routes.use('/articles', require('./articles')); -//routes.use('/comments', require('./comments')); -//routes.use('/tags', require('./tags')); -routes.use('/profiles', require('./profiles')); -routes.use('/applications', require('./applications')); -routes.use('/aeronefs', require('./aeronefs')); -routes.use('/canopies', require('./canopies')); -routes.use('/dropzones', require('./dropzones')); -routes.use('/jumps', require('./jumps')); -routes.use('/pages', require('./pages')); -routes.use('/qcm', require('./qcm')); +routes.use('/profiles', require('./v1/profiles')); +routes.use('/applications', require('./v1/applications')); +routes.use('/aeronefs', require('./v1/aeronefs')); +routes.use('/canopies', require('./v1/canopies')); +routes.use('/dropzones', require('./v1/dropzones')); +routes.use('/jumps', require('./v1/jumps')); +routes.use('/pages', require('./v1/pages')); +routes.use('/qcm', require('./v1/qcm')); -routes.use('/user', require('./user.routes')); -routes.use('/articles', require('./articles.routes')); -routes.use('/comment', require('./comment.routes')); -routes.use('/products', require('./products.routes')); -routes.use('/tag', require('./tag.routes')); +routes.use('/user', require('./v2/user.routes')); +routes.use('/articles', require('./v2/articles.routes')); +routes.use('/comment', require('./v2/comment.routes')); +routes.use('/product', require('./v2/product.routes')); +routes.use('/products', require('./v2/products.routes')); +routes.use('/tag', require('./v2/tag.routes')); + + +routes.use('/clans', require('./v3/clans.routes')); +routes.use('/members', require('./v3/members.routes')); routes.use(function (err, req, res, next) { if (err.name === 'ValidationError') { diff --git a/src/routes/api/aeronefs.js b/src/routes/api/v1/aeronefs.js similarity index 97% rename from src/routes/api/aeronefs.js rename to src/routes/api/v1/aeronefs.js index 07e68d6..7db47c7 100644 --- a/src/routes/api/aeronefs.js +++ b/src/routes/api/v1/aeronefs.js @@ -2,8 +2,8 @@ var router = require('express').Router(), mongoose = require('mongoose'), Jump = mongoose.model('Jump'), User = mongoose.model('User'); -const auth = require('../auth'), - queries = require('../queries'); +const auth = require('../../../middlewares/auth'), + queries = require('../../queries'); router.get('/allByImat', auth.required, function (req, res, next) { diff --git a/src/routes/api/applications.js b/src/routes/api/v1/applications.js similarity index 99% rename from src/routes/api/applications.js rename to src/routes/api/v1/applications.js index 409f43e..fdf32fc 100644 --- a/src/routes/api/applications.js +++ b/src/routes/api/v1/applications.js @@ -2,7 +2,7 @@ var router = require('express').Router(), mongoose = require('mongoose'), Application = mongoose.model('Application'), User = mongoose.model('User'); -const auth = require('../auth'), +const auth = require('../../../middlewares/auth'), mailer = require('@sendgrid/mail'); mailer.setApiKey(process.env.SENDGRID_API_KEY); diff --git a/src/routes/api/canopies.js b/src/routes/api/v1/canopies.js similarity index 98% rename from src/routes/api/canopies.js rename to src/routes/api/v1/canopies.js index 0cff862..e8c04cd 100644 --- a/src/routes/api/canopies.js +++ b/src/routes/api/v1/canopies.js @@ -2,8 +2,8 @@ var router = require('express').Router(), mongoose = require('mongoose'), Jump = mongoose.model('Jump'), User = mongoose.model('User'); -const auth = require('../auth'), - queries = require('../queries'); +const auth = require('../../../middlewares/auth'), + queries = require('../../queries'); router.get('/', auth.required, function (req, res, next) { let query = {}; diff --git a/src/routes/api/dropzones.js b/src/routes/api/v1/dropzones.js similarity index 96% rename from src/routes/api/dropzones.js rename to src/routes/api/v1/dropzones.js index c51bebc..f87fb02 100644 --- a/src/routes/api/dropzones.js +++ b/src/routes/api/v1/dropzones.js @@ -2,8 +2,8 @@ var router = require('express').Router(), mongoose = require('mongoose'), Jump = mongoose.model('Jump'), User = mongoose.model('User'); -const auth = require('../auth'), - queries = require('../queries'); +const auth = require('../../../middlewares/auth'), + queries = require('../../queries'); router.get('/allByOaci', auth.required, function (req, res, next) { diff --git a/src/routes/api/v1/index.js b/src/routes/api/v1/index.js new file mode 100644 index 0000000..8646b96 --- /dev/null +++ b/src/routes/api/v1/index.js @@ -0,0 +1,13 @@ +var routes = require('express').Router(); + +routes.use('/applications', require('./applications')); +routes.use('/aeronefs', require('./aeronefs')); +routes.use('/canopies', require('./canopies')); +routes.use('/dropzones', require('./dropzones')); +routes.use('/jumps', require('./jumps')); +routes.use('/pages', require('./pages')); +routes.use('/profiles', require('./profiles')); +routes.use('/qcm', require('./qcm')); +//routes.use('/user', require('./users')); + +module.exports = routes; \ No newline at end of file diff --git a/src/routes/api/jumps.js b/src/routes/api/v1/jumps.js similarity index 99% rename from src/routes/api/jumps.js rename to src/routes/api/v1/jumps.js index 3d166e5..40fd55c 100644 --- a/src/routes/api/jumps.js +++ b/src/routes/api/v1/jumps.js @@ -4,10 +4,10 @@ var router = require('express').Router(), JumpFile = mongoose.model('JumpFile'), User = mongoose.model('User'), X2DataLog = mongoose.model('X2DataLog'); -const auth = require('../auth'), +const auth = require('../../../middlewares/auth'), chalk = require('chalk'), - queries = require('../queries'), - utils = require('../utils'); + queries = require('../../queries'), + utils = require('../../utils'); // Preload jump objects on routes with ':jump' router.param('jump', function (req, res, next, slug) { diff --git a/src/routes/api/pages.js b/src/routes/api/v1/pages.js similarity index 99% rename from src/routes/api/pages.js rename to src/routes/api/v1/pages.js index bfb3ddd..f68d385 100644 --- a/src/routes/api/pages.js +++ b/src/routes/api/v1/pages.js @@ -2,8 +2,8 @@ var router = require('express').Router(), mongoose = require('mongoose'), Jump = mongoose.model('Jump'), User = mongoose.model('User'); -const auth = require('../auth'), - queries = require('../queries'); +const auth = require('../../../middlewares/auth'), + queries = require('../../queries'); router.get('/aeronefs', auth.required, function (req, res, next) { User.findById(req.payload.id).then(function (user) { diff --git a/src/routes/api/profiles.js b/src/routes/api/v1/profiles.js similarity index 97% rename from src/routes/api/profiles.js rename to src/routes/api/v1/profiles.js index 3fb26be..2bc6ba6 100644 --- a/src/routes/api/profiles.js +++ b/src/routes/api/v1/profiles.js @@ -1,7 +1,7 @@ var router = require('express').Router(), mongoose = require('mongoose'), User = mongoose.model('User'); -const auth = require('../auth'); +const auth = require('../../../middlewares/auth'); // Preload user profile on routes with ':username' router.param('username', function (req, res, next, username) { diff --git a/src/routes/api/qcm.js b/src/routes/api/v1/qcm.js similarity index 98% rename from src/routes/api/qcm.js rename to src/routes/api/v1/qcm.js index 3c2dad6..9a80fc8 100644 --- a/src/routes/api/qcm.js +++ b/src/routes/api/v1/qcm.js @@ -5,7 +5,7 @@ var router = require('express').Router(), QcmQuestion = mongoose.model('QcmQuestion'), QcmChoice = mongoose.model('QcmChoice'), User = mongoose.model('User'); -const auth = require('../auth'); +const auth = require('../../../middlewares/auth'); // Preload qcm objects on routes with ':type' router.param('type', function (req, res, next, type) { diff --git a/src/routes/api/users.js b/src/routes/api/v1/users.js similarity index 99% rename from src/routes/api/users.js rename to src/routes/api/v1/users.js index 4f703d3..d14405d 100644 --- a/src/routes/api/users.js +++ b/src/routes/api/v1/users.js @@ -2,7 +2,7 @@ var router = require('express').Router(), mongoose = require('mongoose'), User = mongoose.model('User'); const passport = require('passport'), - auth = require('../auth'); + auth = require('../../auth'); router.get('/user', auth.required, function (req, res, next) { //console.log(req.payload); diff --git a/src/routes/api/articles.routes.js b/src/routes/api/v2/articles.routes.js similarity index 87% rename from src/routes/api/articles.routes.js rename to src/routes/api/v2/articles.routes.js index 40b2f83..52cdc6f 100644 --- a/src/routes/api/articles.routes.js +++ b/src/routes/api/v2/articles.routes.js @@ -8,8 +8,8 @@ const { updateArticle, addFavoriteArticle, deleteFavoriteArticle -} = require('../../controllers/article.controller'); -const auth = require('../auth'); +} = require('../../../controllers/article.controller'); +const auth = require('../../../middlewares/auth'); const articleRouter = express.Router(); diff --git a/src/routes/api/comment.routes.js b/src/routes/api/v2/comment.routes.js similarity index 60% rename from src/routes/api/comment.routes.js rename to src/routes/api/v2/comment.routes.js index ee1ac74..e421c85 100644 --- a/src/routes/api/comment.routes.js +++ b/src/routes/api/v2/comment.routes.js @@ -1,6 +1,6 @@ const express = require('express'); -const { createComment, getAllComments } = require('../../controllers/comment.controller'); -const auth = require('../auth'); +const { createComment, getAllComments } = require('../../../controllers/comment.controller'); +const auth = require('../../../middlewares/auth'); const commentRouter = express.Router(); diff --git a/src/routes/api/v2/herowars.routes.js b/src/routes/api/v2/herowars.routes.js new file mode 100644 index 0000000..4f49f43 --- /dev/null +++ b/src/routes/api/v2/herowars.routes.js @@ -0,0 +1,13 @@ +const express = require('express'); +const { createMember, getAllMembers, getMember, updateMember } = require('../../../controllers/herowars.controller'); +const auth = require('../../auth'); + +const herowarsRouter = express.Router(); + +herowarsRouter.param('member', getMember); +herowarsRouter.get('/:member', auth.required, getMember); +herowarsRouter.get('/', auth.required, getAllMembers); +herowarsRouter.post('/', auth.required, createMember); +herowarsRouter.put('/', auth.required, updateMember); + +module.exports = herowarsRouter; diff --git a/src/routes/api/v2/index.js b/src/routes/api/v2/index.js new file mode 100644 index 0000000..18c701f --- /dev/null +++ b/src/routes/api/v2/index.js @@ -0,0 +1,11 @@ +var routes = require('express').Router(); + +routes.use('/user', require('./user.routes')); +routes.use('/articles', require('./articles.routes')); +routes.use('/comment', require('./comment.routes')); +routes.use('/product', require('./product.routes')); +routes.use('/products', require('./products.routes')); +routes.use('/tag', require('./tag.routes')); +routes.use('/herowars', require('./herowars.routes')); + +module.exports = routes; \ No newline at end of file diff --git a/src/routes/api/products.routes.js b/src/routes/api/v2/product.routes.js similarity index 81% rename from src/routes/api/products.routes.js rename to src/routes/api/v2/product.routes.js index c4f9781..997aed2 100644 --- a/src/routes/api/products.routes.js +++ b/src/routes/api/v2/product.routes.js @@ -3,19 +3,17 @@ const { getProduct, getProducts, createProduct, - productsFeed, addFavoriteProduct, deleteFavoriteProduct, deleteProduct, updateProduct, -} = require('../../controllers/product.controller'); -const auth = require('../auth'); +} = require('../../../controllers/product.controller'); +const auth = require('../../../middlewares/auth'); const productRouter = express.Router(); productRouter.get('/', auth.optional, getProducts); productRouter.post('/', auth.required, createProduct); -productRouter.get('/feed', auth.required, productsFeed); productRouter.get('/:slug', auth.optional, getProduct); productRouter.put('/:slug', auth.required, updateProduct); productRouter.delete('/:slug', auth.required, deleteProduct); diff --git a/src/routes/api/v2/products.routes.js b/src/routes/api/v2/products.routes.js new file mode 100644 index 0000000..7603457 --- /dev/null +++ b/src/routes/api/v2/products.routes.js @@ -0,0 +1,15 @@ +const express = require('express'); +const { + getProducts, + getProductsByCategory, + productsFeed +} = require('../../../controllers/products.controller'); +const auth = require('../../../middlewares/auth'); + +const productsRouter = express.Router(); + +productsRouter.get('/', auth.optional, getProducts); +productsRouter.get('/feed', auth.required, productsFeed); +productsRouter.get('/:category', auth.optional, getProductsByCategory); + +module.exports = productsRouter; diff --git a/src/routes/api/tag.routes.js b/src/routes/api/v2/tag.routes.js similarity index 59% rename from src/routes/api/tag.routes.js rename to src/routes/api/v2/tag.routes.js index dd20d3e..0936721 100644 --- a/src/routes/api/tag.routes.js +++ b/src/routes/api/v2/tag.routes.js @@ -1,6 +1,6 @@ const express = require('express'); -const { createTag, getAllTags } = require('../../controllers/tag.controller'); -const auth = require('../auth'); +const { createTag, getAllTags } = require('../../../controllers/tag.controller'); +const auth = require('../../../middlewares/auth'); const tagRouter = express.Router(); diff --git a/src/routes/api/user.routes.js b/src/routes/api/v2/user.routes.js similarity index 83% rename from src/routes/api/user.routes.js rename to src/routes/api/v2/user.routes.js index a691e7f..791bfb6 100644 --- a/src/routes/api/user.routes.js +++ b/src/routes/api/v2/user.routes.js @@ -1,6 +1,6 @@ const express = require('express'); -const { authenticate, createUser, getUser, loginAsUser, updateUser } = require('../../controllers/user.controller'); -const auth = require('../auth'); +const { authenticate, createUser, getUser, loginAsUser, updateUser } = require('../../../controllers/user.controller'); +const auth = require('../../../middlewares/auth'); const userRouter = express.Router(); diff --git a/src/routes/api/v3/clans.routes.js b/src/routes/api/v3/clans.routes.js new file mode 100644 index 0000000..2b74b48 --- /dev/null +++ b/src/routes/api/v3/clans.routes.js @@ -0,0 +1,14 @@ +const express = require('express'); +const { createClan, deleteClan, getAllClans, getClan, updateClan } = require('../../../controllers/clan.controller'); +const auth = require('../../../middlewares/auth'); + +const clanRouter = express.Router(); + +//clanRouter.param('clanId', getClan); +clanRouter.get('/', auth.optional, getAllClans); +clanRouter.post('/', auth.required, createClan); +clanRouter.get('/:clanId', auth.required, getClan); +clanRouter.put('/:clanId', auth.required, updateClan); +clanRouter.delete('/:clanId', auth.required, deleteClan); + +module.exports = clanRouter; diff --git a/src/routes/api/v3/index.js b/src/routes/api/v3/index.js new file mode 100644 index 0000000..4a3e800 --- /dev/null +++ b/src/routes/api/v3/index.js @@ -0,0 +1,6 @@ +var routes = require('express').Router(); + +routes.use('/clans', require('./clans')); +routes.use('/members', require('./members')); + +module.exports = routes; \ No newline at end of file diff --git a/src/routes/api/v3/members.routes.js b/src/routes/api/v3/members.routes.js new file mode 100644 index 0000000..0123d4b --- /dev/null +++ b/src/routes/api/v3/members.routes.js @@ -0,0 +1,14 @@ +const express = require('express'); +const { createMember, deleteMember, getAllMembers, getMember, updateMember } = require('../../../controllers/member.controller'); +const auth = require('../../../middlewares/auth'); + +const memberRouter = express.Router(); + +//memberRouter.param('memberId', getMember); +memberRouter.get('/', auth.required, getAllMembers); +memberRouter.post('/', auth.required, createMember); +memberRouter.get('/:memberId', auth.required, getMember); +memberRouter.put('/:memberId', auth.required, updateMember); +memberRouter.delete('/:memberId', auth.required, deleteMember); + +module.exports = memberRouter; diff --git a/src/routes/index.js b/src/routes/index.js index 77f8a4d..1cd29c8 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -1,4 +1,7 @@ var routes = require('express').Router(); routes.use('/api', require('./api')); +//routes.use('/api/v1', require('./api/v1')); +//routes.use('/api/v2', require('./api/v2')); +//routes.use('/api/v3', require('./api/v3')); module.exports = routes; diff --git a/src/services/article.service.js b/src/services/article.service.js index 23a7cc8..27897e3 100644 --- a/src/services/article.service.js +++ b/src/services/article.service.js @@ -31,7 +31,7 @@ class ArticleService { const articles = await Article.findAll({ where: { slug }, include: [ - { model: DB.Tag, as: "tagNameTagTagLists", attributes: ["name"], through: { attributes: [] } }, + { model: DB.Tag, as: "articleTags", attributes: ["name"], through: { attributes: [] } }, { model: DB.User, as: "author", attributes: { exclude: ["email", "phone", "salt", "hash"] } }, //{ model: DB.User, as: "author", attributes: { include: ["id", "username", "image", "role"] } }, ], @@ -50,6 +50,45 @@ class ArticleService { return articles[0]; } + + static appendTagList(articleTags, article) { + const tagList = articleTags.map((tag) => tag.tagName); + + if (!article) return tagList; + delete article.dataValues.tagLists; //articleTags + article.dataValues.tagList = tagList; + } + + static async appendFavorites(loggedUser, article) { + console.log("article: ", article); + //const favorited = await article.hasUser(loggedUser ? loggedUser : null); + const favorited = await article.hasUserIdUsers(loggedUser ? loggedUser : null); + article.dataValues.favorited = loggedUser ? favorited : false; + + //const favoritesCount = await article.countUsers(); + const favoritesCount = await article.countFavorites(); + article.dataValues.favoritesCount = favoritesCount; + } + + static async appendFollowers(loggedUser, toAppend) { + if (toAppend?.author) { + const author = await toAppend.getAuthor(); + //const following = await author.hasFollower(loggedUser ? loggedUser : null); + const following = await author.hasFollowerIdUsers(loggedUser ? loggedUser : null); + toAppend.author.dataValues.following = loggedUser ? following : false; + + const followersCount = await author.countFollowers(); + toAppend.author.dataValues.followersCount = followersCount; + } else { + const following = await toAppend.hasFollowerIdUsers( + loggedUser ? loggedUser : null + ); + toAppend.dataValues.following = loggedUser ? following : false; + + const followersCount = await toAppend.countFollowers(); + toAppend.dataValues.followersCount = followersCount; + } + } } module.exports = ArticleService; \ No newline at end of file diff --git a/src/services/herowars.service.js b/src/services/herowars.service.js new file mode 100644 index 0000000..07f16d8 --- /dev/null +++ b/src/services/herowars.service.js @@ -0,0 +1,34 @@ +const DB = require('../database/mysql'); + +const { HeroWar } = DB; + +class HeroWarService { + static async createMember(data) { + return HeroWar.create(data); + } + + static async getAllMembers() { + return HeroWar.findAll({ + order: [['createdAt', 'DESC']], + }); + } + + static async getMemberById(id) { + return HeroWar.findByPk(id); + } + + static async getMemberByName(email) { + return HeroWar.findOne({ where: { email: email } }); + } + + static async updateMember(data) { + return HeroWar.update(data); + } + + static async deleteMember(data) { + return HeroWar.delete(data); + } + +} + +module.exports = HeroWarService; \ No newline at end of file diff --git a/src/services/hwclan.service.js b/src/services/hwclan.service.js new file mode 100644 index 0000000..7781eee --- /dev/null +++ b/src/services/hwclan.service.js @@ -0,0 +1,66 @@ +var mongoose = require('mongoose'), + HWClan = mongoose.model('HWClan'); + +class HWClanService { + static async createClan(data) { + let clan = new HWClan(); + Object.assign(clan, data); + return clan.save().then(function () { + return HWClanService.getClanById(data.id); + }); + } + + static async getAllClans(query, limit, offset) { + return Promise.all([ + HWClan.find(query) + .skip(Number(offset)) + .limit(Number(limit)) + .sort({ title: 'asc' }) + .populate('author') + .exec(), + HWClan.count(query).exec() + ]).then(function (results) { + const clans = results[0]; + const clansCount = results[1]; + return { + clans: clans, + clansCount: clansCount + }; + }); + } + + static async getClanById(id) { + return HWClan.findOne({ id: id }) + .populate('author') + .then(function (clan) { + if (!clan) { + return null; + } + return clan; + }); + } + + static async getClanByTitle(title) { + return HWClan.findOne({ title: title }) + .populate('author') + .then(function (clan) { + if (!clan) { + return null; + } + return clan; + }); + } + + static async updateClan(data) { + return data.save().then(function () { + return HWClanService.getClanById(data.id); + }); + } + + static async deleteClan(data) { + return data.remove(); + } + +} + +module.exports = HWClanService; \ No newline at end of file diff --git a/src/services/hwmember.service.js b/src/services/hwmember.service.js new file mode 100644 index 0000000..99f3bb8 --- /dev/null +++ b/src/services/hwmember.service.js @@ -0,0 +1,66 @@ +var mongoose = require('mongoose'), + HWMember = mongoose.model('HWMember'); + +class HWMemberService { + static async createMember(data) { + let member = new HWMember(); + Object.assign(member, data); + return member.save().then(function () { + return HWMemberService.getMemberById(data.id); + }); + } + + static async getAllMembers(query, limit, offset) { + return Promise.all([ + HWMember.find(query) + .skip(Number(offset)) + .limit(Number(limit)) + .sort({ name: 'asc' }) + .populate('author') + .exec(), + HWMember.count(query).exec() + ]).then(function (results) { + const members = results[0]; + const membersCount = results[1]; + return { + members: members, + membersCount: membersCount + }; + }); + } + + static async getMemberById(id) { + return HWMember.findOne({ id: id }) + .populate('author') + .then(function (member) { + if (!member) { + return null; + } + return member; + }); + } + + static async getMemberByName(name) { + return HWMember.findOne({ name: name }) + .populate('author') + .then(function (member) { + if (!member) { + return null; + } + return member; + }); + } + + static async updateMember(data) { + return data.save().then(function () { + return HWMemberService.getMemberById(data.id); + }); + } + + static async deleteMember(data) { + return data.remove(); + } + +} + +module.exports = HWMemberService; \ No newline at end of file diff --git a/src/services/index.js b/src/services/index.js index d5b42bd..a2e2ea4 100644 --- a/src/services/index.js +++ b/src/services/index.js @@ -1,5 +1,9 @@ exports.ArticleService = require('./article.service'); exports.CommentService = require('./comment.service'); +exports.ProductService = require('./product.service'); exports.TagService = require('./tag.service'); -exports.UserService = require('./user.service'); \ No newline at end of file +exports.UserService = require('./user.service'); +exports.HeroWarService = require('./herowars.service'); +exports.HWClanService = require('./hwclan.service'); +exports.HWMemberService = require('./hwmember.service'); \ No newline at end of file diff --git a/src/services/product.service.js b/src/services/product.service.js new file mode 100644 index 0000000..547b945 --- /dev/null +++ b/src/services/product.service.js @@ -0,0 +1,76 @@ +const DB = require('../database/mysql'); + +const { Product } = DB; + +class ProductService { + static async createProduct(data) { + return Product.create(data); + } + + static async getAllProducts() { + return Product.findAll({ + order: [['createdAt', 'DESC']], + }); + } + + static async getProductsByUserId(ownerId) { + return Product.findAll({ + where: { ownerId }, + include: [ + { + model: DB.User, + as: 'owner', + attributes: ['username', 'email'], + }, + ], + order: [['createdAt', 'DESC']], + }); + } + + static async getProductBySlug(slug) { + const products = await Product.findAll({ + where: { slug }, + include: [ + { model: DB.Category, as: "productCategories", attributes: ["name"], through: { attributes: [] } }, + { model: DB.Tag, as: "productTags", attributes: ["name"], through: { attributes: [] } }, + { model: DB.User, as: "owner", attributes: { exclude: ["email", "phone", "salt", "hash"] } } + ], + order: [['createdAt', 'DESC']], + }); + //let product = products[0]; + + return products[0]; + } + + static async getProductsByCategory(category) { + const limit = 100, offset = 0; + + const products = await Product.findAndCountAll({ + include: [ + { model: DB.Brand, as: "brand", attributes: ["name", "description"] }, + { model: DB.Category, as: "productCategories", attributes: ["slug", "name", "description"], through: { attributes: [] }, ...(category && { where: { slug: category } }), }, + { model: DB.Tag, as: "productTags", attributes: ["name"], through: { attributes: [] } }, + { model: DB.User, as: "owner", attributes: { exclude: ["email", "phone", "salt", "hash"] } } + ], + limit: parseInt(limit), + offset: offset * limit, + order: [["createdAt", "DESC"]], + //where: { categoryId: 4 }, + distinct: true, + }); + /* + const products = await Product.findAll({ + where: { category }, + include: [ + { model: DB.Category, as: "productCategories", attributes: ["name"], through: { attributes: [] } }, + { model: DB.Tag, as: "productTags", attributes: ["name"], through: { attributes: [] } }, + { model: DB.User, as: "owner", attributes: { exclude: ["email", "phone", "salt", "hash"] } } + ], + order: [['createdAt', 'DESC']], + }); + */ + return products; + } +} + +module.exports = ProductService; \ No newline at end of file diff --git a/src/utils/helpers.js b/src/utils/helpers.js index 762024c..97d7914 100644 --- a/src/utils/helpers.js +++ b/src/utils/helpers.js @@ -1,29 +1,33 @@ const appendTagList = (articleTags, article) => { - const tagList = articleTags.map((tag) => tag.name); + const tagList = articleTags.map((tag) => tag.tagName); if (!article) return tagList; - delete article.dataValues.tagLists; + delete article.dataValues.tagLists; //articleTags article.dataValues.tagList = tagList; }; const appendFavorites = async (loggedUser, article) => { - const favorited = await article.hasUser(loggedUser ? loggedUser : null); + console.log("article: ", article); + //const favorited = await article.hasUser(loggedUser ? loggedUser : null); + const favorited = await article.hasUserIdUsers(loggedUser ? loggedUser : null); article.dataValues.favorited = loggedUser ? favorited : false; - const favoritesCount = await article.countUsers(); + //const favoritesCount = await article.countUsers(); + const favoritesCount = await article.countFavorites(); article.dataValues.favoritesCount = favoritesCount; }; const appendFollowers = async (loggedUser, toAppend) => { if (toAppend?.author) { const author = await toAppend.getAuthor(); - const following = await author.hasFollower(loggedUser ? loggedUser : null); + //const following = await author.hasFollower(loggedUser ? loggedUser : null); + const following = await author.hasFollowerIdUsers(loggedUser ? loggedUser : null); toAppend.author.dataValues.following = loggedUser ? following : false; const followersCount = await author.countFollowers(); toAppend.author.dataValues.followersCount = followersCount; } else { - const following = await toAppend.hasFollower( + const following = await toAppend.hasFollowerIdUsers( loggedUser ? loggedUser : null ); toAppend.dataValues.following = loggedUser ? following : false; diff --git a/tests/env-api-tests.postman.json b/tests/env-api-tests.postman.json index cca4e4e..58c7de4 100644 --- a/tests/env-api-tests.postman.json +++ b/tests/env-api-tests.postman.json @@ -5,7 +5,7 @@ { "enabled": true, "key": "apiUrl", - "value": "http://localhost:3200/api", + "value": "http://localhost:3201/api", "type": "text" } ],