diff --git a/.env b/.env
new file mode 100644
index 0000000..935f278
--- /dev/null
+++ b/.env
@@ -0,0 +1,3 @@
+EMAIL_USER=adeline.ondricka5@ethereal.email
+EMAIL_PASSWORD=B4khRtXZPNqtr58bAu
+EMAIL_FROM=adeline.ondricka5@ethereal.email
\ No newline at end of file
diff --git a/lib/auth/default.js b/lib/auth/default.js
new file mode 100644
index 0000000..2344418
--- /dev/null
+++ b/lib/auth/default.js
@@ -0,0 +1,3 @@
+'use strict';
+
+module.exports = 'jwt';
\ No newline at end of file
diff --git a/lib/auth/strategies/jwt.js b/lib/auth/strategies/jwt.js
new file mode 100644
index 0000000..6a7e694
--- /dev/null
+++ b/lib/auth/strategies/jwt.js
@@ -0,0 +1,24 @@
+'use strict';
+
+module.exports = {
+ scheme: 'jwt',
+ options: {
+ keys: 'random_string',
+ verify: {
+ aud: 'urn:audience:iut',
+ iss: 'urn:issuer:iut',
+ sub: false,
+ nbf: true,
+ exp: true,
+ maxAgeSec: 14400, // 4 hours
+ timeSkewSec: 15
+ },
+ validate: async (artifacts, request, h) => {
+
+ return {
+ isValid: true,
+ credentials: artifacts.decoded.payload
+ };
+ }
+ }
+};
diff --git a/lib/migrations/0-favorites.js b/lib/migrations/0-favorites.js
new file mode 100644
index 0000000..fa0c319
--- /dev/null
+++ b/lib/migrations/0-favorites.js
@@ -0,0 +1,19 @@
+// Migration pour créer la table des favoris
+'use strict';
+
+module.exports = {
+ async up(knex) {
+ await knex.schema.createTable('favorites', (table) => {
+ table.integer('user_id').unsigned().notNullable();
+ table.integer('movie_id').unsigned().notNullable();
+ table.primary(['user_id', 'movie_id']);
+ table.foreign('user_id').references('id').inTable('user');
+ table.foreign('movie_id').references('id').inTable('movie');
+ });
+ },
+
+ async down(knex) {
+ await knex.schema.dropTable('favorites');
+ }
+
+}
\ No newline at end of file
diff --git a/lib/migrations/0-user.js b/lib/migrations/0-user.js
new file mode 100644
index 0000000..3d8ae90
--- /dev/null
+++ b/lib/migrations/0-user.js
@@ -0,0 +1,22 @@
+'use strict';
+
+module.exports = {
+
+ async up(knex) {
+
+ //update table User for role
+ await knex.schema.table('user', (table) => {
+
+ table.string('role').notNullable().defaultTo('user');
+ });
+ },
+
+ async down(knex) {
+
+ //update table User for role
+ await knex.schema.table('user', (table) => {
+
+ table.dropColumn('role');
+ });
+ }
+};
diff --git a/lib/migrations/1-user.js b/lib/migrations/1-user.js
new file mode 100644
index 0000000..3d8ae90
--- /dev/null
+++ b/lib/migrations/1-user.js
@@ -0,0 +1,22 @@
+'use strict';
+
+module.exports = {
+
+ async up(knex) {
+
+ //update table User for role
+ await knex.schema.table('user', (table) => {
+
+ table.string('role').notNullable().defaultTo('user');
+ });
+ },
+
+ async down(knex) {
+
+ //update table User for role
+ await knex.schema.table('user', (table) => {
+
+ table.dropColumn('role');
+ });
+ }
+};
diff --git a/lib/migrations/2-user.js b/lib/migrations/2-user.js
new file mode 100644
index 0000000..8fbcc55
--- /dev/null
+++ b/lib/migrations/2-user.js
@@ -0,0 +1,23 @@
+'use strict';
+
+module.exports = {
+
+ async up(knex) {
+
+ // Add the "scope" field to the "user" table
+ await knex.schema.table('user', (table) => {
+ table.dropColumn('scope'); // Remove the "role" field
+ table.string('scope').notNullable().defaultTo('user');
+
+ });
+ },
+
+ async down(knex) {
+
+ // Revert the changes made in the "up" function
+ await knex.schema.table('user', (table) => {
+ table.dropColumn('scope');
+ table.string('scope').notNullable().defaultTo('user');
+ });
+ }
+};
diff --git a/lib/migrations/3-user.js b/lib/migrations/3-user.js
new file mode 100644
index 0000000..58dba54
--- /dev/null
+++ b/lib/migrations/3-user.js
@@ -0,0 +1,21 @@
+'use strict';
+
+module.exports = {
+
+ async up(knex) {
+
+ // Add the "scope" field to the "user" table
+ await knex.schema.table('user', (table) => {
+ table.dropColumn('scope'); // Remove the "role" field
+
+ });
+ },
+
+ async down(knex) {
+
+ // Revert the changes made in the "up" function
+ await knex.schema.table('user', (table) => {
+ table.string('scope').notNullable().defaultTo('user');
+ });
+ }
+};
diff --git a/lib/migrations/4-user.js b/lib/migrations/4-user.js
new file mode 100644
index 0000000..4a63ce5
--- /dev/null
+++ b/lib/migrations/4-user.js
@@ -0,0 +1,21 @@
+'use strict';
+
+module.exports = {
+
+ async up(knex) {
+
+ // Add the "scope" field to the "user" table
+ await knex.schema.table('user', (table) => {
+ table.string('scope').notNullable().defaultTo('user');
+
+ });
+ },
+
+ async down(knex) {
+
+ // Revert the changes made in the "up" function
+ await knex.schema.table('user', (table) => {
+ table.dropColumn('scope');
+ });
+ }
+};
diff --git a/lib/models/favorite.js b/lib/models/favorite.js
new file mode 100644
index 0000000..a8c6622
--- /dev/null
+++ b/lib/models/favorite.js
@@ -0,0 +1,23 @@
+'use strict';
+
+const Joi = require('joi');
+const { Model } = require('@hapipal/schwifty');
+
+module.exports = class Favorite extends Model {
+
+ static get tableName() {
+
+ return 'favorites';
+ }
+
+ static get joiSchema() {
+
+ return Joi.object({
+ id: Joi.number().integer().greater(0),
+ user_id: Joi.number().integer().greater(0).required().example(1).description('User id'),
+ movie_id: Joi.number().integer().greater(0).required().example(1).description('Movie id')
+ });
+ }
+
+
+}
\ No newline at end of file
diff --git a/lib/models/movie.js b/lib/models/movie.js
new file mode 100644
index 0000000..9d5ff0f
--- /dev/null
+++ b/lib/models/movie.js
@@ -0,0 +1,35 @@
+'use strict';
+
+const Joi = require('joi');
+const { Model } = require('@hapipal/schwifty');
+
+module.exports = class Movie extends Model {
+
+ static get tableName() {
+
+ return 'movie';
+ }
+
+ static get joiSchema() {
+
+ return Joi.object({
+ id: Joi.number().integer().greater(0),
+ title: Joi.string().min(3).required().example('The Matrix').description('Title of the film'),
+ description: Joi.string().min(3).required().example('A computer hacker learns from mysterious rebels about the true nature of his reality and his role in the war against its controllers.').description('Description of the film'),
+ director: Joi.string().min(3).required().example('Lana Wachowski').description('Director of the film'),
+ releaseDate: Joi.date().required().example('1999-03-31').description('Release date of the film'),
+ created_at: Joi.date(),
+ updated_at: Joi.date()
+ });
+ }
+
+ $beforeInsert(queryContext) {
+ this.created_at = new Date();
+ this.created_at = this.updated_at;
+ }
+
+ $beforeUpdate(queryContext) {
+ this.updated_at = new Date();
+ }
+
+}
\ No newline at end of file
diff --git a/lib/models/user.js b/lib/models/user.js
new file mode 100644
index 0000000..4ddffbb
--- /dev/null
+++ b/lib/models/user.js
@@ -0,0 +1,45 @@
+'use strict';
+
+const Joi = require('joi');
+const { Model } = require('@hapipal/schwifty');
+const { encryptSha1 } = require('iut-encrypt-cemal'); // Importe les fonctions d'encryption
+
+module.exports = class User extends Model {
+
+ static get tableName() {
+
+ return 'user';
+ }
+
+ static get joiSchema() {
+
+ return Joi.object({
+ id: Joi.number().integer().greater(0),
+ scope: Joi.string().required().example('user').description('Scope of the user'),
+ username: Joi.string().min(3).required().example('john_doe').description('Username of the user'),
+ firstName: Joi.string().min(3).required().example('John').description('Firstname of the user'),
+ lastName: Joi.string().min(3).required().example('Doe').description('Lastname of the user'),
+ email: Joi.string().email().required().example('john@example.com').description('Email address of the user'),
+ password: Joi.string().min(8).required().example('password123').description('Password of the user'),
+ createdAt: Joi.date(),
+ updatedAt: Joi.date()
+ });
+ }
+
+ $beforeInsert(queryContext) {
+ this.scope = 'user';
+ this.updatedAt = new Date();
+ this.createdAt = this.updatedAt;
+ this.password = encryptSha1(this.password); // Encrypte le mot de passe avant insertion
+ }
+
+ $beforeUpdate(queryContext) {
+ this.updatedAt = new Date();
+
+ // Si le mot de passe a été modifié, ré-encrypte-le avant la mise à jour
+ if (this.password && this.old && this.password !== this.old.password) {
+ this.password = encryptSha1(this.password);
+ }
+ }
+
+};
diff --git a/lib/plugins/@hapi.jwt.js b/lib/plugins/@hapi.jwt.js
new file mode 100644
index 0000000..7a53d76
--- /dev/null
+++ b/lib/plugins/@hapi.jwt.js
@@ -0,0 +1,7 @@
+'use strict';
+
+module.exports = {
+ plugins: {
+ options: {}
+ }
+};
diff --git a/lib/plugins/@hapipal.schmervice.js b/lib/plugins/@hapipal.schmervice.js
new file mode 100644
index 0000000..26853c9
--- /dev/null
+++ b/lib/plugins/@hapipal.schmervice.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = {
+ options: { }
+};
diff --git a/lib/routes/favorites.js b/lib/routes/favorites.js
new file mode 100644
index 0000000..1c0c544
--- /dev/null
+++ b/lib/routes/favorites.js
@@ -0,0 +1,114 @@
+'use strict';
+
+const Joi = require('joi');
+const Jwt = require('@hapi/jwt');
+
+module.exports = [
+ {
+ method: 'POST',
+ path: '/favorites/add',
+ options: {
+ auth: {
+ scope : ['user', 'admin']
+ },
+ tags: ['api'],
+ validate: {
+ payload: Joi.object({
+ movieId: Joi.number().required().example(1).description('Id of the movie'),
+ })
+ }
+ },
+ handler: async (request, h) => {
+ const {userService} = request.services();
+ const { favoriteService } = request.services();
+
+ const { movieId } = request.payload;
+
+ //Search user id in the database with the email
+ const userId = await userService.getByEmail(request.auth.credentials.email).then((user) => user.id)
+
+ //If movie not exist, return error
+ const { Movie } = request.models();
+
+ const movie = await Movie.query().findById(movieId);
+ if(!movie) {
+ return h.response({message: 'Movie not found'}).code(400);
+ }
+
+ //if movie already in favorite, return error
+ const favorite = await favoriteService.getByMovieAndUser(movieId, userId);
+ if(favorite) {
+ return h.response({message: 'Movie already in favorite'}).code(400);
+ }
+
+
+ // Appelle la méthode create du favoriteService en passant les champs nécessaires
+ return await favoriteService.create({
+ movie_id: movieId,
+ user_id: userId
+ });
+ }
+ },
+
+ {
+ method: 'GET',
+ path: '/favorites',
+ options: {
+ auth: {
+ scope : ['user', 'admin']
+ },
+ tags: ['api']
+ },
+ handler: async (request, h) => {
+ const { Favorite } = request.models();
+ const { favoriteService } = request.services();
+
+ // Appelle la méthode list du favoriteService pour récupérer tous les favoris
+ return await favoriteService.list();
+ }
+ },
+
+ {
+ method: 'DELETE',
+ path: '/favorites/remove',
+ options: {
+ auth: {
+ scope : ['user', 'admin']
+ },
+ tags: ['api'],
+ validate: {
+ payload: Joi.object({
+ movieId: Joi.number().required().example(1).description('Id of the movie'),
+ })
+ }
+ },
+ handler: async (request, h) => {
+ const { userService } = request.services();
+ const {favoriteService} = request.services();
+
+ const {movieId} = request.payload;
+
+ const userId = await userService.getByEmail(request.auth.credentials.email).then((user) => user.id)
+
+ //If movie not exist, return error
+ const { Movie } = request.models();
+
+ const movie = await Movie.query().findById(movieId);
+ if(!movie) {
+ return h.response({message: 'Movie not found'}).code(400);
+ }
+
+ // If the movie is not in the favorite, return an error
+ const favorite = await favoriteService.getByMovieAndUser(movieId, userId);
+ if(!favorite) {
+ return h.response({message: 'Movie not in favorite'}).code(400);
+ }
+
+ // Appelle la méthode remove du favoriteService pour supprimer le favori
+ return await favoriteService.delete({
+ movie_id: movieId,
+ user_id: userId
+ });
+ }
+ }
+]
\ No newline at end of file
diff --git a/lib/routes/movie.js b/lib/routes/movie.js
new file mode 100644
index 0000000..d8b28ff
--- /dev/null
+++ b/lib/routes/movie.js
@@ -0,0 +1,382 @@
+'use strict';
+
+const Joi = require('joi');
+const Jwt = require('@hapi/jwt');
+
+
+module.exports = [
+ {
+ method: 'POST',
+ path: '/movie',
+ options: {
+ auth: {
+ scope : 'admin'
+ },
+ tags: ['api'],
+ validate: {
+ payload: Joi.object({
+ title: Joi.string().required().min(3).example('The Matrix').description('Title of the movie'),
+ description: Joi.string().required().min(3).example('A computer hacker learns from mysterious rebels about the true nature of his reality and his role in the war against its controllers.').description('Description of the movie'),
+ director: Joi.string().required().min(3).example('Lana Wachowski').description('Director of the movie'),
+ releaseDate: Joi.date().required().example('1999-03-31').description('Release date of the movie'),
+ })
+ }
+ },
+ handler: async (request, h) => {
+ const { User } = request.models();
+ const { movieService } = request.services();
+
+ const { title, description, director, releaseDate } = request.payload;
+
+ //send email to all users
+ const { emailService } = request.services();
+ const users = await User.query();
+ for (const user of users) {
+ await emailService.sendEmail(
+ user.email,
+ user.firstName,
+ user.lastName,
+ 'New movie added',
+ '\n' +
+ '\n' +
+ '\n' +
+ '
\n' +
+ ' \n' +
+ ' \n' +
+ ' A new movie was added !\n' +
+ ' \n' +
+ '\n' +
+ '\n' +
+ '\n' +
+ '\n' +
+ ' \n' +
+ '
\n' +
+ '
Hello,
\n' +
+ '
A new movie was just added to the library.
\n' +
+ '
Go discover it now !
\n' +
+ '
Discover new movie\n' +
+ '
Happy exploring!
\n' +
+ '
\n' +
+ ' \n' +
+ '
\n' +
+ '\n' +
+ '\n' +
+ '\n'
+ );
+ }
+
+ // Appelle la méthode create du movieService en passant les champs nécessaires
+ return await movieService.create({
+ title: title,
+ description: description,
+ director: director,
+ releaseDate: releaseDate
+ });
+ }
+ },
+
+ {
+ method: 'GET',
+ path: '/movies',
+ options: {
+ tags: ['api'],
+ auth: false
+ },
+ handler: async (request, h) => {
+ const { Movie } = request.models();
+ const { movieService } = request.services();
+
+ // Appelle la méthode list du movieService pour récupérer tous les films
+ return await movieService.list();
+ }
+ },
+
+ {
+ method: 'GET',
+ path: '/movie/{id}',
+ options: {
+ tags: ['api'],
+ auth: false,
+ validate: {
+ params: Joi.object({
+ id: Joi.number().integer().required().example(1).description('ID of the movie')
+ })
+ }
+ },
+ handler: async (request, h) => {
+ const { Movie } = request.models();
+ const { movieService } = request.services();
+
+ const { id } = request.params;
+
+ // Appelle la méthode get du movieService pour récupérer le film par son ID
+ return await movieService.get(id);
+ }
+ },
+
+ {
+ method: 'DELETE',
+ path: '/movie/{id}',
+ options: {
+ auth: {
+ scope : 'admin'
+ },
+ tags: ['api'],
+ validate: {
+ params: Joi.object({
+ id: Joi.number().integer().positive().required().example(1).description('ID of the movie to delete')
+ })
+ }
+ },
+ handler: async (request, h) => {
+ const { movieService } = request.services();
+ const { id } = request.params;
+
+ // Appelle la méthode delete du movieService pour supprimer le film par son ID
+ await movieService.delete(id);
+
+ // Renvoie une réponse vide lorsque la suppression se déroule correctement
+ return 'deleted';
+ }
+ },
+
+ {
+ method: 'PATCH',
+ path: '/movie/{id}',
+ options: {
+ auth: {
+ scope : 'admin'
+ },
+ tags: ['api'],
+ validate: {
+ params: Joi.object({
+ id: Joi.number().integer().positive().required().example(1).description('ID of the movie to update')
+ }),
+ payload: Joi.object({
+ title: Joi.string().min(3).example('The Matrix').description('Title of the movie'),
+ description: Joi.string().min(3).example('A computer hacker learns from mysterious rebels about the true nature of his reality and his role in the war against its controllers.').description('Description of the movie'),
+ director: Joi.string().min(3).example('Lana Wachowski').description('Director of the movie'),
+ releaseDate: Joi.date().example('1999-03-31').description('Release date of the movie'),
+ })
+ }
+ },
+ handler: async (request, h) => {
+ const { movieService } = request.services();
+ const { id } = request.params;
+
+ //Email users who have favorited the movie
+ const { emailService } = request.services();
+ const { Favorite } = request.models();
+ const { User } = request.models();
+
+ const favorites = await Favorite.query().where('movie_id', id);
+
+ for (const favorite of favorites) {
+ const user = await User.query().findById(favorite.user_id);
+ await emailService.sendEmail(
+ user.email,
+ user.firstName,
+ user.lastName,
+ 'Movie updated',
+ '\n' +
+ '\n' +
+ '\n' +
+ '\n' +
+ ' \n' +
+ ' \n' +
+ ' A movie was updated !\n' +
+ ' \n' +
+ '\n' +
+ '\n' +
+ '\n' +
+ '\n' +
+ ' \n' +
+ '
\n' +
+ '
Hello,
\n' +
+ '
The movie ' + request.payload.title + ' was just updated in the library.
\n' +
+ '
Go check it out now !
\n' +
+ '
Discover updated movie\n' +
+ '
Happy exploring!
\n' +
+ '
\n' +
+ ' \n' +
+ '
\n' +
+ '\n' +
+ '\n' +
+ '\n'
+ );
+
+ }
+
+ // Appelle la méthode update du movieService pour mettre à jour le film par son ID
+ return await movieService.update(id, request.payload);
+ }
+ },
+
+ {
+ method: 'GET',
+ path: '/movie/csv',
+ options: {
+ auth: {
+ scope: 'admin'
+ },
+ tags: ['api']
+ },
+ handler: async (request, h) => {
+ const { rabbitmqService } = request.services();
+ const { Movie } = request.models();
+ const { movieService } = request.services();
+
+ try {
+ // Récupérer les films depuis la base de données
+ const movies = await Movie.query();
+
+ // Générer le fichier CSV
+ const csvData = await movieService.generateCsvData(movies);
+ console.log(csvData);
+
+ // Envoyer le fichier CSV via RabbitMQ pour l'envoi par e-mail
+ await rabbitmqService.sendCsvToQueue();
+
+ //When message is received, send the csv to the admin email
+ await rabbitmqService.receiveAndReturnCSV().then(
+ //Send the csv to the admin email
+ async () => {
+ const {emailService} = request.services();
+ await emailService.sendEmailWithAttachment(
+ request.auth.credentials.email,
+ 'Admin',
+ 'Admin',
+ 'Movie list in CSV',
+ 'Find the movie list in CSV format attached to this email.',
+ csvData
+ );
+ });
+
+ return h.response({ message: 'CSV sent to the admin email' }).code(200);
+
+ } catch (error) {
+ console.error('Erreur lors de l\'export CSV :', error);
+ return h.response({ message: 'Erreur lors du traitement de la requête' + error }).code(500);
+ }
+ }
+ }
+
+]
\ No newline at end of file
diff --git a/lib/routes/user.js b/lib/routes/user.js
index 5c2a6fd..6bef206 100644
--- a/lib/routes/user.js
+++ b/lib/routes/user.js
@@ -1,13 +1,257 @@
'use strict';
-module.exports = {
- method: 'get',
- path: '/user',
- options: {
- tags: ['api'],
- },
- handler: async (request, h) => {
+const Joi = require('joi');
+const { encryptSha1, compareSha1 } = require('iut-encrypt-cemal'); // Importe les fonctions d'encryption
+const Jwt = require('@hapi/jwt');
+
+
+module.exports = [
+ {
+ method: 'post',
+ path: '/user',
+ options: {
+ auth: false,
+ tags:['api'],
+ validate: {
+ payload: Joi.object({
+ scope: Joi.string().valid('admin', 'user').example('admin').description('Scope of the user (user or admin)'),
+ firstName: Joi.string().required().min(3).example('John').description('Firstname of the user'),
+ lastName: Joi.string().required().min(3).example('Doe').description('Lastname of the user'),
+ username: Joi.string().required().min(3).example('john_doe').description('Username of the user'),
+ email: Joi.string().email().required().example('john@example.com').description('Email address of the user'),
+ password: Joi.string().required().min(8).example('password123').description('Password of the user')
+ })
+ }
+ },
+ handler: async (request, h) => {
+ const { userService } = request.services();
+ const { emailService } = request.services();
+
+ //send welcome email
+ const { email, firstName, lastName } = request.payload;
+ await emailService.sendEmail(
+ email,
+ firstName,
+ lastName,
+ 'welcome',
+ '\n' +
+ '\n' +
+ '\n' +
+ '\n' +
+ ' \n' +
+ ' \n' +
+ ' Welcome to Our Application!\n' +
+ ' \n' +
+ '\n' +
+ '\n' +
+ '\n' +
+ '\n' +
+ ' \n' +
+ '
\n' +
+ '
Hello,
\n' +
+ '
We are thrilled to have you join our community! Your journey with us begins now, and we can\'t wait to\n' +
+ ' share\n' +
+ ' all the exciting features and updates we have in store for you.
\n' +
+ '
To get started, simply log in to your account and explore everything our application has to offer.\n' +
+ ' Don\'t hesitate to reach out to our support team if you have any questions or need assistance along the\n' +
+ ' way.
\n' +
+ '
Log In Now\n' +
+ '
Happy exploring!
\n' +
+ '
\n' +
+ ' \n' +
+ '
\n' +
+ '\n' +
+ '\n' +
+ '\n'
+ );
+
+ // Appelle la méthode create du userService en passant les champs nécessaires
+ return await userService.create({
+ scope: request.payload.scope,
+ firstName: request.payload.firstName,
+ lastName: request.payload.lastName,
+ username: request.payload.username,
+ email: request.payload.email,
+ password: request.payload.password
+ });
+ }
+ },
+ {
+ method: 'GET',
+ path: '/users',
+ options: {
+ tags: ['api'],
+ },
+ handler: async (request, h) => {
+ const { User } = request.models();
+
+ // Récupère tous les utilisateurs dans la base de données
+ const users = await User.query();
+
+ return users; // Renvoie tous les utilisateurs
+ }
+ },
+ {
+ method: 'DELETE',
+ path: '/user/{id}',
+ options: {
+ auth: {
+ scope : 'admin'
+ },
+ tags: ['api'],
+ validate: {
+ params: Joi.object({
+ id: Joi.number().integer().positive().required().example(1).description('ID of the user to delete')
+ })
+ }
+ },
+ handler: async (request, h) => {
+ const { userService } = request.services();
+ const { id } = request.params;
+
+ // Appelle la méthode delete du userService pour supprimer l'utilisateur par son ID
+ await userService.delete(id);
+
+ // Renvoie une réponse vide lorsque la suppression se déroule correctement
+ return 'deleted';
+ }
+ },
+ {
+ method: 'PATCH',
+ path: '/user/{id}',
+ options: {
+ auth: {
+ strategy: 'jwt',
+ scope : ['admin']
+ },
+ tags: ['api'],
+ validate: {
+ params: Joi.object({
+ id: Joi.number().integer().positive().required().example(1).description('ID of the user to update')
+ }),
+ payload: Joi.object({
+ scope: Joi.string().valid('admin').example('admin').description('New scope of the user'),
+ username: Joi.string().min(3).example('john_doe').description('New username of the user'),
+ firstName: Joi.string().min(3).example('John').description('New firstname of the user'),
+ lastName: Joi.string().min(3).example('Doe').description('New lastname of the user'),
+ email: Joi.string().email().example('john@example.com').description('New email address of the user'),
+ password: Joi.string().min(8).example('password123').description('New password of the user')
+
+ })
+ }
+ },
+ handler: async (request, h) => {
+ const { userService } = request.services();
+ const { id } = request.params;
+
+ // Appelle la méthode update du userService pour mettre à jour l'utilisateur par son ID
+ return await userService.update(id, request.payload);
+ }
+ },
+ {
+ method: 'POST',
+ path: '/user/login',
+ options: {
+ auth: false,
+ tags: ['api'],
+ validate: {
+ payload: Joi.object({
+ email: Joi.string().email().required().example('john@example.com').description('Email address of the user'),
+ password: Joi.string().min(8).required().example('password123').description('Password of the user')
+ })
+ }
+ },
+ handler: async (request, h) => {
+ const {User} = request.models();
+ const {email, password} = request.payload;
+
+ // Récupère l'utilisateur par son email depuis la base de données
+ const user = await User.query().findOne({email});
+
+ // Vérifie si l'utilisateur existe et si le mot de passe est valide
+ if (user && compareSha1(password, user.password)) {
+ // Génère un JWT avec les informations de l'utilisateur
+ const token = Jwt.token.generate({
+ aud: 'urn:audience:iut',
+ iss: 'urn:issuer:iut',
+ firstName: user.firstName,
+ lastName: user.lastName,
+ email: user.email,
+ scope: user.scope,
+ }, {
+ key: 'random_string', // Clé secrète pour signer le JWT (devrait être stockée en toute sécurité)
+ algorithm: 'HS512'
+ }, {
+ ttlSec: 14400 // Durée de validité du JWT en secondes (4 heures)
+ });
+
+ // Retourne le JWT généré
+ return {token};
+ } else {
+ // Si le mot de passe n'est pas correct, retourne une réponse 401 Unauthorized
+ return h.response().code(401);
+ }
+ },
- return { firstName: 'John', lastName: 'Doe'};
}
-};
+
+];
diff --git a/lib/services/email.js b/lib/services/email.js
new file mode 100644
index 0000000..cd05ce8
--- /dev/null
+++ b/lib/services/email.js
@@ -0,0 +1,74 @@
+const nodemailer = require('nodemailer');
+const {Service} = require("@hapipal/schmervice");
+
+// Fonction pour créer un transporteur SMTP réutilisable
+module.exports = class EmailService extends Service {
+
+ createTransporter() {
+ // Crée un transporteur SMTP réutilisable
+ return nodemailer.createTransport({
+ host: 'smtp.ethereal.email',
+ port: 587,
+ auth: {
+ user: 'adeline.ondricka5@ethereal.email',
+ pass: 'B4khRtXZPNqtr58bAu'
+ }
+ });
+ }
+
+ // Fonction pour envoyer un e-mail
+ async sendEmail(email, firstName, lastName, subject, html) {
+ // Crée un transporteur SMTP réutilisable
+ const transporter = this.createTransporter();
+
+ // Paramètres de l'e-mail
+ const mailOptions = {
+ from: process.env.EMAIL_FROM,
+ to: email,
+ subject: subject,
+ html: html
+
+ };
+
+ // Envoyer l'e-mail
+ try {
+ const info = await transporter.sendMail(mailOptions);
+ console.log('Message sent: %s', info.messageId);
+ console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info)); // For testing with Ethereal
+ return info;
+ } catch (error) {
+ console.error('Error sending email:', error);
+ throw error; // Propagate the error
+ }
+ }
+
+ async sendEmailWithAttachment(email, firstName, lastName, subject, html, attachment) {
+ // Crée un transporteur SMTP réutilisable
+ const transporter = this.createTransporter();
+
+ // Paramètres de l'e-mail
+ const mailOptions = {
+ from: process.env.EMAIL_FROM,
+ to: email,
+ subject: subject,
+ html: html,
+ attachments: [
+ {
+ filename: 'movies.csv',
+ content: attachment
+ }
+ ]
+ };
+
+ // Envoyer l'e-mail
+ try {
+ const info = await transporter.sendMail(mailOptions);
+ console.log('Message sent: %s', info.messageId);
+ console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info)); // For testing with Ethereal
+ return info;
+ } catch (error) {
+ console.error('Error sending email:', error);
+ throw error; // Propagate the error
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/services/favorite.js b/lib/services/favorite.js
new file mode 100644
index 0000000..05d2774
--- /dev/null
+++ b/lib/services/favorite.js
@@ -0,0 +1,37 @@
+'use strict';
+
+const { Service } = require('@hapipal/schmervice');
+
+
+module.exports = class FavoriteService extends Service {
+
+ async list() {
+ const { Favorite } = this.server.models();
+ return Favorite.query();
+ }
+
+ async create(payload) {
+ const { Favorite } = this.server.models();
+ return Favorite.query().insert(payload);
+ }
+
+ async get(id) {
+ const { Favorite } = this.server.models();
+ return Favorite.query().findById(id);
+ }
+
+ async update(id, payload) {
+ const { Favorite } = this.server.models();
+ return Favorite.query().patchAndFetchById(id, payload);
+ }
+
+ async delete(payload) {
+ const { Favorite } = this.server.models();
+ return Favorite.query().delete().where(payload);
+ }
+
+ async getByMovieAndUser(movieId, userId) {
+ const { Favorite } = this.server.models();
+ return Favorite.query().findOne({movie_id: movieId, user_id: userId});
+ }
+}
\ No newline at end of file
diff --git a/lib/services/logo.png b/lib/services/logo.png
new file mode 100644
index 0000000..66406c4
Binary files /dev/null and b/lib/services/logo.png differ
diff --git a/lib/services/movie.js b/lib/services/movie.js
new file mode 100644
index 0000000..8fbd413
--- /dev/null
+++ b/lib/services/movie.js
@@ -0,0 +1,48 @@
+'use strict';
+
+const { Service } = require('@hapipal/schmervice');
+const { parse } = require('json2csv');
+
+
+module.exports = class MovieService extends Service {
+
+ async list() {
+ const { Movie } = this.server.models();
+ return Movie.query();
+ }
+
+ async create(payload) {
+ const { Movie } = this.server.models();
+ return Movie.query().insert(payload);
+ }
+
+ async get(id) {
+ const { Movie } = this.server.models();
+ return Movie.query().findById(id);
+ }
+
+ async update(id, payload) {
+ const { Movie } = this.server.models();
+ return Movie.query().patchAndFetchById(id, payload);
+ }
+
+ async delete(id) {
+ const { Movie } = this.server.models();
+ return Movie.query().deleteById(id);
+ }
+
+ async generateCsvData(movies) {
+ try {
+ // Définir les champs CSV à partir des propriétés des films
+ const fields = ['title', 'description', 'director', 'releaseDate'];
+ console.log(parse(movies, {fields}));
+
+ // Convertir la liste des films en données CSV
+ return parse(movies, {fields});
+ } catch (error) {
+ console.error('Erreur lors de la génération des données CSV :', error);
+ throw error;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/lib/services/rabbitmq.js b/lib/services/rabbitmq.js
new file mode 100644
index 0000000..6b461f1
--- /dev/null
+++ b/lib/services/rabbitmq.js
@@ -0,0 +1,50 @@
+'use strict';
+
+const amqp = require('amqplib');
+const {Service} = require("@hapipal/schmervice");
+
+module.exports = class RabbitmqService extends Service {
+ async sendCsvToQueue() {
+ try {
+ const connection = await amqp.connect('amqp://localhost'); // Assurez-vous d'ajuster l'URL de connexion si nécessaire
+ const channel = await connection.createChannel();
+ const queue = 'csv_queue';
+
+ await channel.assertQueue(queue, { durable: false });
+ await channel.sendToQueue(queue, Buffer.from('Send the CSV PLZ!'));
+
+ await channel.close();
+ await connection.close();
+ } catch (error) {
+ console.error('Erreur lors de l\'envoi du CSV à la file d\'attente RabbitMQ :', error);
+ throw error;
+ }
+ }
+
+ async receiveAndReturnCSV() {
+ try {
+
+ const connection = await amqp.connect('amqp://localhost'); // Assurez-vous d'ajuster l'URL de connexion si nécessaire
+ const channel = await connection.createChannel();
+ const queue = 'csv_queue';
+
+ await channel.assertQueue(queue, { durable: false });
+ console.log('En attente de messages dans la file d\'attente RabbitMQ...');
+
+ //when message is received, send the csv to the admin email
+ await channel.consume(queue, async (message) => {
+ return message.content.toString();
+
+ });
+
+ await channel.close();
+ await connection.close();
+
+ } catch (error) {
+ console.error('Erreur lors de la réception du CSV de la file d\'attente RabbitMQ :', error);
+ throw error;
+ }
+ }
+
+
+};
diff --git a/lib/services/templates/welcome.html b/lib/services/templates/welcome.html
new file mode 100644
index 0000000..9e77faa
--- /dev/null
+++ b/lib/services/templates/welcome.html
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+ Welcome to Our Application!
+
+
+
+
+
+
+
+
Hello,
+
We are thrilled to have you join our community! Your journey with us begins now, and we can't wait to
+ share
+ all the exciting features and updates we have in store for you.
+
To get started, simply log in to your account and explore everything our application has to offer.
+ Don't hesitate to reach out to our support team if you have any questions or need assistance along the
+ way.
+
Log In Now
+
Happy exploring!
+
+
+
+
+
+
diff --git a/lib/services/user.js b/lib/services/user.js
new file mode 100644
index 0000000..184f9e3
--- /dev/null
+++ b/lib/services/user.js
@@ -0,0 +1,68 @@
+'use strict';
+
+const { Service } = require('@hapipal/schmervice');
+
+const { encryptSha1, compareSha1 } = require('iut-encrypt-cemal'); // Importe les fonctions d'encryption
+
+
+module.exports = class UserService extends Service {
+
+ create(user){
+
+ const { User } = this.server.models();
+
+ return User.query().insertAndFetch(user);
+ }
+
+ async update(id, userData) {
+ const { User } = this.server.models();
+
+ // Récupère l'utilisateur à mettre à jour
+ let user = await User.query().findById(id);
+
+ if (!user) {
+ throw new Error(`User with ID ${id} not found.`);
+ }
+
+ // Extrait les champs nécessaires de userData
+ const { firstName, lastName, username, email, password } = userData;
+
+ // Met à jour les champs de l'utilisateur avec les nouvelles valeurs
+ user = {
+ ...user,
+ firstName,
+ lastName,
+ username,
+ email,
+ password: password ? encryptSha1(password) : user.password // Si un nouveau mot de passe est fourni, encrypte-le
+ };
+
+ // Effectue la mise à jour de l'utilisateur dans la base de données
+ return await User.query().patchAndFetchById(id, user);
+ }
+
+ // Méthode pour supprimer un utilisateur
+ async delete(id) {
+ const { User } = this.server.models();
+
+ // Récupère l'utilisateur à supprimer
+ const user = await User.query().findById(id);
+
+ if (!user) {
+ throw new Error(`User with ID ${id} not found.`);
+ }
+
+ // Supprime l'utilisateur de la base de données
+ return await User.query().deleteById(id);
+ }
+
+ // Méthode pour récupérer un utilisateur par son email
+ async getByEmail(email) {
+ const {User} = this.server.models();
+ const user = await User.query().findOne({email});
+ return user;
+
+ }
+
+
+}
diff --git a/package-lock.json b/package-lock.json
index 5b464bb..7c0e62c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,17 +1,24 @@
{
- "name": "hapipal-boilerplate",
+ "name": "iut-encrypt-cemal",
"version": "3.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
- "name": "hapipal-boilerplate",
+ "name": "iut-encrypt-cemal",
"version": "3.0.0",
"dependencies": {
"@hapi/boom": "9.x.x",
+ "@hapi/jwt": "^3.2.0",
"@hapipal/haute-couture": "4.x.x",
+ "@hapipal/schmervice": "^3.0.0",
"@hapipal/schwifty": "6.x.x",
+ "amqplib": "^0.10.3",
+ "iut-encrypt-cemal": "^1.0.0",
"joi": "17.x.x",
+ "json2csv": "^6.0.0-alpha.2",
+ "mysql": "^2.18.1",
+ "nodemailer": "^6.9.8",
"objection": "2.x.x"
},
"devDependencies": {
@@ -21,7 +28,9 @@
"@hapi/glue": "8.x.x",
"@hapi/hapi": "20.x.x",
"@hapi/hoek": "9.x.x",
+ "@hapi/inert": "6.x.x",
"@hapi/lab": "24.x.x",
+ "@hapi/vision": "6.x.x",
"@hapipal/confidence": "6.x.x",
"@hapipal/hpal": "3.x.x",
"@hapipal/hpal-debug": "2.x.x",
@@ -30,6 +39,7 @@
"dotenv": "8.x.x",
"eslint": "7.x.x",
"exiting": "6.x.x",
+ "hapi-swagger": "14.x.x",
"knex": "0.21.x",
"sqlite3": "5.x.x"
},
@@ -46,6 +56,19 @@
"node": ">=0.10.0"
}
},
+ "node_modules/@acuminous/bitsyntax": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/@acuminous/bitsyntax/-/bitsyntax-0.1.2.tgz",
+ "integrity": "sha512-29lUK80d1muEQqiUsSo+3A0yP6CdspgC95EnKBMi22Xlwt79i/En4Vr67+cXhU+cZjbti3TgGGC5wy1stIywVQ==",
+ "dependencies": {
+ "buffer-more-ints": "~1.0.0",
+ "debug": "^4.3.4",
+ "safe-buffer": "~5.1.2"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
"node_modules/@ampproject/remapping": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz",
@@ -59,6 +82,68 @@
"node": ">=6.0.0"
}
},
+ "node_modules/@apidevtools/json-schema-ref-parser": {
+ "version": "9.1.2",
+ "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz",
+ "integrity": "sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg==",
+ "dev": true,
+ "dependencies": {
+ "@jsdevtools/ono": "^7.1.3",
+ "@types/json-schema": "^7.0.6",
+ "call-me-maybe": "^1.0.1",
+ "js-yaml": "^4.1.0"
+ }
+ },
+ "node_modules/@apidevtools/json-schema-ref-parser/node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "node_modules/@apidevtools/json-schema-ref-parser/node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/@apidevtools/openapi-schemas": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz",
+ "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@apidevtools/swagger-methods": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz",
+ "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==",
+ "dev": true
+ },
+ "node_modules/@apidevtools/swagger-parser": {
+ "version": "10.0.3",
+ "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz",
+ "integrity": "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==",
+ "dev": true,
+ "dependencies": {
+ "@apidevtools/json-schema-ref-parser": "^9.0.6",
+ "@apidevtools/openapi-schemas": "^2.0.4",
+ "@apidevtools/swagger-methods": "^3.0.2",
+ "@jsdevtools/ono": "^7.1.3",
+ "call-me-maybe": "^1.0.1",
+ "z-schema": "^5.0.1"
+ },
+ "peerDependencies": {
+ "openapi-types": ">=7"
+ }
+ },
"node_modules/@babel/code-frame": {
"version": "7.23.5",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz",
@@ -541,6 +626,28 @@
"@hapi/hoek": "9.x.x"
}
},
+ "node_modules/@hapi/catbox-object": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@hapi/catbox-object/-/catbox-object-3.0.1.tgz",
+ "integrity": "sha512-3w6E2DXtjWbmLYi4WcFUOor5jgrXN4PWhDrMrXKP/cEsFSfVSRJ0FhY2PXrhrUHwcllfKezYafWU3tQ5+8RO1w==",
+ "dependencies": {
+ "@hapi/boom": "^10.0.1",
+ "@hapi/hoek": "^11.0.2"
+ }
+ },
+ "node_modules/@hapi/catbox-object/node_modules/@hapi/boom": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/@hapi/boom/-/boom-10.0.1.tgz",
+ "integrity": "sha512-ERcCZaEjdH3OgSJlyjVk8pHIFeus91CjKP3v+MpgBNp5IvGzP2l/bRiD78nqYcKPaZdbKkK5vDBVPd2ohHBlsA==",
+ "dependencies": {
+ "@hapi/hoek": "^11.0.2"
+ }
+ },
+ "node_modules/@hapi/catbox-object/node_modules/@hapi/hoek": {
+ "version": "11.0.4",
+ "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-11.0.4.tgz",
+ "integrity": "sha512-PnsP5d4q7289pS2T2EgGz147BFJ2Jpb4yrEdkpz2IhgEUzos1S7HTl7ezWh1yfYzYlj89KzLdCRkqsP6SIryeQ=="
+ },
"node_modules/@hapi/code": {
"version": "8.0.7",
"resolved": "https://registry.npmjs.org/@hapi/code/-/code-8.0.7.tgz",
@@ -663,6 +770,20 @@
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz",
"integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ=="
},
+ "node_modules/@hapi/inert": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/@hapi/inert/-/inert-6.0.5.tgz",
+ "integrity": "sha512-eVAdUVhJLmmXLM/Zt7u5H5Vzazs9GKe4zfPK2b97ePHEfs3g/AQkxHfYQjJqMy11hvyB7a21Z6rBEA0R//dtXw==",
+ "dev": true,
+ "dependencies": {
+ "@hapi/ammo": "5.x.x",
+ "@hapi/boom": "9.x.x",
+ "@hapi/bounce": "2.x.x",
+ "@hapi/hoek": "9.x.x",
+ "@hapi/validate": "1.x.x",
+ "lru-cache": "^6.0.0"
+ }
+ },
"node_modules/@hapi/iron": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/@hapi/iron/-/iron-6.0.0.tgz",
@@ -675,6 +796,99 @@
"@hapi/hoek": "9.x.x"
}
},
+ "node_modules/@hapi/jwt": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/@hapi/jwt/-/jwt-3.2.0.tgz",
+ "integrity": "sha512-2EU5zdr0petG63J2RHiagGByA1Qr6qzxMmrJJ3/0cm78be1Lq4vi038YgKJvbBSxSboIp5SWGZdYB6+CJlqEoQ==",
+ "dependencies": {
+ "@hapi/b64": "^6.0.0",
+ "@hapi/boom": "^10.0.0",
+ "@hapi/bounce": "^3.0.0",
+ "@hapi/bourne": "^3.0.0",
+ "@hapi/catbox-object": "^3.0.0",
+ "@hapi/cryptiles": "^6.0.0",
+ "@hapi/hoek": "^10.0.0",
+ "@hapi/wreck": "^18.0.0",
+ "ecdsa-sig-formatter": "^1.0.0",
+ "joi": "^17.2.1"
+ }
+ },
+ "node_modules/@hapi/jwt/node_modules/@hapi/b64": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/@hapi/b64/-/b64-6.0.1.tgz",
+ "integrity": "sha512-ZvjX4JQReUmBheeCq+S9YavcnMMHWqx3S0jHNXWIM1kQDxB9cyfSycpVvjfrKcIS8Mh5N3hmu/YKo4Iag9g2Kw==",
+ "dependencies": {
+ "@hapi/hoek": "^11.0.2"
+ }
+ },
+ "node_modules/@hapi/jwt/node_modules/@hapi/b64/node_modules/@hapi/hoek": {
+ "version": "11.0.4",
+ "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-11.0.4.tgz",
+ "integrity": "sha512-PnsP5d4q7289pS2T2EgGz147BFJ2Jpb4yrEdkpz2IhgEUzos1S7HTl7ezWh1yfYzYlj89KzLdCRkqsP6SIryeQ=="
+ },
+ "node_modules/@hapi/jwt/node_modules/@hapi/boom": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/@hapi/boom/-/boom-10.0.1.tgz",
+ "integrity": "sha512-ERcCZaEjdH3OgSJlyjVk8pHIFeus91CjKP3v+MpgBNp5IvGzP2l/bRiD78nqYcKPaZdbKkK5vDBVPd2ohHBlsA==",
+ "dependencies": {
+ "@hapi/hoek": "^11.0.2"
+ }
+ },
+ "node_modules/@hapi/jwt/node_modules/@hapi/boom/node_modules/@hapi/hoek": {
+ "version": "11.0.4",
+ "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-11.0.4.tgz",
+ "integrity": "sha512-PnsP5d4q7289pS2T2EgGz147BFJ2Jpb4yrEdkpz2IhgEUzos1S7HTl7ezWh1yfYzYlj89KzLdCRkqsP6SIryeQ=="
+ },
+ "node_modules/@hapi/jwt/node_modules/@hapi/bounce": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@hapi/bounce/-/bounce-3.0.1.tgz",
+ "integrity": "sha512-G+/Pp9c1Ha4FDP+3Sy/Xwg2O4Ahaw3lIZFSX+BL4uWi64CmiETuZPxhKDUD4xBMOUZbBlzvO8HjiK8ePnhBadA==",
+ "dependencies": {
+ "@hapi/boom": "^10.0.1",
+ "@hapi/hoek": "^11.0.2"
+ }
+ },
+ "node_modules/@hapi/jwt/node_modules/@hapi/bounce/node_modules/@hapi/hoek": {
+ "version": "11.0.4",
+ "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-11.0.4.tgz",
+ "integrity": "sha512-PnsP5d4q7289pS2T2EgGz147BFJ2Jpb4yrEdkpz2IhgEUzos1S7HTl7ezWh1yfYzYlj89KzLdCRkqsP6SIryeQ=="
+ },
+ "node_modules/@hapi/jwt/node_modules/@hapi/bourne": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-3.0.0.tgz",
+ "integrity": "sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w=="
+ },
+ "node_modules/@hapi/jwt/node_modules/@hapi/cryptiles": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/@hapi/cryptiles/-/cryptiles-6.0.1.tgz",
+ "integrity": "sha512-9GM9ECEHfR8lk5ASOKG4+4ZsEzFqLfhiryIJ2ISePVB92OHLp/yne4m+zn7z9dgvM98TLpiFebjDFQ0UHcqxXQ==",
+ "dependencies": {
+ "@hapi/boom": "^10.0.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@hapi/jwt/node_modules/@hapi/hoek": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-10.0.1.tgz",
+ "integrity": "sha512-CvlW7jmOhWzuqOqiJQ3rQVLMcREh0eel4IBnxDx2FAcK8g7qoJRQK4L1CPBASoCY6y8e6zuCy3f2g+HWdkzcMw=="
+ },
+ "node_modules/@hapi/jwt/node_modules/@hapi/wreck": {
+ "version": "18.0.1",
+ "resolved": "https://registry.npmjs.org/@hapi/wreck/-/wreck-18.0.1.tgz",
+ "integrity": "sha512-OLHER70+rZxvDl75xq3xXOfd3e8XIvz8fWY0dqg92UvhZ29zo24vQgfqgHSYhB5ZiuFpSLeriOisAlxAo/1jWg==",
+ "dependencies": {
+ "@hapi/boom": "^10.0.1",
+ "@hapi/bourne": "^3.0.0",
+ "@hapi/hoek": "^11.0.2"
+ }
+ },
+ "node_modules/@hapi/jwt/node_modules/@hapi/wreck/node_modules/@hapi/hoek": {
+ "version": "11.0.4",
+ "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-11.0.4.tgz",
+ "integrity": "sha512-PnsP5d4q7289pS2T2EgGz147BFJ2Jpb4yrEdkpz2IhgEUzos1S7HTl7ezWh1yfYzYlj89KzLdCRkqsP6SIryeQ=="
+ },
"node_modules/@hapi/lab": {
"version": "24.7.1",
"resolved": "https://registry.npmjs.org/@hapi/lab/-/lab-24.7.1.tgz",
@@ -861,8 +1075,7 @@
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@hapi/vision/-/vision-6.1.0.tgz",
"integrity": "sha512-ll0zJ13xDxCYIWvC1aq/8srK0bTXfqZYGT+YoTi/fS42gYYJ3dnvmS35r8T8XXtJ6F6cmya8G2cRlMR/z11LQw==",
- "optional": true,
- "peer": true,
+ "devOptional": true,
"dependencies": {
"@hapi/boom": "9.x.x",
"@hapi/bounce": "2.x.x",
@@ -995,6 +1208,17 @@
}
}
},
+ "node_modules/@hapipal/schmervice": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@hapipal/schmervice/-/schmervice-3.0.0.tgz",
+ "integrity": "sha512-1v7GY6BPHP9vLrUkQ1mi8qnzrAKKLy0J0rRznhogkILcvuwZXMHuMuSBrmmyEmHh4fPvL+WxPgeINjrL0TRtxQ==",
+ "engines": {
+ "node": ">=16"
+ },
+ "peerDependencies": {
+ "@hapi/hapi": ">=20 <22"
+ }
+ },
"node_modules/@hapipal/schwifty": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/@hapipal/schwifty/-/schwifty-6.2.0.tgz",
@@ -1101,6 +1325,12 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
+ "node_modules/@jsdevtools/ono": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz",
+ "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==",
+ "dev": true
+ },
"node_modules/@nicolo-ribaudo/eslint-scope-5-internals": {
"version": "5.1.1-v1",
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz",
@@ -1163,6 +1393,17 @@
"resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz",
"integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ=="
},
+ "node_modules/@streamparser/json": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/@streamparser/json/-/json-0.0.6.tgz",
+ "integrity": "sha512-vL9EVn/v+OhZ+Wcs6O4iKE9EUpwHUqHmCtNUMWjqp+6dr85+XPOSGTEsqYNq1Vn04uk9SWlOVmx9J48ggJVT2Q=="
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true
+ },
"node_modules/abbrev": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
@@ -1205,6 +1446,41 @@
"url": "https://github.com/sponsors/epoberezkin"
}
},
+ "node_modules/amqplib": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.10.3.tgz",
+ "integrity": "sha512-UHmuSa7n8vVW/a5HGh2nFPqAEr8+cD4dEZ6u9GjP91nHfr1a54RyAKyra7Sb5NH7NBKOUlyQSMXIp0qAixKexw==",
+ "dependencies": {
+ "@acuminous/bitsyntax": "^0.1.2",
+ "buffer-more-ints": "~1.0.0",
+ "readable-stream": "1.x >=1.1.9",
+ "url-parse": "~1.5.10"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/amqplib/node_modules/isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="
+ },
+ "node_modules/amqplib/node_modules/readable-stream": {
+ "version": "1.1.14",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+ "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.1",
+ "isarray": "0.0.1",
+ "string_decoder": "~0.10.x"
+ }
+ },
+ "node_modules/amqplib/node_modules/string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="
+ },
"node_modules/ansi-colors": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
@@ -1508,6 +1784,14 @@
"tweetnacl": "^0.14.3"
}
},
+ "node_modules/bignumber.js": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz",
+ "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==",
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/bin-v8-flags-filter": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/bin-v8-flags-filter/-/bin-v8-flags-filter-1.2.0.tgz",
@@ -1587,6 +1871,11 @@
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true
},
+ "node_modules/buffer-more-ints": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz",
+ "integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg=="
+ },
"node_modules/cache-base": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
@@ -1606,6 +1895,12 @@
"node": ">=0.10.0"
}
},
+ "node_modules/call-me-maybe": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz",
+ "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==",
+ "dev": true
+ },
"node_modules/callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -1680,6 +1975,14 @@
"node": ">=4"
}
},
+ "node_modules/charenc": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz",
+ "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==",
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/chownr": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
@@ -1801,6 +2104,16 @@
"node": ">= 0.8"
}
},
+ "node_modules/commander": {
+ "version": "9.5.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
+ "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
+ "dev": true,
+ "optional": true,
+ "engines": {
+ "node": "^12.20.0 || >=14"
+ }
+ },
"node_modules/component-emitter": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz",
@@ -1838,8 +2151,7 @@
"node_modules/core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
- "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
- "devOptional": true
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
},
"node_modules/cross-spawn": {
"version": "7.0.3",
@@ -1855,6 +2167,14 @@
"node": ">= 8"
}
},
+ "node_modules/crypt": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
+ "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==",
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
@@ -1877,7 +2197,6 @@
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
- "dev": true,
"dependencies": {
"ms": "2.1.2"
},
@@ -2026,6 +2345,14 @@
"safer-buffer": "^2.1.0"
}
},
+ "node_modules/ecdsa-sig-formatter": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
+ "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
"node_modules/electron-to-chromium": {
"version": "1.4.647",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.647.tgz",
@@ -2826,6 +3153,12 @@
"node": ">= 0.12"
}
},
+ "node_modules/format-util": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/format-util/-/format-util-1.0.5.tgz",
+ "integrity": "sha512-varLbTj0e0yVyRpqQhuWV+8hlePAgaoFRhNFj50BNjEIrw1/DphHSObtqwskVCPWNgzwPoQrZAbfa/SBiicNeg==",
+ "dev": true
+ },
"node_modules/fragment-cache": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
@@ -3149,6 +3482,28 @@
"node": ">=0.10.0"
}
},
+ "node_modules/hapi-swagger": {
+ "version": "14.5.5",
+ "resolved": "https://registry.npmjs.org/hapi-swagger/-/hapi-swagger-14.5.5.tgz",
+ "integrity": "sha512-qhqmr48+CZrhHDwhg0bHuQ3EW1VWnP71fG8gg5FPAEjF5iIHxIVtRZvioN3dPcBEuk/EqiLoPj/x3va51TbEEA==",
+ "dev": true,
+ "dependencies": {
+ "@hapi/boom": "^9.1.4",
+ "@hapi/hoek": "^9.3.0",
+ "handlebars": "^4.7.7",
+ "http-status": "^1.5.2",
+ "json-schema-ref-parser": "^6.1.0",
+ "swagger-parser": "^10.0.3",
+ "swagger-ui-dist": "^4.11.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "@hapi/hapi": "^20.2.2",
+ "joi": "17.x"
+ }
+ },
"node_modules/har-schema": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
@@ -3297,6 +3652,15 @@
"npm": ">=1.3.7"
}
},
+ "node_modules/http-status": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/http-status/-/http-status-1.7.3.tgz",
+ "integrity": "sha512-GS8tL1qHT2nBCMJDYMHGkkkKQLNkIAHz37vgO68XKvzv+XyqB4oh/DfmMHdtRzfqSJPj1xKG2TaELZtlCz6BEQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
"node_modules/iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
@@ -3377,8 +3741,7 @@
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "devOptional": true
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"node_modules/ini": {
"version": "1.3.8",
@@ -3573,6 +3936,14 @@
"dev": true,
"optional": true
},
+ "node_modules/iut-encrypt-cemal": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/iut-encrypt-cemal/-/iut-encrypt-cemal-1.0.0.tgz",
+ "integrity": "sha512-f+BjMCIRGDLfKRFofgD3OIm7gbwowNp/clvzb9ohEBcYWjjp86wvW5PgVEe34GHrQlVRHSu0qxHZxjFSR9V+EA==",
+ "dependencies": {
+ "sha1": "^1.1.1"
+ }
+ },
"node_modules/joi": {
"version": "17.12.0",
"resolved": "https://registry.npmjs.org/joi/-/joi-17.12.0.tgz",
@@ -3636,6 +4007,18 @@
"dev": true,
"optional": true
},
+ "node_modules/json-schema-ref-parser": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/json-schema-ref-parser/-/json-schema-ref-parser-6.1.0.tgz",
+ "integrity": "sha512-pXe9H1m6IgIpXmE5JSb8epilNTGsmTb2iPohAXpOdhqGFbQjNeHHsZxU+C8w6T81GZxSPFLeUoqDJmzxx5IGuw==",
+ "deprecated": "Please switch to @apidevtools/json-schema-ref-parser",
+ "dev": true,
+ "dependencies": {
+ "call-me-maybe": "^1.0.1",
+ "js-yaml": "^3.12.1",
+ "ono": "^4.0.11"
+ }
+ },
"node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
@@ -3654,6 +4037,31 @@
"dev": true,
"optional": true
},
+ "node_modules/json2csv": {
+ "version": "6.0.0-alpha.2",
+ "resolved": "https://registry.npmjs.org/json2csv/-/json2csv-6.0.0-alpha.2.tgz",
+ "integrity": "sha512-nJ3oP6QxN8z69IT1HmrJdfVxhU1kLTBVgMfRnNZc37YEY+jZ4nU27rBGxT4vaqM/KUCavLRhntmTuBFqZLBUcA==",
+ "dependencies": {
+ "@streamparser/json": "^0.0.6",
+ "commander": "^6.2.0",
+ "lodash.get": "^4.4.2"
+ },
+ "bin": {
+ "json2csv": "bin/json2csv.js"
+ },
+ "engines": {
+ "node": ">= 12",
+ "npm": ">= 6.13.0"
+ }
+ },
+ "node_modules/json2csv/node_modules/commander": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
+ "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/json5": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
@@ -3820,6 +4228,17 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
+ "node_modules/lodash.get": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
+ "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ=="
+ },
+ "node_modules/lodash.isequal": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
+ "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
+ "dev": true
+ },
"node_modules/lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
@@ -4092,6 +4511,34 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
+ "node_modules/mysql": {
+ "version": "2.18.1",
+ "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz",
+ "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==",
+ "dependencies": {
+ "bignumber.js": "9.0.0",
+ "readable-stream": "2.3.7",
+ "safe-buffer": "5.1.2",
+ "sqlstring": "2.3.1"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mysql/node_modules/readable-stream": {
+ "version": "2.3.7",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+ "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
"node_modules/nanomatch": {
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
@@ -4360,6 +4807,14 @@
"integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==",
"dev": true
},
+ "node_modules/nodemailer": {
+ "version": "6.9.8",
+ "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.8.tgz",
+ "integrity": "sha512-cfrYUk16e67Ks051i4CntM9kshRYei1/o/Gi8K1d+R34OIs21xdFnW7Pt7EucmVKA0LKtqUGNcjMZ7ehjl49mQ==",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/nopt": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
@@ -4546,6 +5001,22 @@
"wrappy": "1"
}
},
+ "node_modules/ono": {
+ "version": "4.0.11",
+ "resolved": "https://registry.npmjs.org/ono/-/ono-4.0.11.tgz",
+ "integrity": "sha512-jQ31cORBFE6td25deYeD80wxKBMj+zBmHTrVxnc6CKhx8gho6ipmWM5zj/oeoqioZ99yqBls9Z/9Nss7J26G2g==",
+ "dev": true,
+ "dependencies": {
+ "format-util": "^1.0.3"
+ }
+ },
+ "node_modules/openapi-types": {
+ "version": "12.1.3",
+ "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz",
+ "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==",
+ "dev": true,
+ "peer": true
+ },
"node_modules/optionator": {
"version": "0.9.3",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
@@ -4875,8 +5346,7 @@
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
- "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
- "devOptional": true
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
"node_modules/progress": {
"version": "2.0.3",
@@ -4912,6 +5382,11 @@
"node": ">=0.6"
}
},
+ "node_modules/querystringify": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
+ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ=="
+ },
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@@ -5073,6 +5548,11 @@
"node": ">=0.10.0"
}
},
+ "node_modules/requires-port": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
+ },
"node_modules/resolve": {
"version": "1.22.8",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
@@ -5175,8 +5655,7 @@
"node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
- "devOptional": true
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"node_modules/safe-regex": {
"version": "1.1.0",
@@ -5250,6 +5729,18 @@
"node": ">=0.10.0"
}
},
+ "node_modules/sha1": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/sha1/-/sha1-1.1.1.tgz",
+ "integrity": "sha512-dZBS6OrMjtgVkopB1Gmo4RQCDKiZsqcpAQpkV/aaj+FCrCg8r4I4qMkDPQjBgLIxlmu9k4nUbWq6ohXahOneYA==",
+ "dependencies": {
+ "charenc": ">= 0.0.1",
+ "crypt": ">= 0.0.1"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -5541,6 +6032,14 @@
}
}
},
+ "node_modules/sqlstring": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz",
+ "integrity": "sha512-ooAzh/7dxIG5+uDik1z/Rd1vli0+38izZhGzSa34FwR7IbelPWCCKSNIl8jlL/F7ERvy8CB2jNeM1E9i9mXMAQ==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/sshpk": {
"version": "1.18.0",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz",
@@ -5594,7 +6093,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
- "devOptional": true,
"dependencies": {
"safe-buffer": "~5.1.0"
}
@@ -5691,6 +6189,24 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/swagger-parser": {
+ "version": "10.0.3",
+ "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.3.tgz",
+ "integrity": "sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg==",
+ "dev": true,
+ "dependencies": {
+ "@apidevtools/swagger-parser": "10.0.3"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/swagger-ui-dist": {
+ "version": "4.19.1",
+ "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.19.1.tgz",
+ "integrity": "sha512-n/gFn+R7G/BXWwl5UZLw6F1YgWOlf3zkwGlsPhTMhNtAAolBGKg0JS5b2RKt5NI6/hSopVaSrki2wTIMUDDy2w==",
+ "dev": true
+ },
"node_modules/table": {
"version": "6.8.1",
"resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz",
@@ -6017,6 +6533,15 @@
"integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==",
"deprecated": "Please see https://github.com/lydell/urix#deprecated"
},
+ "node_modules/url-parse": {
+ "version": "1.5.10",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
+ "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
+ "dependencies": {
+ "querystringify": "^2.1.1",
+ "requires-port": "^1.0.0"
+ }
+ },
"node_modules/use": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
@@ -6028,8 +6553,7 @@
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "devOptional": true
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"node_modules/uuid": {
"version": "3.4.0",
@@ -6059,6 +6583,15 @@
"node": ">= 0.10"
}
},
+ "node_modules/validator": {
+ "version": "13.11.0",
+ "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz",
+ "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
"node_modules/verror": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
@@ -6149,6 +6682,26 @@
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
+ },
+ "node_modules/z-schema": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz",
+ "integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==",
+ "dev": true,
+ "dependencies": {
+ "lodash.get": "^4.4.2",
+ "lodash.isequal": "^4.5.0",
+ "validator": "^13.7.0"
+ },
+ "bin": {
+ "z-schema": "bin/z-schema"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "commander": "^9.4.1"
+ }
}
}
}
diff --git a/package.json b/package.json
index 9041b92..823d048 100644
--- a/package.json
+++ b/package.json
@@ -1,17 +1,24 @@
{
- "name": "hapipal-boilerplate",
+ "name": "iut-encrypt-cemal",
"version": "3.0.0",
"main": "lib/index.js",
"scripts": {
"start": "node server",
- "test": "lab -a @hapi/code -L",
+ "test": "lab -a @hapi/code -I \"__core-js_shared__,CSS,regeneratorRuntime,core\" -L",
"lint": "eslint ."
},
"dependencies": {
"@hapi/boom": "9.x.x",
+ "@hapi/jwt": "^3.2.0",
"@hapipal/haute-couture": "4.x.x",
+ "@hapipal/schmervice": "^3.0.0",
"@hapipal/schwifty": "6.x.x",
+ "amqplib": "^0.10.3",
+ "iut-encrypt-cemal": "^1.0.0",
"joi": "17.x.x",
+ "json2csv": "^6.0.0-alpha.2",
+ "mysql": "^2.18.1",
+ "nodemailer": "^6.9.8",
"objection": "2.x.x"
},
"peerDependencies": {
@@ -24,7 +31,9 @@
"@hapi/glue": "8.x.x",
"@hapi/hapi": "20.x.x",
"@hapi/hoek": "9.x.x",
+ "@hapi/inert": "6.x.x",
"@hapi/lab": "24.x.x",
+ "@hapi/vision": "6.x.x",
"@hapipal/confidence": "6.x.x",
"@hapipal/hpal": "3.x.x",
"@hapipal/hpal-debug": "2.x.x",
@@ -33,6 +42,7 @@
"dotenv": "8.x.x",
"eslint": "7.x.x",
"exiting": "6.x.x",
+ "hapi-swagger": "14.x.x",
"knex": "0.21.x",
"sqlite3": "5.x.x"
}
diff --git a/server/manifest.js b/server/manifest.js
index fa9797d..2010831 100644
--- a/server/manifest.js
+++ b/server/manifest.js
@@ -35,25 +35,28 @@ module.exports = new Confidence.Store({
options: {}
},
{
- plugin: '@hapipal/schwifty',
- options: {
- $filter: 'NODE_ENV',
- $default: {},
- $base: {
- migrateOnStart: true,
- knex: {
- client: 'sqlite3',
- useNullAsDefault: true, // Suggested for sqlite3
- connection: {
- filename: ':memory:'
- },
- migrations: {
- stub: Schwifty.migrationsStubPath
+ plugin: './plugins/swagger'
+ },
+ {
+ plugin : '@hapipal/schwifty',
+ options : {
+ $filter : 'NODE_ENV',
+ $default : {},
+ $base : {
+ migrateOnStart : true,
+ knex : {
+ client : 'mysql',
+ connection : {
+ host : 'localhost',
+ user : 'root',
+ password : 'hapi',
+ database : 'user',
+ port : 3307
}
}
},
- production: {
- migrateOnStart: false
+ production : {
+ migrateOnStart : false
}
}
},
diff --git a/server/plugins/swagger.js b/server/plugins/swagger.js
index 19595d1..ab052ba 100644
--- a/server/plugins/swagger.js
+++ b/server/plugins/swagger.js
@@ -17,9 +17,17 @@ module.exports = {
options: {
info: {
version: Package.version
- }
+ },
+ securityDefinitions : {
+ 'jwt' : {
+ 'type' : 'apiKey',
+ 'name' : 'Authorization',
+ 'in' : 'header'
+ }
+ },
+ security : [{ 'jwt' : [] }],
}
}
]);
}
-};
\ No newline at end of file
+};