This commit is contained in:
el 2025-04-02 00:10:02 +02:00
commit 73ea49c3fe
16 changed files with 2746 additions and 0 deletions

View file

@ -0,0 +1,135 @@
import { Request, Response } from 'express';
import { prisma } from '../lib/prisma';
export const pageController = {
// Créer une nouvelle page
async create(req: Request, res: Response) {
try {
const { title, parentId, userId } = req.body;
const page = await prisma.page.create({
data: {
title,
parentId,
userId,
},
include: {
blocks: true,
},
});
return res.status(201).json(page);
} catch (error) {
return res.status(500).json({ error: 'Erreur lors de la création de la page' });
}
},
// Obtenir une page par son ID avec ses blocs
async getById(req: Request, res: Response) {
try {
const { id } = req.params;
const page = await prisma.page.findUnique({
where: { id },
include: {
blocks: {
orderBy: {
order: 'asc',
},
},
},
});
if (!page) {
return res.status(404).json({ error: 'Page non trouvée' });
}
return res.json(page);
} catch (error) {
return res.status(500).json({ error: 'Erreur lors de la récupération de la page' });
}
},
// Mettre à jour une page
async update(req: Request, res: Response) {
try {
const { id } = req.params;
const { title, blocks } = req.body;
// Supprimer tous les blocs existants
await prisma.block.deleteMany({
where: { pageId: id },
});
// Créer les nouveaux blocs
const newBlocks = await Promise.all(
blocks.map((block: any) =>
prisma.block.create({
data: {
type: block.type,
content: block.content,
order: block.order,
pageId: id,
},
})
)
);
// Mettre à jour la page
const page = await prisma.page.update({
where: { id },
data: {
title,
},
include: {
blocks: {
orderBy: {
order: 'asc',
},
},
},
});
return res.json(page);
} catch (error) {
console.error('Erreur lors de la mise à jour:', error);
return res.status(500).json({ error: 'Erreur lors de la mise à jour de la page' });
}
},
// Supprimer une page
async delete(req: Request, res: Response) {
try {
const { id } = req.params;
await prisma.page.delete({
where: { id },
});
return res.status(204).send();
} catch (error) {
return res.status(500).json({ error: 'Erreur lors de la suppression de la page' });
}
},
// Récupérer toutes les pages
async getAll(req: Request, res: Response) {
try {
const pages = await prisma.page.findMany({
include: {
blocks: {
orderBy: {
order: 'asc',
},
},
},
orderBy: {
updatedAt: 'desc',
},
});
return res.json(pages);
} catch (error) {
console.error('Erreur lors de la récupération des pages:', error);
return res.status(500).json({ error: 'Erreur lors de la récupération des pages' });
}
},
};

View file

@ -0,0 +1,64 @@
import { Request, Response } from 'express';
import { prisma } from '../lib/prisma';
import bcrypt from 'bcryptjs';
export const userController = {
// Créer un nouvel utilisateur
async create(req: Request, res: Response) {
try {
const { email, password, name } = req.body;
// Vérifier si l'utilisateur existe déjà
const existingUser = await prisma.user.findUnique({
where: { email },
});
if (existingUser) {
return res.status(400).json({ error: 'Cet email est déjà utilisé' });
}
// Hasher le mot de passe
const hashedPassword = await bcrypt.hash(password, 10);
// Créer l'utilisateur
const user = await prisma.user.create({
data: {
email,
password: hashedPassword,
name,
},
});
// Ne pas renvoyer le mot de passe
const { password: _, ...userWithoutPassword } = user;
return res.status(201).json(userWithoutPassword);
} catch (error) {
return res.status(500).json({ error: 'Erreur lors de la création de l\'utilisateur' });
}
},
// Obtenir un utilisateur par son ID
async getById(req: Request, res: Response) {
try {
const { id } = req.params;
const user = await prisma.user.findUnique({
where: { id },
select: {
id: true,
email: true,
name: true,
createdAt: true,
},
});
if (!user) {
return res.status(404).json({ error: 'Utilisateur non trouvé' });
}
return res.json(user);
} catch (error) {
return res.status(500).json({ error: 'Erreur lors de la récupération de l\'utilisateur' });
}
},
};

