Merge pull request 'master' (#9) from master into WORK-RHA
continuous-integration/drone/push Build is passing Details

Reviewed-on: #9
WORK-RHA
Rayhân HASSOU 1 year ago
commit f5d9064ce1

@ -9,6 +9,17 @@ trigger:
steps:
- name: api-build
image: node:latest
environment:
DB_USERNAME:
from_secret: SECRET_DB_USERNAME
DB_DBHOST:
from_secret: SECRET_DB_DBHOST
DB_DBNAME:
from_secret: SECRET_DB_DBNAME
DB_USERPASSWORD:
from_secret: SECRET_DB_USERPASSWORD
DB_PORT:
from_secret: SECRET_DB_PORT
commands:
- cd ./API-Project
- npm install
@ -16,6 +27,17 @@ steps:
- name: test
image: node:latest
environment:
DB_USERNAME:
from_secret: SECRET_DB_USERNAME
DB_DBHOST:
from_secret: SECRET_DB_DBHOST
DB_DBNAME:
from_secret: SECRET_DB_DBNAME
DB_USERPASSWORD:
from_secret: SECRET_DB_USERPASSWORD
DB_PORT:
from_secret: SECRET_DB_PORT
commands:
- cd ./API-Project
- npm run test
@ -23,6 +45,17 @@ steps:
- name: docker-build-and-push
image: plugins/docker
environment:
DB_USERNAME:
from_secret: SECRET_DB_USERNAME
DB_DBHOST:
from_secret: SECRET_DB_DBHOST
DB_DBNAME:
from_secret: SECRET_DB_DBNAME
DB_USERPASSWORD:
from_secret: SECRET_DB_USERPASSWORD
DB_PORT:
from_secret: SECRET_DB_PORT
settings:
dockerfile: API-Project/Dockerfile
context: API-Project
@ -38,11 +71,21 @@ steps:
- name: deploy-container
image: hub.codefirst.iut.uca.fr/thomas.bellembois/codefirst-dockerproxy-clientdrone:latest
environment:
IMAGENAME: hub.codefirst.iut.uca.fr/rayhan.hassou/leftovers_api:latest
CONTAINERNAME: left-over-container
COMMAND: create
OVERWRITE: true
ADMINS: louison.parant,remi.regnault,rayhan.hassou
IMAGENAME: hub.codefirst.iut.uca.fr/rayhan.hassou/leftovers_api:latest
CONTAINERNAME: left-over-container
COMMAND: create
OVERWRITE: true
ADMINS: louison.parant,remi.regnault,rayhan.hassou
DB_USERNAME:
from_secret: SECRET_DB_USERNAME
DB_DBHOST:
from_secret: SECRET_DB_DBHOST
DB_DBNAME:
from_secret: SECRET_DB_DBNAME
DB_USERPASSWORD:
from_secret: SECRET_DB_USERPASSWORD
DB_PORT:
from_secret: SECRET_DB_PORT
depends_on: [ docker-build-and-push ]
- name: code-analysis

@ -12,7 +12,9 @@
"@types/express": "^4.17.21",
"@types/morgan": "^1.9.9",
"cors": "^2.8.5",
"dotenv": "^16.3.1",
"express": "^4.18.2",
"helmet": "^7.1.0",
"morgan": "^1.10.0",
"nodemon": "^3.0.1",
"pg": "^8.11.3",
@ -2260,6 +2262,17 @@
"node": ">=8"
}
},
"node_modules/dotenv": {
"version": "16.3.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
"integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/motdotla/dotenv?sponsor=1"
}
},
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@ -2774,6 +2787,14 @@
"node": ">= 0.4"
}
},
"node_modules/helmet": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/helmet/-/helmet-7.1.0.tgz",
"integrity": "sha512-g+HZqgfbpXdCkme/Cd/mZkV0aV3BZZZSugecH03kl38m/Kmdx8jKjBikpDj2cr+Iynv4KpYEviojNdTJActJAg==",
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/html-escaper": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",

