58 lines
1.8 KiB
Python
58 lines
1.8 KiB
Python
"""
|
|
annonce_model.py — Accès aux données pour l'entité "annonce".
|
|
|
|
Toutes les requêtes utilisent des paramètres préparés (%s) : aucune
|
|
concaténation de chaîne SQL n'est utilisée dans ce module (OWASP A03:2021 —
|
|
Injection). Voir tests de sécurité TS-01 (tests/test_security.py).
|
|
"""
|
|
|
|
|
|
class AnnonceNotFoundError(Exception):
|
|
"""Exception métier levée quand une annonce n'existe pas.
|
|
|
|
La couche services/ traduit les erreurs SQL bas niveau en exceptions
|
|
métier compréhensibles, afin que les routes n'aient jamais à connaître
|
|
les détails de pymysql (cf. C4 — convention de gestion des erreurs).
|
|
"""
|
|
|
|
|
|
def insert(db, titre, contenu, auteur_sub, epinglee=False):
|
|
query = (
|
|
"INSERT INTO annonces (titre, contenu, epinglee, auteur_sub) "
|
|
"VALUES (%s, %s, %s, %s)"
|
|
)
|
|
return db.execute(query, (titre, contenu, int(epinglee), auteur_sub))
|
|
|
|
|
|
def fetch_all(db):
|
|
query = (
|
|
"SELECT id, titre, contenu, epinglee, auteur_sub, created_at, updated_at "
|
|
"FROM annonces ORDER BY epinglee DESC, created_at DESC"
|
|
)
|
|
return db.fetch_all(query)
|
|
|
|
|
|
def get(db, annonce_id):
|
|
query = (
|
|
"SELECT id, titre, contenu, epinglee, auteur_sub, created_at, updated_at "
|
|
"FROM annonces WHERE id = %s"
|
|
)
|
|
return db.fetch_one(query, (annonce_id,))
|
|
|
|
|
|
def update(db, annonce_id, titre, contenu, epinglee=False):
|
|
query = (
|
|
"UPDATE annonces SET titre = %s, contenu = %s, epinglee = %s "
|
|
"WHERE id = %s"
|
|
)
|
|
with db.cursor(commit=True) as cur:
|
|
cur.execute(query, (titre, contenu, int(epinglee), annonce_id))
|
|
return cur.rowcount
|
|
|
|
|
|
def delete(db, annonce_id):
|
|
query = "DELETE FROM annonces WHERE id = %s"
|
|
with db.cursor(commit=True) as cur:
|
|
cur.execute(query, (annonce_id,))
|
|
return cur.rowcount
|