46
backend/src/index.ts Normal file
View file

@ -0,0 +1,46 @@
import express from 'express';
import cors from 'cors';
import dotenv from 'dotenv';
import { PrismaClient } from '@prisma/client';
import userRoutes from './routes/userRoutes';
import pageRoutes from './routes/pageRoutes';
import blockRoutes from './routes/blockRoutes';
// Chargement des variables d'environnement
dotenv.config();
const app = express();
const prisma = new PrismaClient();
const port = process.env.PORT || 3001;
// Configuration CORS
app.use(cors({
origin: 'http://localhost:3000',
credentials: true,
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization']
}));
// Middleware
app.use(express.json());
// Routes
app.use('/api/users', userRoutes);
app.use('/api/pages', pageRoutes);
app.use('/api/blocks', blockRoutes);
// Route de test
app.get('/', (req, res) => {
res.json({ message: 'Bienvenue sur l\'API OrbitDocs' });
});
// Gestion des erreurs
app.use((err: Error, req: express.Request, res: express.Response, next: express.NextFunction) => {
console.error(err.stack);
res.status(500).json({ message: 'Une erreur est survenue sur le serveur' });
});
// Démarrage du serveur
app.listen(port, () => {
console.log(`Serveur démarré sur le port ${port}`);
});

View file

@ -0,0 +1,9 @@
import { PrismaClient } from '@prisma/client';
const globalForPrisma = globalThis as unknown as {
prisma: PrismaClient | undefined;
};
export const prisma = globalForPrisma.prisma ?? new PrismaClient();
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma;

View file

@ -0,0 +1,84 @@
import express from 'express';
import { PrismaClient } from '@prisma/client';
const router = express.Router();
const prisma = new PrismaClient();
// Créer un nouveau bloc
router.post('/', async (req, res) => {
try {
const { type, content, pageId, userId, order } = req.body;
const block = await prisma.block.create({
data: {
type,
content,
pageId,
userId,
order
}
});
res.status(201).json(block);
} catch (error) {
console.error('Erreur lors de la création du bloc:', error);
res.status(500).json({ message: 'Erreur lors de la création du bloc' });
}
});
// Mettre à jour un bloc
router.put('/:id', async (req, res) => {
try {
const { id } = req.params;
const { content, type, order } = req.body;
const block = await prisma.block.update({
where: { id },
data: {
content,
type,
order
}
});
res.json(block);
} catch (error) {
console.error('Erreur lors de la mise à jour du bloc:', error);
res.status(500).json({ message: 'Erreur lors de la mise à jour du bloc' });
}
});
// Supprimer un bloc
router.delete('/:id', async (req, res) => {
try {
const { id } = req.params;
await prisma.block.delete({
where: { id }
});
res.status(204).send();
} catch (error) {
console.error('Erreur lors de la suppression du bloc:', error);
res.status(500).json({ message: 'Erreur lors de la suppression du bloc' });
}
});
// Obtenir tous les blocs d'une page
router.get('/page/:pageId', async (req, res) => {
try {
const { pageId } = req.params;
const blocks = await prisma.block.findMany({
where: { pageId },
orderBy: { order: 'asc' }
});
res.json(blocks);
} catch (error) {
console.error('Erreur lors de la récupération des blocs:', error);
res.status(500).json({ message: 'Erreur lors de la récupération des blocs' });
}
});
export default router;

View file

