001
This commit is contained in:
commit
73ea49c3fe
16 changed files with 2746 additions and 0 deletions
135
backend/src/controllers/pageController.ts
Normal file
135
backend/src/controllers/pageController.ts
Normal 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' });
|
||||
}
|
||||
},
|
||||
};
|
64
backend/src/controllers/userController.ts
Normal file
64
backend/src/controllers/userController.ts
Normal 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
46
backend/src/index.ts
Normal 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}`);
|
||||
});
|
9
backend/src/lib/prisma.ts
Normal file
9
backend/src/lib/prisma.ts
Normal 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;
|
84
backend/src/routes/blockRoutes.ts
Normal file
84
backend/src/routes/blockRoutes.ts
Normal 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;
|
123
backend/src/routes/pageRoutes.ts
Normal file
123
backend/src/routes/pageRoutes.ts
Normal 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;
|
124
backend/src/routes/userRoutes.ts
Normal file
124
backend/src/routes/userRoutes.ts
Normal 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;
|
Loading…
Add table
Add a link
Reference in a new issue