Ajout de la base de données MySQL

This commit is contained in:
Rampeur
2025-08-13 21:51:07 +02:00
parent be44e4fdf0
commit 49b1a3f6b3
35 changed files with 1579 additions and 37 deletions
+7 -1
View File
@@ -1,7 +1,7 @@
APP_ENV="development"
NODE_ENV="development"
DEBUG=false
SERVER_PORT="3200"
SERVER_PORT="3201"
SECRET="$2b$10$2.JkQCRUa3fXESy/WyKVWO"
SESSION_LIFETIME="3600"
MONGODB_URI="mongodb://localhost:27017/adastradb"
@@ -15,3 +15,9 @@ COUCHDB_DESIGN="adastra_app"
COUCHDB_CREDENTIAL="cmFtcGV1cjpES3hwMjRQUw=="
SKYDIVERID_API_URL="https://skydiver.id/api"
SKYDIVERID_API_TOKEN="xmqzgnGYMD.OJgFw1pCXCpJFGmZfSjmWK8lrpqAQNnu"
MYSQL_DBNAME="c4adastracomdb2"
MYSQL_DBUSER="c4adastracomu2"
MYSQL_DBPASS="kbrnrt5jPK12"
MYSQL_DBHOST="ns388640.ip-176-31-255.eu"
MYSQL_DBPORT="3306"
MYSQL_DBTYPE="mysql"
+7 -1
View File
@@ -1,7 +1,7 @@
APP_ENV="development"
NODE_ENV="development"
DEBUG=false
SERVER_PORT="3200"
SERVER_PORT="3201"
SECRET="$2b$10$2.JkQCRUa3fXESy/WyKVWO"
SESSION_LIFETIME=3600
MONGODB_URI="mongodb://localhost:27017/adastradb"
@@ -15,3 +15,9 @@ COUCHDB_DESIGN="adastra_app"
COUCHDB_CREDENTIAL="cmFtcGV1cjpES3hwMjRQUw=="
SKYDIVERID_API_URL="https://skydiver.id/api"
SKYDIVERID_API_TOKEN="xmqzgnGYMD.OJgFw1pCXCpJFGmZfSjmWK8lrpqAQNnu"
MYSQL_DBNAME="c4adastracomdb2"
MYSQL_DBUSER="c4adastracomu2"
MYSQL_DBPASS="kbrnrt5jPK12"
MYSQL_DBHOST="ns388640.ip-176-31-255.eu"
MYSQL_DBPORT="3306"
MYSQL_DBTYPE="mysql"
+7 -1
View File
@@ -1,7 +1,7 @@
APP_ENV="local"
NODE_ENV="development"
DEBUG=false
SERVER_PORT="3200"
SERVER_PORT="3201"
SECRET="$2b$10$2.JkQCRUa3fXESy/WyKVWO"
SESSION_LIFETIME=3600
MONGODB_URI="mongodb://localhost:27017/adastradb"
@@ -15,3 +15,9 @@ COUCHDB_DESIGN="adastra_app"
COUCHDB_CREDENTIAL="cmFtcGV1cjpES3hwMjRQUw=="
SKYDIVERID_API_URL="https://skydiver.id/api"
SKYDIVERID_API_TOKEN="xmqzgnGYMD.OJgFw1pCXCpJFGmZfSjmWK8lrpqAQNnu"
MYSQL_DBNAME="c4adastracomdb2"
MYSQL_DBUSER="c4adastracomu2"
MYSQL_DBPASS="kbrnrt5jPK12"
MYSQL_DBHOST="ns388640.ip-176-31-255.eu"
MYSQL_DBPORT="3306"
MYSQL_DBTYPE="mysql"
+7 -1
View File
@@ -1,7 +1,7 @@
APP_ENV="production"
NODE_ENV="production"
DEBUG=false
SERVER_PORT="3200"
SERVER_PORT="3201"
SECRET="$2b$10$2.JkQCRUa3fXESy/WyKVWO"
SESSION_LIFETIME=3600
MONGODB_URI="mongodb://localhost:27017/adastradb"
@@ -15,3 +15,9 @@ COUCHDB_DESIGN="adastra_app"
COUCHDB_CREDENTIAL="cmFtcGV1cjpES3hwMjRQUw=="
SKYDIVERID_API_URL="https://skydiver.id/api"
SKYDIVERID_API_TOKEN="xmqzgnGYMD.OJgFw1pCXCpJFGmZfSjmWK8lrpqAQNnu"
MYSQL_DBNAME="c4adastracomdb2"
MYSQL_DBUSER="c4adastracomu2"
MYSQL_DBPASS="kbrnrt5jPK12"
MYSQL_DBHOST="ns388640.ip-176-31-255.eu"
MYSQL_DBPORT="3306"
MYSQL_DBTYPE="mysql"
-2
View File
@@ -62,5 +62,3 @@ sonar.properties
**/*.copy.ts
**/*.copy.scss
**/*.copy.html
middlewares
+4 -1
View File
@@ -7,7 +7,8 @@ const { promisify } = require('util'),
bodyParser = require('body-parser'),
chalk = require('chalk'),
utils = require('./routes/utils'),
exceptionHandler = require('./middlewares/exceptions.handler.js');
exceptionHandler = require('./middlewares/exceptions.handler.js'),
connectDB = require('./src/services/connectDB');
var express = require('express'),
session = require('express-session'),
cors = require('cors'),
@@ -65,6 +66,8 @@ if(isProduction){
require('./models/mongo');
require('./config/passport');
connectDB();
app.use(require('./routes'));
app.use(exceptionHandler.notFoundErrorHandler);
+49
View File
@@ -0,0 +1,49 @@
var appEnv = process.env.APP_ENV;
if (appEnv == undefined) {
appEnv = 'development';
}
const isProduction = appEnv === 'production',
chalk = require('chalk'),
utils = require('../routes/utils');
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}`));
next(err);
},
logErrorHandler: (err, req, res, next) => {
console.log(`${utils.getDateTimeISOString()}`, chalk.red(`error handler : ${err.message} ${err.err}`));
console.error(err.stack);
next(err);
},
clientErrorHandler: (err, req, res, next) => {
if (req.xhr) {
res.status(err.status || 500);
} else {
next(err);
}
},
// eslint-disable-next-line no-unused-vars
fianlErrorHandler: (err, req, res, next) => {
res.status(err.status || 500);
if (!isProduction) {
/* development error handler will print stacktrace */
res.json({errors: {
message: err.message,
error: err.err,
stack: err.stack
}});
} else {
/* production error handler no stacktraces leaked to user */
res.json({errors: {
message: err.message,
error: {},
stack: {}
}});
}
}
};
module.exports = exceptionHandler;
+8 -2
View File
@@ -3,7 +3,7 @@
"APP_ENV": "local",
"NODE_ENV" : "development",
"DEBUG": false,
"SERVER_PORT": "3200",
"SERVER_PORT": "3201",
"SECRET": "$2b$10$aEsAUG7Dy8dcTORi1vaQle",
"SESSION_LIFETIME": "3600",
"MONGODB_URI": "mongodb://localhost:27017/adastradb",
@@ -16,6 +16,12 @@
"COUCHDB_DESIGN": "adastra_app",
"COUCHDB_CREDENTIAL": "cmFtcGV1cjpES3hwMjRQUw==",
"SKYDIVERID_API_URL": "https://skydiver.id/api",
"SKYDIVERID_API_TOKEN": "xmqzgnGYMD.OJgFw1pCXCpJFGmZfSjmWK8lrpqAQNnu"
"SKYDIVERID_API_TOKEN": "xmqzgnGYMD.OJgFw1pCXCpJFGmZfSjmWK8lrpqAQNnu",
"MYSQL_DBNAME": "c4adastracomdb2",
"MYSQL_DBUSER": "c4adastracomu2",
"MYSQL_DBPASS": "kbrnrt5jPK12",
"MYSQL_DBHOST": "ns388640.ip-176-31-255.eu",
"MYSQL_DBPORT": "3306",
"MYSQL_DBTYPE": "mysql"
}
}
+955 -7
View File
File diff suppressed because it is too large Load Diff
+5 -2
View File
@@ -45,13 +45,16 @@
"request": "^2.88.2",
"slug": "^8.2.3",
"underscore": "^1.13.6",
"uuid": "^9.0.1"
"uuid": "^9.0.1",
"sequelize": "^6.37.3",
"mysql2": "^3.14.3"
},
"devDependencies": {
"@eslint/js": "^9.0.0",
"eslint": "^9.0.0",
"globals": "^15.0.0",
"newman": "^5.3.2",
"nodemon": "^2.0.22"
"nodemon": "^2.0.22",
"sequelize-cli": "^6.6.2"
}
}
+15 -15
View File
@@ -1,19 +1,19 @@
var router = require('express').Router();
var routes = require('express').Router();
router.use('/', require('./users'));
router.use('/articles', require('./articles'));
router.use('/comments', require('./comments'));
router.use('/tags', require('./tags'));
router.use('/profiles', require('./profiles'));
router.use('/applications', require('./applications'));
router.use('/aeronefs', require('./aeronefs'));
router.use('/canopies', require('./canopies'));
router.use('/dropzones', require('./dropzones'));
router.use('/jumps', require('./jumps'));
router.use('/pages', require('./pages'));
router.use('/qcm', require('./qcm'));
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'));
router.use(function (err, req, res, next) {
routes.use(function (err, req, res, next) {
if (err.name === 'ValidationError') {
return res.status(422).json({
errors: Object.keys(err.errors).reduce(function (errors, key) {
@@ -25,4 +25,4 @@ router.use(function (err, req, res, next) {
return next(err);
});
module.exports = router;
module.exports = routes;
+3 -3
View File
@@ -1,4 +1,4 @@
var router = require('express').Router();
router.use('/api', require('./api'));
var routes = require('express').Router();
routes.use('/api', require('./api'));
module.exports = router;
module.exports = routes;
+19
View File
@@ -0,0 +1,19 @@
//import express to use express methods and properties
const express = require('express');
const routes = require('./routes');
//create an instance of express
const app = express();
//use express.json() to parse incoming requests with JSON payloads
app.use(express.json());
app.use(express.urlencoded({ extended: true })); //parse incoming requests with urlencoded payloads
app.use('/api/v1', routes);
//catch all routes that are not defined to avoid running into errors when a route is not defined
app.use('*', (req, res) => {
res.status(404).json({ error: 'Path does not found, try again' });
});
module.exports = app; //export app to be used in other files
+42
View File
@@ -0,0 +1,42 @@
const { ArticleService } = require('../services/article.service');
const createArticle = async (req, res) => {
try {
const { name, description, userId } = req.body;
const article = await ArticleService.createArticle({
name,
description,
userId,
});
res.status(201).json({
message: 'Article created successfully',
data: article,
});
} catch (err) {
res.status(500).json({
message: 'something went wrong while creating article',
error: err.message,
});
}
};
const getArticlesByUserId = async (req, res) => {
try {
const { userId } = req.params;
const articles = await ArticleService.getArticlesByUserId(userId);
res.status(200).json({
data: articles,
});
} catch (err) {
res.status(500).json({
message: 'something went wrong while fetching articles',
error: err.message,
});
}
};
module.exports = { createArticle, getArticlesByUserId };
+36
View File
@@ -0,0 +1,36 @@
const { UserService } = require('../services/user.service');
const createUser = async (req, res) => {
try {
const { name, email } = req.body;
const user = await UserService.createUser({ name, email });
res.status(201).json({
message: 'User created successfully',
data: user,
});
} catch (err) {
res.status(500).json({
message: 'something went wrong while creating user',
error: err.message,
});
}
};
const getAllUsers = async (req, res) => {
try {
const users = await UserService.getAllUsers();
res.status(200).json({
data: users,
});
} catch (err) {
res.status(500).json({
message: 'something went wrong while fetching users',
error: err.message,
});
}
};
module.exports = { createUser, getAllUsers };
+33
View File
@@ -0,0 +1,33 @@
module.exports = {
"development": {
"username": process.env.MYSQL_DBUSER,
"password": process.env.MYSQL_DBPASS,
"database": process.env.MYSQL_DBNAME,
"host": process.env.MYSQL_DBHOST,
"port": process.env.MYSQL_DBPORT,
"dialect": process.env.MYSQL_DBTYPE
},
"test": {
"username": process.env.MYSQL_DBUSER,
"password": process.env.MYSQL_DBPASS,
"database": process.env.MYSQL_DBNAME,
"host": process.env.MYSQL_DBHOST,
"port": process.env.MYSQL_DBPORT,
"dialect": process.env.MYSQL_DBTYPE
},
"production": {
"username": process.env.MYSQL_DBUSER,
"password": process.env.MYSQL_DBPASS,
"database": process.env.MYSQL_DBNAME,
"host": process.env.MYSQL_DBHOST,
"port": process.env.MYSQL_DBPORT,
"dialect": process.env.MYSQL_DBTYPE,
"dialectOptions": {
"ssl": {
// enable this for production environment only if using a secure connection
"require": true,
"rejectUnauthorized": false
},
}
}
}
+43
View File
@@ -0,0 +1,43 @@
const { Sequelize } = require('sequelize');
const Op = Sequelize.Op;
const sequelize = new Sequelize(
process.env.MYSQL_DBNAME,
process.env.MYSQL_DBUSER,
process.env.MYSQL_DBPASS,
{
host: process.env.MYSQL_DBHOST,
port: process.env.MYSQL_DBPORT,
dialect: process.env.MYSQL_DBTYPE,
$like: Op.like,
$not: Op.not,
timezone: '+02:00',
define: {
charset: 'utf8mb4',
collate: 'utf8mb4_general_ci',
underscored: false,
freezeTableName: true,
},
pool: {
//explain this line of code? this means that the connection pool will have a minimum of 0 connections and a maximum of 5 connections
min: 0,
max: 5,
},
logQueryParameters: process.env.APP_ENV === 'development', // this line of code will log the query parameters if the environment is development
benchmark: true,
});
/*
const checkConnection = async () => {
try {
await sequelize.authenticate();
console.log(`DB Connected`.cyan.underline.bold);
} catch (error) {
console.error("Unable to connect to the database:".red.bold, error);
}
};
checkConnection();
*/
module.exports = sequelize;
+11
View File
@@ -0,0 +1,11 @@
const sequelize = require('./config/sequelize');
const ArticleModel = require('./models/article');
const UserModel = require('./models/user');
const DB = {
sequelize,
User: UserModel(sequelize),
Article: ArticleModel(sequelize),
};
module.exports = DB;
@@ -0,0 +1,33 @@
'use strict';
/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable('Users', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER,
},
name: {
type: Sequelize.STRING,
},
email: {
type: Sequelize.STRING,
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.NOW,
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.NOW,
},
});
},
async down(queryInterface, Sequelize) {
await queryInterface.dropTable('Users');
},
};
@@ -0,0 +1,41 @@
'use strict';
/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable('article', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER,
},
name: {
type: Sequelize.STRING,
},
description: {
type: Sequelize.TEXT,
},
userId: {
type: Sequelize.INTEGER,
allowNull: false,
references: {
model: 'User',
key: 'id',
},
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.NOW,
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.NOW,
},
});
},
async down(queryInterface, Sequelize) {
await queryInterface.dropTable('article');
},
};
+43
View File
@@ -0,0 +1,43 @@
const { DataTypes, Model } = require("sequelize");
const sequelize = require("../config/sequelize");
const slug = require("slug");
class Article extends Model { }
const ArticleModel = () => {
Article.init(
{
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false },
slug: { type: DataTypes.STRING, allowNull: false },
title: { type: DataTypes.STRING, allowNull: false },
description: { type: DataTypes.TEXT },
body: { type: DataTypes.TEXT, allowNull: false }
},
{
sequelize,
modelName: 'Article',
tableName: 'article',
timestamps: true,
createdAt: true,
updatedAt: true
}
);
Article.beforeValidate((article) => {
article.slug =slug(`${article.title}`) + '-' + (Math.random() * Math.pow(36, 6) | 0).toString(36);
});
Article.prototype.toJSONFor = function () {
return {
id: this.id,
slug: this.slug,
title: this.title,
description: this.description,
body: this.body
};
};
return Article;
};
module.exports = ArticleModel;
View File
View File
+60
View File
@@ -0,0 +1,60 @@
const { DataTypes, Model } = require("sequelize");
const sequelize = require("../config/sequelize");
const bcrypt = require("bcrypt");
class User extends Model { }
const UserModel = () => {
User.init(
{
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false },
email: { type: DataTypes.STRING, allowNull: false, unique: true },
username: { type: DataTypes.STRING, allowNull: false, unique: true },
firstname: { type: DataTypes.STRING },
lastname: { type: DataTypes.STRING },
bio: { type: DataTypes.TEXT, allowNull: true },
image: { type: DataTypes.TEXT, allowNull: true },
role: { type: DataTypes.STRING },
password: { type: DataTypes.STRING, allowNull: false }
},
{
sequelize,
modelName: 'User',
tableName: 'user',
timestamps: false,
createdAt: true,
updatedAt: true
}
);
Model.prototype.matchPassword = async function (enteredPassword) {
return await bcrypt.compare(enteredPassword, this.password);
};
const DEFAULT_SALT_ROUNDS = 10;
User.addHook("beforeCreate", async (user) => {
const encryptedPassword = await bcrypt.hash(
user.password,
DEFAULT_SALT_ROUNDS
);
user.password = encryptedPassword;
});
User.prototype.toJSONFor = function () {
return {
id: this.id,
email: this.email,
username: this.username,
firstname: this.firstname,
lastname: this.lastname,
bio: this.bio,
image: this.image,
role: this.role
};
};
return User;
};
module.exports = UserModel;
+29
View File
@@ -0,0 +1,29 @@
const DB = require('../index');
const associate = () => {
DB.User.hasMany(DB.Article, {
foreignKey: 'userId',
as: 'projects',
});
DB.Article.belongsTo(DB.User, {
foreignKey: 'userId',
as: 'user',
});
/*
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.omment, { 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;
+1
View File
@@ -0,0 +1 @@
console.log('this is placeholder for models');
+9
View File
@@ -0,0 +1,9 @@
const express = require('express');
const { createProject, getProjectsByUserId } = require('../../controllers/article.controller');
const projectRouter = express.Router();
projectRouter.post('/', createProject);
projectRouter.get('/:userId', getProjectsByUserId);
module.exports = projectRouter;
+9
View File
@@ -0,0 +1,9 @@
const express = require('express');
const { createUser, getAllUsers } = require('../../controllers/user.controller');
const userRouter = express.Router();
userRouter.post('/register', createUser);
userRouter.get('/', getAllUsers);
module.exports = userRouter;
+10
View File
@@ -0,0 +1,10 @@
const express = require('express');
const articleRouter = require('./api/article.routes');
const userRouter = require('./api/user.routes');
const routes = express.Router();
routes.use('/user', userRouter);
routes.use('/article', articleRouter);
module.exports = routes;
+24
View File
@@ -0,0 +1,24 @@
const http = require('http'); // import the http module from node.js core to create a server instance
const app = require('./app'); // import the express app from the app.js file
const connectDB = require('./services/connectDB');
const PORT = process.env.PORT || 3000; // set the port number to be used by the server instance
/* create a server instance using the http.createServer method
* there is no right or wrong way to create a server instance weather using the http.createServer method or the app.listen method
* I usualy use the http.createServer method because it gives me more control over the server instance like adding a socket.io instance to the server instance
*/
const server = http.createServer(app);
// Adding server instance inside a callback function also gives a flexibility to add more logic before starting the server
const startServer = () => {
// Listen to the server instance on the specified port number
connectDB(); // connect to the database before starting the server
server.listen(PORT, () => {
console.log(
`Server is running on port ${PORT} AND NODE_ENV is ${process.env.NODE_ENV}`
);
});
};
startServer(); // start the server instance
+23
View File
@@ -0,0 +1,23 @@
const DB = require('../database');
const { Projects } = DB;
module.exports = class ProjectService {
static async createProject(data) {
return Projects.create(data);
}
static async getProjectsByUserId(userId) {
return Projects.findAll({
where: { userId },
include: [
{
model: DB.Users,
as: 'user',
attributes: ['name', 'email'],
},
],
order: [['createdAt', 'DESC']],
});
}
}
+23
View File
@@ -0,0 +1,23 @@
const DB = require('../database');
const sequelize = require('../database/config/sequelize');
const associate = require('../database/relationships');
// Connect to the database and log a message to the console
const connectDB = async () => {
try {
await sequelize.authenticate();
console.log('Connection has been established successfully🔥');
// Synchronize the database with the models without need of dropping the tables
await DB.sequelize.sync({
force: false,
});
associate(); // Call the associate function to create the relationships between the models
} catch (error) {
console.error('Unable to connect to the database:', error);
process.exit(1); // Exit the process if the connection is not successful
}
};
module.exports = connectDB;
+21
View File
@@ -0,0 +1,21 @@
const DB = require('../database');
const { Users } = DB;
module.exports = class UserService {
static async createUser(data) {
return Users.create(data);
}
static async getAllUsers() {
return Users.findAll({
order: [['createdAt', 'DESC']],
});
}
static async getUserById(id) {
return Users.findByPk(id);
}
}
//module.exports = userService;
+1
View File
@@ -0,0 +1 @@
console.log('this is placeholder for routes');
View File