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:
Sonny
2022-05-06 19:35:12 +02:00
parent 988dc47ecd
commit aee3e6a820
48 changed files with 7164 additions and 1122 deletions

View File

@@ -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;
}
}
});

View 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'
}
});

View 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;

View 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;

View 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
View 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;

View 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;

View 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;