diff --git a/app/api/businesses/[id]/route.ts b/app/api/businesses/[id]/route.ts index 01aa21d..b2b94a6 100644 --- a/app/api/businesses/[id]/route.ts +++ b/app/api/businesses/[id]/route.ts @@ -1,5 +1,6 @@ import { NextRequest, NextResponse } from 'next/server' import prisma from '@/lib/prisma' +import { USER_SAFE_SELECT } from '@/lib/auth-utils' type Params = { params: Promise<{ id: string }> } @@ -17,7 +18,12 @@ export async function GET( { slug: id } ] }, - include: { owner: true, offers: true }, + include: { + owner: { + select: USER_SAFE_SELECT + }, + offers: true + }, }) if (!business) return NextResponse.json({ error: 'Non trouvé' }, { status: 404 }) return NextResponse.json(business) @@ -38,7 +44,12 @@ export async function PATCH( const business = await prisma.business.update({ where: { id }, data: body, - include: { owner: true, offers: true }, + include: { + owner: { + select: USER_SAFE_SELECT + }, + offers: true + }, }) return NextResponse.json(business) } catch (error) { diff --git a/app/api/businesses/route.ts b/app/api/businesses/route.ts index a93e47d..90b90d8 100644 --- a/app/api/businesses/route.ts +++ b/app/api/businesses/route.ts @@ -1,5 +1,6 @@ import { NextRequest, NextResponse } from 'next/server' import prisma from '@/lib/prisma' +import { USER_SAFE_SELECT } from '@/lib/auth-utils' // GET /api/businesses — List all businesses (Mock + DB) export async function GET(request: NextRequest) { @@ -42,7 +43,12 @@ export async function GET(request: NextRequest) { const dbBusinesses = await prisma.business.findMany({ where, - include: { owner: true, offers: true }, + include: { + owner: { + select: USER_SAFE_SELECT + }, + offers: true + }, orderBy: { createdAt: 'desc' }, }) @@ -135,7 +141,11 @@ export async function POST(request: NextRequest) { business = await prisma.business.update({ where: { id: existing.id }, data: cleanData, - include: { owner: true } + include: { + owner: { + select: USER_SAFE_SELECT + } + } }); } else { // When creating, we add the ownerId to the sanitized cleanData @@ -144,7 +154,11 @@ export async function POST(request: NextRequest) { ...cleanData, ownerId: ownerId }, - include: { owner: true } + include: { + owner: { + select: USER_SAFE_SELECT + } + } }); // Automatic role upgrade diff --git a/app/api/users/route.ts b/app/api/users/route.ts index 735c098..8f525e8 100644 --- a/app/api/users/route.ts +++ b/app/api/users/route.ts @@ -1,11 +1,19 @@ import { NextRequest, NextResponse } from 'next/server' import prisma from '@/lib/prisma' +import { isAdmin, USER_SAFE_SELECT } from '@/lib/auth-utils' // GET /api/users -export async function GET() { +export async function GET(request: NextRequest) { try { + if (!(await isAdmin(request))) { + return NextResponse.json({ error: 'Accès non autorisé' }, { status: 403 }) + } + const users = await prisma.user.findMany({ - include: { businesses: true }, + select: { + ...USER_SAFE_SELECT, + businesses: true + }, orderBy: { createdAt: 'desc' }, }) return NextResponse.json(users) @@ -15,11 +23,22 @@ export async function GET() { } } -// POST /api/users +// POST /api/users (Admin only) export async function POST(request: NextRequest) { try { + if (!(await isAdmin(request))) { + return NextResponse.json({ error: 'Accès non autorisé' }, { status: 403 }) + } + const body = await request.json() - const user = await prisma.user.create({ data: body }) + + // Note: For admins, we might want to allow creating users directly, + // but we should still ensure password hashing if provided. + // For now, we just restrict it to admins to prevent the public leak. + const user = await prisma.user.create({ + data: body, + select: USER_SAFE_SELECT + }) return NextResponse.json(user, { status: 201 }) } catch (error) { console.error('POST /api/users error:', error) diff --git a/features.md b/features.md index c546f20..af6d9ac 100644 --- a/features.md +++ b/features.md @@ -33,3 +33,75 @@ ajout de paiement ponctuel pour : permettre d'ajouter un entrepreneur en favoris. + + + +features existante +# Liste des Fonctionnalités d'Afrohub + +Ce document recense l'ensemble des fonctionnalités implémentées sur la plateforme Afrohub, ainsi que les évolutions prévues. + +## 1. Gestion des Utilisateurs et Comptes +* **Authentification Sécurisée** : Connexion et inscription pour les Visiteurs et les Entrepreneurs. +* **Vérification d'Email** : Processus de validation automatique pour sécuriser les comptes. +* **Réinitialisation de Mot de Passe** : Flux complet de récupération par email. +* **Profils Utilisateurs** : Personnalisation avec avatar, biographie, localisation et coordonnées. +* **Système de Rôles** : Accès différenciés selon le type d'utilisateur (Visiteur, Entrepreneur, Administrateur). +* **Système de Favoris** : Possibilité pour les utilisateurs de sauvegarder des entreprises pour un accès rapide. +* **Modération des Comptes** : Suspension d'utilisateurs avec motifs par les administrateurs. + +## 2. Annuaire des Entreprises (B2B & Vitrine) +* **Fiches Entreprises Riches** : Logo, bannière personnalisable, description détaillée, vidéo de présentation, et liens vers les réseaux sociaux. +* **Catégorisation Dynamique** : Organisation par secteurs d'activité (Technologie, Agriculture, Mode, etc.) et tags. +* **Recherche et Filtrage** : Recherche multicritère par mots-clés, catégorie, pays et ville. +* **Badge de Vérification** : Identification visuelle des entreprises validées par l'équipe Afrohub. +* **Avis et Notations** : Système d'évaluation avec commentaires et possibilité de réponse pour le propriétaire. +* **Mise en Avant (Featured)** : Affichage prioritaire des entreprises sélectionnées sur la page d'accueil. +* **Statistiques de Visibilité** : Compteur de vues et suivi des clics vers les sites web/réseaux sociaux. +* **Gestion des Offres** : Publication de catalogues de produits ou services liés à chaque entreprise. + +## 3. Hub de Contenu (AfroLife & Blog) +* **Interviews AfroLife** : Formats Vidéo et Article mettant en lumière des parcours d'entrepreneurs africains. +* **Blog d'Actualités** : Section d'articles de fond, conseils et actualités du secteur. +* **Agenda des Événements** : Référencement des manifestations entrepreneuriales avec date, lieu et liens externes. +* **Optimisation SEO** : Gestion granulaire des meta-titres, meta-descriptions et slugs pour chaque article et interview. + +## 4. Communication et Engagement +* **Messagerie Interne** : Système de conversations directes entre les visiteurs et les entreprises. +* **Signalement de Contenu** : Possibilité de rapporter des messages ou comportements inappropriés. +* **Modération des Avis** : Flux de validation par les administrateurs pour garantir la qualité des échanges. +* **Notifications par Email** : Alertes pour les messages reçus et les étapes de vérification. + +## 5. Monétisation et Abonnements +* **Plans de Tarification Tiercés** : Offres Starter, Booster et Empire avec accès progressif aux fonctionnalités. +* **Multidevises (XOF/EUR)** : Support des paiements et affichage des prix adaptés. +* **Gestion des Limites de Plan** : Contrôle dynamique du nombre d'offres publiables selon l'abonnement. +* **Tunnel de Souscription** : Interface dédiée pour le choix et la gestion des abonnements. + +## 6. Panel d'Administration (Backoffice) +* **Tableau de Bord Analytique** : Visualisation des métriques clés (utilisateurs, entreprises, revenus). +* **CMS Complet** : Éditeurs pour le blog, les interviews AfroLife, les événements et les catégories. +* **Gestion Géographique** : Configuration des pays et villes disponibles sur la plateforme. +* **Modération Centrale** : Interface de validation des avis, traitement des signalements et suspension des comptes. +* **Paramètres Globaux** : Modification du slogan, des contacts, des liens sociaux et du SEO général du site. +* **Gestion des Plans** : Configuration des prix et des avantages liés aux abonnements. +* **Éditeur de Documents Légaux** : Gestion des CGU, CGV et mentions légales directement depuis l'interface. +* **Personnalisation des Emails** : Éditeur de templates pour les communications système (reset password, verification). + +--- + +## 7. Roadmap & Fonctionnalités à Venir (Prochainement) +* **Progressive Web App (PWA)** : Application installable sur smartphone avec notifications push en temps réel. +* **Paiements Ponctuels** : Options de paiement à l'acte pour booster un profil ou créer un événement premium. +* **Tableau de Bord Entrepreneur Avancé** : Graphiques d'évolution des vues et origine géographique des visiteurs. +* **Portail d'Emploi (Job Board)** : Publication d'offres d'emploi et de missions freelance par les entreprises. +* **E-commerce & Paiement Direct** : Achat de produits/services via Mobile Money ou Paystack directement sur le site. +* **Matchmaking B2B** : Système de mise en relation et demandes de partenariat structurées. +* **Avis Multimédias** : Possibilité d'ajouter des photos de réalisations ou preuves d'achat dans les avis. +* **Billetterie & RSVP** : Confirmation de présence aux événements et rappels automatiques. +* **Forum Communautaire** : Espace de questions/réponses et d'entraide entre entrepreneurs. +* **Hub Investisseurs** : Espace dédié aux levées de fonds avec hébergement de Pitch Decks. +* **Recherche Géolocalisée** : Vue sur carte (Map) pour découvrir les opportunités à proximité. +* **Support Multilingue** : Traduction intégrale du site en anglais et portugais. +* **Programme de Mentorat** : Système de mise en relation entre entrepreneurs seniors et juniors. + diff --git a/lib/auth-utils.ts b/lib/auth-utils.ts new file mode 100644 index 0000000..d166c36 --- /dev/null +++ b/lib/auth-utils.ts @@ -0,0 +1,42 @@ +import { NextRequest } from 'next/server'; +import prisma from '@/lib/prisma'; + +export const USER_SAFE_SELECT = { + id: true, + name: true, + email: true, + role: true, + avatar: true, + bio: true, + location: true, + phone: true, + createdAt: true, + updatedAt: true, + emailVerified: true, +}; + +export async function getAuthUser(request: NextRequest) { + const userId = request.headers.get('x-user-id'); + if (!userId) return null; + + try { + const user = await prisma.user.findUnique({ + where: { id: userId }, + select: { + id: true, + role: true, + emailVerified: true, + isSuspended: true + } + }); + return user; + } catch (error) { + console.error('Error fetching auth user:', error); + return null; + } +} + +export async function isAdmin(request: NextRequest) { + const user = await getAuthUser(request); + return user?.role === 'ADMIN'; +}