@ -14,8 +14,10 @@
"dependencies": {
"@types/express": "^4.17.21",
"@types/morgan": "^1.9.9",
"dotenv": "^16.3.1",
"cors": "^2.8.5",
"express": "^4.18.2",
"helmet": "^7.1.0",
"morgan": "^1.10.0",
"nodemon": "^3.0.1",
"pg": "^8.11.3",

@ -1,7 +1,5 @@
import { Request, Response, NextFunction } from "express";
import { Router } from "express";
import { Exceptions } from "../utils/exception";
import { IIngredient, Ingredient } from "../types/ingredients";
import { IngredientsGateway } from "../gateways/ingredients.gateway";
const IngredientsController = Router()
@ -67,7 +65,6 @@ IngredientsController.get('/:id', async (req, res) => {
res.status(404).send('not found')
}
else {
const ingredient_ingredient = ingredient as Ingredient
res.status(200).json(ingredient)
}
} catch (error) {

@ -1,5 +1,4 @@
import { Router } from "express";
import { Recipe } from "../types/recipes";
import { Exceptions } from "../utils/exception";
import { RecipeGateway } from "../gateways/recipe.gateway";
@ -33,7 +32,6 @@ RecipesController.get('/:id', async (req, res) => {
res.status(404).send('not found')
}
else {
const ingredient_ingredient = recipe as Recipe
res.status(200).json(recipe)
}
} catch (error) {

@ -1,5 +1,4 @@
import { Router } from "express";
import { Recipe } from "../types/recipes";
import { Exceptions } from "../utils/exception";
import { StepsGateway } from "../gateways/steps.gateway";
@ -22,8 +21,6 @@ StepsController.get('/:id', async (req, res) => {
res.status(404).send('not found')
}
else {
const steps_steps = steps as string[]
res.status(200).json(steps)
}
} catch (error) {

@ -1,34 +1,20 @@
import { Client } from "pg"
const Pool = require('pg').Pool
export const pool = new Pool({
user: 'rgregnault',
host: 'localhost',
database: 'leftovers',
password: 'motdepasse',
port: 5432,
})
import { Pool, PoolClient } from "pg"
export class Connection {
public client:Client
clientIsConnected:boolean = false
private pool:Pool
constructor() {
this.client = new Client({
user: 'leftovers_appuser',
host: 'postgresql-leftovers.alwaysdata.net',
database: 'leftovers_recipedb',
password: 'UsrPsswd',
port: 5432,
this.pool = new Pool({
user: process.env.DB_USERNAME,
host: process.env.DB_DBHOST,
database: process.env.DB_DBNAME,
password: process.env.DB_USERPASSWORD,
port: Number(process.env.DB_PORT),
})
}
public async connect() {
if (!this.clientIsConnected) {
await this.client.connect()
this.clientIsConnected = true
}
public async getPoolClient() : Promise<PoolClient> {
return await this.pool.connect()
}
}

@ -9,9 +9,11 @@ export class IngredientsGateway {
}
async getAll() : Promise<Ingredient[]> {
this.connection.connect()
const client = await this.connection.getPoolClient()
const res = await this.connection.client.query('SELECT * FROM Ingredients ORDER BY id')
const res = await client.query('SELECT * FROM Ingredients ORDER BY id')
client.release()
let ingredients:Ingredient[] = []
@ -24,14 +26,16 @@ export class IngredientsGateway {
}
async findOneById(id: number) : Promise<Ingredient | null> {
this.connection.connect()
const client = await this.connection.getPoolClient()
const query = {
text: 'SELECT * FROM Ingredients WHERE id =$1',
values: [id],
}
const res = await this.connection.client.query(query)
const res = await client.query(query)
client.release()
if (res.rowCount != 1) {
return null
@ -42,16 +46,17 @@ export class IngredientsGateway {
return ingredient
}
async findIngredientsForRecipe(id: Number): Promise<any> {
this.connection.connect();
async findIngredientsForRecipe(id: number): Promise<any> {
const client = await this.connection.getPoolClient()
const query = {
text: 'SELECT i.name, i.id FROM Ingredients i, Composed c WHERE c.idRecipe =$1 AND i.id = c.idIngredient',
values: [id],
};
const res = await this.connection.client.query(query);
console.log(res)
const res = await client.query(query);
client.release()
if (res.rowCount === 0) {
return null;
@ -61,21 +66,21 @@ export class IngredientsGateway {
name: row.name,
id: Number(row.id), // Conversion de l'identifiant en nombre
}));
console.log(ingredients);
return ingredients as Ingredient[];
}
async getByLetter(letter: string): Promise<any> {
this.connection.connect();
const client = await this.connection.getPoolClient()
const query = {
text: 'SELECT * FROM Ingredients i WHERE LOWER(SUBSTRING(i.name, 1, 1)) = $1',
values: [letter.toLowerCase()],
};
const res = await this.connection.client.query(query);
console.log(res)
const res = await client.query(query);
client.release()
if (res.rowCount === 0) {
return null;
@ -92,15 +97,16 @@ export class IngredientsGateway {
}
async filter(prompt: string): Promise<any> {
this.connection.connect();
const client = await this.connection.getPoolClient()
const query = {
text: 'SELECT * FROM Ingredients WHERE LOWER(name) LIKE $1',
values: [`%${prompt.toLowerCase()}%`],
};
const res = await this.connection.client.query(query);
console.log(res)
const res = await client.query(query);
client.release()
if (res.rowCount === 0) {
return null;

@ -1,7 +1,5 @@
import { Ingredient } from "../types/ingredients";
import { Recipe } from "../types/recipes"
import { Connection } from "../database/connection"
import { Router } from "express";
import { StepsGateway } from "./steps.gateway";
import { IngredientsGateway } from "./ingredients.gateway";
@ -17,11 +15,12 @@ export class RecipeGateway {
}
async getAll() : Promise<Recipe[]> {
this.connection.connect()
const res = await this.connection.client.query('SELECT * FROM Recipes ORDER BY id');
const client = await this.connection.getPoolClient()
const res = await client.query('SELECT * FROM Recipes ORDER BY id');
client.release()
const steps: string[] = [];
let recipes:Recipe[] = []
let recipes: Recipe[] = []
for (let key in res.rows) {
const steps = await this.steps_gw.getForRecipes(Number(key));
@ -30,27 +29,27 @@ export class RecipeGateway {
recipes.push(recipe);
}
console.log(recipes);
return recipes
}
async getById(id: Number) : Promise<Recipe | null>{
this.connection.connect()
async getById(id: number) : Promise<Recipe | null>{
const client = await this.connection.getPoolClient()
const query = {
text: 'SELECT * FROM Recipes WHERE id =$1',
values: [id],
}
const res = await this.connection.client.query(query)
const res = await client.query(query)
client.release()
if (res.rowCount != 1) {
return null
}
const steps = await this.steps_gw.getForRecipes(id)
const ingredients = await this.ingredient_gw.findIngredientsForRecipe(id)
const steps = await this.steps_gw.getForRecipes(Number(id))
const ingredients = await this.ingredient_gw.findIngredientsForRecipe(Number(id))
const recipe = new Recipe(Number(res.rows[0].id),
res.rows[0].name,
res.rows[0].description,

@ -1,4 +1,3 @@
import { Recipe } from "../types/recipes"
import { Connection } from "../database/connection"
export class StepsGateway {
@ -9,15 +8,17 @@ export class StepsGateway {
}
async getForRecipes(id: Number): Promise<string[]> {
this.connection.connect();
async getForRecipes(id: number): Promise<string[]> {
const client = await this.connection.getPoolClient()
const query = {
text: 'SELECT action FROM Steps WHERE idRecipe = $1 ORDER BY numstep',
values: [id],
};
const res = await this.connection.client.query(query);
const res = await client.query(query);
client.release()
const steps = res.rows.map(row => row.action);

@ -1,10 +1,15 @@
require('dotenv').config();
import express from "express";
import cors from "cors";
import { IngredientsController } from "./controllers/ingredients.controller";
import { RecipesController } from "./controllers/recipes.controller";
import { StepsController } from "./controllers/steps.controller";
const app = express();
let helmet = require("helmet");
let app = express();
app.use(helmet.hidePoweredBy());
// Configuration du middleware CORS pour autoriser toutes les origines
app.use(cors({

@ -14,11 +14,12 @@ class Exception implements ApiException {
constructor(readonly error: any, readonly status: number) {}
}
/**
* Création d'une 404
*/
export module Exceptions {
export namespace Exceptions {
/**
* Création d'une 404
*/
export class NotFoundException extends Exception {
constructor(error: any) {
super(error, 404)

Loading…
Cancel
Save