@ -0,0 +1,123 @@
import express from 'express';
import { PrismaClient } from '@prisma/client';
const router = express.Router();
const prisma = new PrismaClient();
// Créer une nouvelle page
router.post('/', async (req, res) => {
try {
const { title, content, userId, parentId } = req.body;
const page = await prisma.page.create({
data: {
title,
content,
userId,
parentId
},
include: {
user: {
select: {
id: true,
name: true
}
}
}
});
res.status(201).json(page);
} catch (error) {
res.status(500).json({ message: 'Erreur lors de la création de la page' });
}
});
// Obtenir toutes les pages d'un utilisateur
router.get('/user/:userId', async (req, res) => {
try {
const { userId } = req.params;
const pages = await prisma.page.findMany({
where: {
userId
},
include: {
user: {
select: {
id: true,
name: true
}
}
}
});
res.json(pages);
} catch (error) {
res.status(500).json({ message: 'Erreur lors de la récupération des pages' });
}
});
// Obtenir une page spécifique
router.get('/:id', async (req, res) => {
try {
const { id } = req.params;
const page = await prisma.page.findUnique({
where: { id },
include: {
user: {
select: {
id: true,
name: true
}
},
blocks: true
}
});
if (!page) {
return res.status(404).json({ message: 'Page non trouvée' });
}
res.json(page);
} catch (error) {
res.status(500).json({ message: 'Erreur lors de la récupération de la page' });
}
});
// Mettre à jour une page
router.put('/:id', async (req, res) => {
try {
const { id } = req.params;
const { title, content } = req.body;
const page = await prisma.page.update({
where: { id },
data: {
title,
content
}
});
res.json(page);
} catch (error) {
res.status(500).json({ message: 'Erreur lors de la mise à jour de la page' });
}
});
// Supprimer une page
router.delete('/:id', async (req, res) => {
try {
const { id } = req.params;
await prisma.page.delete({
where: { id }
});
res.status(204).send();
} catch (error) {
res.status(500).json({ message: 'Erreur lors de la suppression de la page' });
}
});
export default router;

View file

@ -0,0 +1,124 @@
import express from 'express';
import { PrismaClient } from '@prisma/client';
import bcrypt from 'bcryptjs';
const router = express.Router();
const prisma = new PrismaClient();
// Supprimer un utilisateur (route de développement)
router.delete('/:email', async (req, res) => {
try {
const { email } = req.params;
await prisma.user.delete({
where: { email }
});
res.status(204).send();
} catch (error) {
console.error('Erreur lors de la suppression:', error);
res.status(500).json({ message: 'Erreur lors de la suppression' });
}
});
// Inscription
router.post('/register', async (req, res) => {
try {
const { email, password, name } = req.body;
// Vérification si l'utilisateur existe déjà
const existingUser = await prisma.user.findUnique({
where: { email }
});
if (existingUser) {
return res.status(400).json({ message: 'Cet email est déjà utilisé' });
}
// Hashage du mot de passe
const hashedPassword = await bcrypt.hash(password, 10);
// Création de l'utilisateur
const user = await prisma.user.create({
data: {
email,
password: hashedPassword,
name
}
});
res.status(201).json({
id: user.id,
email: user.email,
name: user.name
});
} catch (error) {
console.error('Erreur lors de l\'inscription:', error);
res.status(500).json({ message: 'Erreur lors de l\'inscription' });
}
});
// Connexion
router.post('/login', async (req, res) => {
try {
const { email, password } = req.body;
console.log('Tentative de connexion pour:', email);
// Recherche de l'utilisateur
const user = await prisma.user.findUnique({
where: { email }
});
if (!user) {
console.log('Utilisateur non trouvé');
return res.status(400).json({ message: 'Email ou mot de passe incorrect' });
}
console.log('Utilisateur trouvé, vérification du mot de passe');
// Vérification du mot de passe
const validPassword = await bcrypt.compare(password, user.password);
console.log('Mot de passe valide:', validPassword);
if (!validPassword) {
return res.status(400).json({ message: 'Email ou mot de passe incorrect' });
}
res.json({
id: user.id,
email: user.email,
name: user.name
});
} catch (error) {
console.error('Erreur lors de la connexion:', error);
res.status(500).json({ message: 'Erreur lors de la connexion' });
}
});
// Vérifier l'état de l'authentification
router.get('/me', async (req, res) => {
try {
const { email } = req.query;
if (!email) {
return res.status(400).json({ message: 'Email requis' });
}
const user = await prisma.user.findUnique({
where: { email: email as string }
});
if (!user) {
return res.status(404).json({ message: 'Utilisateur non trouvé' });
}
res.json({
id: user.id,
email: user.email,
name: user.name
});
} catch (error) {
console.error('Erreur lors de la vérification de l\'authentification:', error);
res.status(500).json({ message: 'Erreur lors de la vérification de l\'authentification' });
}
});
export default router;