mirror of
https://github.com/Sonny93/my-links.git
synced 2025-12-10 15:35:35 +00:00
Beaucoup trop de chose
- Ajout création, édition, suppression catégories & liens - Ajout auth google - Ajout/modification style pour catégories & liens - Ajout component générique pour bouton, inputs, checkbox & selector - Gestion des messages d'erreur/succès/infos via component dédié - Ajout component FormLayout pour les pages création, édition, suppression catégories & liens - Page custom 404, 500 & signin - Modification schéma DB
This commit is contained in:
@@ -1,30 +0,0 @@
|
||||
import NextAuth from 'next-auth';
|
||||
import GoogleProvider from 'next-auth/providers/google';
|
||||
|
||||
export default NextAuth({
|
||||
providers: [
|
||||
GoogleProvider({
|
||||
clientId: process.env.GOOGLE_CLIENT_ID,
|
||||
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
|
||||
authorization: {
|
||||
params: {
|
||||
prompt: "consent",
|
||||
access_type: "offline",
|
||||
response_type: "code"
|
||||
}
|
||||
}
|
||||
})
|
||||
],
|
||||
callbacks: {
|
||||
async signIn({ account, profile }) {
|
||||
if (account.provider === "google" && profile.email !== '') {
|
||||
if (profile.email_verified && profile.email.endsWith("@gmail.com")) {
|
||||
return true;
|
||||
} else {
|
||||
return "/signin?error=" + encodeURI('Une erreur s\'est produite lors de l\'authentification');
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
60
pages/api/auth/[...nextauth].ts
Normal file
60
pages/api/auth/[...nextauth].ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import NextAuth from 'next-auth';
|
||||
import GoogleProvider from 'next-auth/providers/google';
|
||||
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
export default NextAuth({
|
||||
providers: [
|
||||
GoogleProvider({
|
||||
clientId: process.env.GOOGLE_CLIENT_ID,
|
||||
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
|
||||
authorization: {
|
||||
params: {
|
||||
prompt: 'consent',
|
||||
access_type: 'offline',
|
||||
response_type: 'code'
|
||||
}
|
||||
}
|
||||
})
|
||||
],
|
||||
callbacks: {
|
||||
async signIn({ account: accountParam, profile }) { // TODO: Auth
|
||||
if (accountParam.provider !== 'google') {
|
||||
return '/signin?error=' + encodeURI('Authentitifcation via Google requise');
|
||||
}
|
||||
|
||||
const email = profile?.email;
|
||||
if (email === '') {
|
||||
return '/signin?error=' + encodeURI('Impossible de récupérer l\'email associé à ce compte Google');
|
||||
}
|
||||
|
||||
const googleId = profile?.sub;
|
||||
if (googleId === '') {
|
||||
return '/signin?error=' + encodeURI('Impossible de récupérer l\'identifiant associé à ce compte Google');
|
||||
}
|
||||
|
||||
try {
|
||||
const account = await prisma.user.findFirst({
|
||||
where: {
|
||||
google_id: googleId,
|
||||
email
|
||||
}
|
||||
});
|
||||
|
||||
if (!account) {
|
||||
return '/signin?error=' + encodeURI('Vous n\'êtes pas autorisé à vous connecter avec ce compte Google');
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return '/signin?error=' + encodeURI('Une erreur est survenue lors de l\'authentification');
|
||||
}
|
||||
}
|
||||
},
|
||||
pages: {
|
||||
signIn: '/signin',
|
||||
error: '/signin'
|
||||
}
|
||||
});
|
||||
39
pages/api/category/create.ts
Normal file
39
pages/api/category/create.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { NextApiRequest, NextApiResponse } from 'next';
|
||||
|
||||
import { apiRoute } from '../../../utils/back';
|
||||
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
apiRoute.post(async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const name = req.body?.name as string;
|
||||
|
||||
if (!name) {
|
||||
return res.status(400).send({ error: 'Nom de catégorie manquant' });
|
||||
}
|
||||
|
||||
try {
|
||||
const category = await prisma.category.findFirst({
|
||||
where: { name }
|
||||
});
|
||||
|
||||
if (category) {
|
||||
return res.status(400).send({ error: 'Une catégorie avec ce nom existe déjà' });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return res.status(400).send({ error: 'Une erreur est survenue lors de la création de la catégorie' });
|
||||
}
|
||||
|
||||
try {
|
||||
await prisma.category.create({
|
||||
data: { name }
|
||||
});
|
||||
return res.status(200).send({ success: 'Catégorie créée avec succès' });
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return res.status(400).send({ error: 'Une erreur est survenue lors de la création de la catégorie' });
|
||||
}
|
||||
});
|
||||
|
||||
export default apiRoute;
|
||||
45
pages/api/category/edit/[cid].ts
Normal file
45
pages/api/category/edit/[cid].ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { NextApiRequest, NextApiResponse } from 'next';
|
||||
|
||||
import { apiRoute } from '../../../../utils/back';
|
||||
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
apiRoute.put(async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const { cid } = req.query;
|
||||
|
||||
let category;
|
||||
try {
|
||||
category = await prisma.category.findFirst({
|
||||
where: { id: Number(cid) }
|
||||
});
|
||||
|
||||
if (!category) {
|
||||
return res.status(400).send({ error: 'Catégorie introuvable' });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return res.status(400).send({ error: 'Une erreur est survenue lors de l\'édition de la catégorie' });
|
||||
}
|
||||
|
||||
const name = req.body?.name as string;
|
||||
if (!name) {
|
||||
return res.status(400).send({ error: 'Nom de la catégorie manquante' });
|
||||
} else if (name === category.name) {
|
||||
return res.status(400).send({ error: 'Le nom de la catégorie doit être différent du nom actuel' });
|
||||
}
|
||||
|
||||
try {
|
||||
await prisma.category.update({
|
||||
where: { id: Number(cid) },
|
||||
data: { name }
|
||||
});
|
||||
|
||||
return res.status(200).send({ success: 'Catégorie mise à jour avec succès' });
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return res.status(400).send({ error: 'Une erreur est survenue lors de l\'édition de la catégorie' });
|
||||
}
|
||||
});
|
||||
|
||||
export default apiRoute;
|
||||
36
pages/api/category/remove/[cid].ts
Normal file
36
pages/api/category/remove/[cid].ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { NextApiRequest, NextApiResponse } from 'next';
|
||||
|
||||
import { apiRoute } from '../../../../utils/back';
|
||||
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
apiRoute.delete(async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const { cid } = req.query;
|
||||
|
||||
try {
|
||||
const category = await prisma.category.findFirst({
|
||||
where: { id: Number(cid) }
|
||||
});
|
||||
|
||||
if (!category) {
|
||||
return res.status(400).send({ error: 'Categorie introuvable' });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return res.status(400).send({ error: 'Une erreur est survenue lors de la suppression de la catégorie' });
|
||||
}
|
||||
|
||||
try {
|
||||
await prisma.category.delete({
|
||||
where: { id: Number(cid) }
|
||||
});
|
||||
|
||||
return res.status(200).send({ success: 'La catégorie a été supprimée avec succès' });
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return res.status(400).send({ error: 'Une erreur est survenue lors de la suppression de la catégorie' });
|
||||
}
|
||||
});
|
||||
|
||||
export default apiRoute;
|
||||
68
pages/api/link/create.ts
Normal file
68
pages/api/link/create.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { NextApiRequest, NextApiResponse } from 'next';
|
||||
|
||||
import { apiRoute } from '../../../utils/back';
|
||||
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
apiRoute.post(async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const name = req.body?.name as string;
|
||||
const url = req.body?.url as string;
|
||||
const favorite = Boolean(req.body?.favorite) || false;
|
||||
const categoryId = Number(req.body?.categoryId);
|
||||
|
||||
if (!name) {
|
||||
return res.status(400).send({ error: 'Nom du lien manquant' });
|
||||
}
|
||||
|
||||
if (!url) {
|
||||
return res.status(400).send({ error: 'URL du lien manquant' });
|
||||
}
|
||||
|
||||
if (!categoryId) {
|
||||
return res.status(400).send({ error: 'Catégorie du lien manquante' });
|
||||
}
|
||||
|
||||
try {
|
||||
const link = await prisma.link.findFirst({
|
||||
where: { name }
|
||||
});
|
||||
|
||||
if (link) {
|
||||
return res.status(400).send({ error: 'Un lien avec ce nom existe déjà' });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return res.status(400).send({ error: 'Une erreur est survenue lors de la création du lien' });
|
||||
}
|
||||
|
||||
try {
|
||||
const category = await prisma.category.findFirst({
|
||||
where: { id: categoryId }
|
||||
});
|
||||
|
||||
if (!category) {
|
||||
return res.status(400).send({ error: 'Cette catégorie n\'existe pas' });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return res.status(400).send({ error: 'Une erreur est survenue lors de la création du lien' });
|
||||
}
|
||||
|
||||
try {
|
||||
await prisma.link.create({
|
||||
data: {
|
||||
name,
|
||||
url,
|
||||
categoryId,
|
||||
favorite
|
||||
}
|
||||
});
|
||||
return res.status(200).send({ success: 'Lien créé avec succès' });
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return res.status(400).send({ error: 'Une erreur est survenue lors de la création du lien' });
|
||||
}
|
||||
});
|
||||
|
||||
export default apiRoute;
|
||||
59
pages/api/link/edit/[lid].ts
Normal file
59
pages/api/link/edit/[lid].ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { NextApiRequest, NextApiResponse } from 'next';
|
||||
|
||||
import { apiRoute } from '../../../../utils/back';
|
||||
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
apiRoute.put(async (req: NextApiRequest, res: NextApiResponse) => { // TODO: Ajouter vérification -> l'utilisateur doit changer au moins un champ
|
||||
const { lid } = req.query;
|
||||
|
||||
try {
|
||||
const link = await prisma.link.findFirst({
|
||||
where: { id: Number(lid) }
|
||||
});
|
||||
|
||||
if (!link) {
|
||||
return res.status(400).send({ error: 'Lien introuvable' });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return res.status(400).send({ error: 'Une erreur est survenue lors de l\'édition du lien' });
|
||||
}
|
||||
|
||||
const name = req.body?.name as string;
|
||||
const url = req.body?.url as string;
|
||||
const favorite = Boolean(req.body?.favorite) || false;
|
||||
const categoryId = Number(req.body?.categoryId);
|
||||
|
||||
if (!name) {
|
||||
return res.status(400).send({ error: 'Nom du lien manquant' });
|
||||
}
|
||||
|
||||
if (!url) {
|
||||
return res.status(400).send({ error: 'URL du lien manquant' });
|
||||
}
|
||||
|
||||
if (!categoryId) {
|
||||
return res.status(400).send({ error: 'Catégorie du lien manquante' });
|
||||
}
|
||||
|
||||
try {
|
||||
await prisma.link.update({
|
||||
where: { id: Number(lid) },
|
||||
data: {
|
||||
name,
|
||||
url,
|
||||
favorite,
|
||||
categoryId
|
||||
}
|
||||
});
|
||||
|
||||
return res.status(200).send({ success: 'Lien mis à jour avec succès' });
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return res.status(400).send({ error: 'Une erreur est survenue lors de l\'édition du lien' });
|
||||
}
|
||||
});
|
||||
|
||||
export default apiRoute;
|
||||
36
pages/api/link/remove/[lid].ts
Normal file
36
pages/api/link/remove/[lid].ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { NextApiRequest, NextApiResponse } from 'next';
|
||||
|
||||
import { apiRoute } from '../../../../utils/back';
|
||||
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
apiRoute.delete(async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const { lid } = req.query;
|
||||
|
||||
try {
|
||||
const link = await prisma.link.findFirst({
|
||||
where: { id: Number(lid) }
|
||||
});
|
||||
|
||||
if (!link) {
|
||||
return res.status(400).send({ error: 'Lien introuvable' });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return res.status(400).send({ error: 'Une erreur est survenue lors de la suppression du lien' });
|
||||
}
|
||||
|
||||
try {
|
||||
await prisma.link.delete({
|
||||
where: { id: Number(lid) }
|
||||
});
|
||||
|
||||
return res.status(200).send({ success: 'Le lien a été supprimé avec succès' });
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return res.status(400).send({ error: 'Une erreur est survenue lors de la suppression du lien' });
|
||||
}
|
||||
});
|
||||
|
||||
export default apiRoute;
|
||||
Reference in New Issue
Block a user