Documentation pour les développeurs - SaigoNoo/GetTheBeer GitHub Wiki

Bienvenue dans la documentation développeur

Description

Ressources et outils:

Dans le cadre de ce projet nous avons utilisé les logiciels et appareils suivants:

Type Logiciel Description
Serveur Ubuntu 24.04 Un serveur personnel sur lequel tournera la backend et la base de donnée
FastAPI python3-fastapi ainsi que certains modules pour son bon fonctionnement
MariaDB Base de donnée basée sur MySQL, on y mettra des fonctions et procédure utilisables au sein de la DB et de la backend !
ReactJS Sera aussi présent sur le serveur
Électronique RaspberryPi (modele a définir) Modele a définir
GPIO, boutons, etc... Besoin de développer xD ?

Structure du code:

Backend

Pour rappel, elle est constituée d'une API en Python et de MariaDB

Structure du code Backend:

Nous avons ces premiers fichiers / dossiers:

.
| - [d] api/                        # Dossier API contenant tout les fichiers liés à l'API
   | -- [f] __init__.py             # Fichier initial qui crée une fois le socket vers la base de donnée, gère le swagger et les nouveaux endpoints API
   | -- [f] database.py             # Un fichier permettant de créer des endpoints en lien avec la base de donnée via FastAPI pour recuperer des infos
   | -- [f] models.py               # IMPORTANT: Permet de créer les entêtes des requêtes POST
| - [d] classes/                    # Dossier contenant du code réutilisable exploitable sous forme de classe
   | -- [f] database.py             # Fichier permettant de créer un socket entre Python et la base de donnée, et quelques fonctions qui peuvent être appelés dans les fichiers API
   | -- [f] mail.py                 # Fichier permettant d'envoyer un mail a destinataire. Afin de pas réecrire le code a chaque fichier API, on le crée ici dans classes/
| - [f] .env                        # Fichier contenant les credentials du serveur de DB et serveur SMTP
| - [f] main.py                     # Fichier principal où est crée le point de départ de l'API et l'appel du reste du code

Modèles de code et syntaxe:

main.py

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

from api import start

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

start(app=app)

C'est le point de départ du code, de là est initialisée l'API ! la fonction start(app=app) va call le fichier _init_.py et déployer les endpoints et générer le swagger !

code explication
app Contiendra l'instance API qui permettra de créer nos endpoints
middleware On définit quels noms de domaines et port ont le droit d'avoir une réponse de l'API, aussi appelé CORS

api/init.py

from fastapi import FastAPI

import api.database
import api.user
from classes.database import Database

# Database Init for API
db = Database()
db.connect()


def start(app: FastAPI):
    """
    Charger toutes les routes préecrites et appellées après le update_swagger()
    """

    def update_swagger():
        """
        Une fois toutes les routes chargées, on appelle update_swagger pour forcer le reset du swagger et afficher
        toutes les requetes!
        """
        app.openapi_schema = None
        app.setup()

    """
    A partir d'ici, on load toutes les routes API et à la fin, on update le swagger !
    """
    api.user.load(app=app, db=db)
    api.database.load(app=app, db=db)

    update_swagger()

C'est ici que notre API est développée et utilise d'autres endpoints API

code explication
db Instance initiale qu'on crée une seule fois et qu'on distribuera a chaque nouveaux endpoints afin que l'API puisse communiquer avec la DB
api.*.load(app, db) Chaque nouveau fichier endpoint API est contenu dans une fonction load() ou app est l'instance de l'API et db celle de la base de donnée !
update_swagger Par défaut, le swagger se met pas à jour lors de l'import dynamique des endpoints, mais en utilisant update_swagger à la fin, on force le swagger a se regénérer, en prenant en compte les enpoints importées

Modèle à suivre pour créer un fichier avec des endpoints

Structure du nouveau fichier dans /api/

from fastapi import FastAPI
from classes.database import Database


def load(app: FastAPI, db: Database) -> None:
    """Charger toutes les CALLS API"""

    @app.get(
        path="/api/db/test",
        description="Permet d'obtenir une confirmation de l'accès a la base de donnée",
        tags=["DATABASE"]
    )
    async def db_test():
        return db.call_function(name="test_api")
Code Explications
def load(app: FastAPI, db: Database) Pour respecter le loading et pour éviter de charger des endpoints dont des dépendances pourraient échouer a charger, le _init_.py peut décider quoi charger selon la stratégie établie par le développeur.

Il faut dès lors inserer nos endpoints de la façon suivante, y'a 4 types mais pour l'instant on utilise GET et POST !

Type Description
GET On insère les paramètres dans la requête URL ! Danger si données sensibles car en clair
POST On insère les paramètres dans l'en-tête du paquet HTTP ! Les données sont pas lisibles dans l'URL => Parfait pour les connexions avec token

❗ Les endpoints fonctionnent en asynchrone, donc utiliser le async ❗

GET
@app.get(
  path="/api/choisissez/autant/que",
  description="Définissez l'utilité de votre endpoint",
  tags=["ANY"] # Permet de regrouper les endpoints dans le swagger
)
async def do(nom: str = "Giorgio"):
   return f"Bonjour c'est {nom}"

/api/choisissez/autant/que?nom="Salut"

POST

Il faut créer un modèle d'en-tête dans api/models.py

class CreateUser(BaseModel):
   username: str,
   password: str

Une fois crée:

from api.models import CreateUser


@app.post(
  path="/api/create_user",
  description="Définissez l'utilité de votre endpoint",
  tags=["ANY"] # Permet de regrouper les endpoints dans le swagger
)
async def do(data: CreateUser):
   ...
   return f"Compte crée pour {data.username} avec {data.password}"

CALL /api/crete_user (en inserant une entete avec un dictionnaire)

Modifications à apporter dans init.py

Frontend

A définir