Skip to content

feat(admin): signalements, lieux signalés et avis - #479

Open
Nascimento95 wants to merge 13 commits into
issue/55-catalog-dashboardfrom
issue/54-reports-and-ratings
Open

Nascimento95 wants to merge 13 commits into
issue/55-catalog-dashboardfrom
issue/54-reports-and-ratings

Conversation

@Nascimento95

@Nascimento95 Nascimento95 commented Oct 15, 2026 •

Copy link
Copy Markdown
Collaborator

Résultat et problème

L'équipe ne pouvait ni voir ni traiter ce que la communauté signale. Cette PR ajoute les signalements et les avis (A-03) : les signalements de parcours, les lieux signalés et la liste des avis, côté API et côté admin.

Ce qui est fait :

  • Signalements de parcours : GET /admin/reports (ouverts, du plus ancien au plus récent, avec l'étape d'un « lieu modifié », filtre par motif) et POST /admin/reports/:id/resolve (accepter ou rejeter, note dans le journal, retour au signaleur report_resolved à l'acceptation, 409 already_decided si un autre membre a déjà tranché).
  • Note basse : un signalement sans signaleur propose « Garder » (rejeté), « Demander des modifications » (le parcours publié passe en needs_fix et reste en ligne, request-changes accepte maintenant un parcours publié) et « Dépublier » (motif et message obligatoires).
  • Lieux signalés : GET /admin/signals (lieux au statut flagged avec les parcours publiés qui y passent), POST /admin/places/:id/verify (remet les confirmations à zéro) et POST /admin/places/:id/close (motif obligatoire, parcours publiés concernés en needs_fix avec une ligne d'historique chacun).
  • Avis : GET /admin/ratings, liste vide, filtres validés.
  • Compteurs : la pastille « Signalements » et la tuile du tableau de bord comptent les signalements de parcours ouverts et les lieux signalés (en retard au-delà de 72 h pour les signalements de parcours).
  • Admin : /signalements en trois onglets (Parcours, Lieux, Avis), les décisions dans un panneau de détail, des fenêtres de confirmation pour la note, le message à l'auteur et le motif.

Critères d'acceptation :

Limites, et le ticket qui les lève :

  • Signalements de lieux (nombre, motifs, confirmations récentes, « Rejeter le signalement » via signals/:id/reject) : la table place_signals n'existe pas (Enregistrer confirmations et signalements de lieux avec pondération et statuts #49). L'onglet Lieux liste les lieux au statut flagged ; leur nombre de signalements est 0, depuis une seule constante à remplacer.
  • Masquer et rétablir un avis (ratings/:id/hide et unhide, motif obligatoire) : Noter un parcours en fin de sortie (E-15) et afficher les avis #64.
  • Prévenir l'auteur quand son parcours passe en needs_fix (fermeture d'un lieu, demande de modifications) : notifications.kind n'a que go_closed et report_resolved, aucun type pour l'auteur et aucun ticket ne le porte. Le message est gardé dans l'historique du parcours. À créer.
  • « Rejeter » un signalement ne prévient pas le signaleur, comme le wiki le dit (D-056) ; la note est dans le journal (admin_actions.reason), faute de colonne dédiée (Trancher le nom du signaleur de route_reports et l'emplacement de la note de résolution #438).
  • « Demander des modifications » et « Dépublier » sur une note basse font deux appels (le parcours, puis le signalement) : si le second échoue, le signalement reste ouvert et le parcours a déjà changé ; la relance se fait par le même bouton.
  • L'onglet Avis n'a pas encore de lignes à afficher à l'écran : sa table est écrite d'après le schéma, sans donnée pour la voir.

Fixes #54
Écrans : A-03
Dépendance : empilée sur #398 (ticket 55), elle-même sur #365 et #363.

Comment vérifier

Montage local de #363, base locale migrée, compte admin ou moderator. Quelques lignes en base locale suffisent : des route_reports ouverts (dont un low_rating, sans user_id) et des lieux au statut flagged.

Testé par Marco le 2026-10-15, en local, sur les modèles de Ecrans › Admin web (A-03 n'a pas de planche) :

  • le compteur « Signalements » du menu, et l'arrivée sur l'onglet Parcours ;
  • la liste des signalements de parcours, le filtre par motif, « Accepter » et « Rejeter » avec une note ;
  • une note basse : « Garder », « Demander des modifications » (le parcours passe en « À corriger » et reste en ligne) et « Dépublier » (motif et message obligatoires) ;
  • les lieux signalés : « Marquer vérifié » et « Fermer le lieu » (motif obligatoire, le parcours concerné passe en « À corriger ») ; la pastille baisse à chaque décision ;
  • l'onglet Avis : état vide et filtre par note ;
  • un compte modérateur voit les trois onglets.

Non vérifié : un éditeur refusé à l'écran (couvert par les tests d'API), le comportement de deux membres qui décident en même temps (couvert par un test d'API), et rien n'a été testé contre un environnement déployé.

  • pnpm lint && pnpm typecheck && pnpm test verts en local
  • Testé sur iOS / Android (préciser) — sans objet

Formatage mécanique : non

Risque

Niveau : 2 — nouveaux endpoints authentifiés qui écrivent (décision sur un signalement, statut d'un lieu, statut de parcours publiés, notification à un utilisateur) ; aucune migration.

Taille : un commit au-dessus de 390 lignes utiles, tests compris : 4b3e901 (392) : la liste des signalements de parcours, son tableau, son panneau, sa configuration et ses pages. Aucun fichier généré.

Revue OWASP (Top 10) :

  • Contrôle d'accès : tous les endpoints passent par requireAdminSection('reports') (modérateurs et admins). Un éditeur reçoit 403 sur la liste et sur chaque décision, sans rien écrire (testé). Le test de garde de toutes les routes /admin/* couvre ces nouveaux endpoints.
  • Intégrité et concurrence : un signalement, un lieu, et les parcours d'un lieu fermé sont verrouillés (for update) le temps de la décision, avec le journal écrit dans la même transaction. Deux décisions simultanées sur un signalement donnent un 200 et un 409, une seule ligne de journal (testé).
  • Entrées non fiables : la note et le motif sont du texte brut borné (500 caractères, sans balise ni caractère de contrôle), les corps sont stricts (champ inconnu refusé), les filtres validés ; requêtes paramétrées. Les commentaires des signalements s'affichent sans HTML.
  • Données personnelles : le prénom du signaleur n'est lu que par l'équipe ; la notification au signaleur ne porte que les identifiants du signalement et du parcours.
  • Journalisation : report.resolve, place.verify et place.close gardent l'auteur, l'état avant et après et la note ou le motif.

Nouvelle dépendance : aucune.

Retour arrière

Le revert de la PR suffit pour le code, sans migration à annuler. Les signalements décidés, les lieux vérifiés ou fermés, les parcours passés en needs_fix et les notifications envoyées restent en base ; un lieu fermé par erreur se rouvre par « Marquer vérifié », un parcours needs_fix se corrige depuis l'éditeur.

🤖 Generated with Claude Code

@Nascimento95 Nascimento95 added type:feature Nouvelle fonctionnalité area:admin apps/admin level:2 Risque niveau 2 (SECURITY.md) labels Oct 15, 2026
@Nascimento95
Nascimento95 force-pushed the issue/55-catalog-dashboard branch from f2ccb57 to 52d1d10 Compare October 16, 2026 03:35
Nascimento95 and others added 13 commits October 16, 2026 10:35
…the admin (A-03)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…route (A-03)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…d (A-03)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…rrect (A-03)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ed (A-03)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ation and the dashboard

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… them (A-03)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ratings (A-03)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…(A-03)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…a panel (A-03)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…(A-03)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@Nascimento95
Nascimento95 force-pushed the issue/54-reports-and-ratings branch from 5ddf205 to ac97da0 Compare October 16, 2026 03:37
@Nascimento95

Copy link
Copy Markdown
Collaborator Author

Branche remise à jour sur le ticket 55 (#398), elle-même sur la pile rebasée sur main. Aucune migration, aucun changement de comportement. Lint, types et tests verts en local.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:admin apps/admin level:2 Risque niveau 2 (SECURITY.md) type:feature Nouvelle fonctionnalité

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant