Skip to content
Snippets Groups Projects
Commit f7d327c0 authored by Sofiane Lasri's avatar Sofiane Lasri
Browse files

feat(auth): implement authentication system with register, login, and middleware

Add API endpoints for user registration and login using bcrypt for
password hashing and comparison. Introduce a Pinia store for managing
authentication state, including login, register, and logout actions.
Implement middleware to protect admin routes, redirecting
unauthenticated users to the login page. Integrate Prisma for database
interactions.
parent 8d50607e
No related branches found
No related tags found
No related merge requests found
export default defineNuxtRouteMiddleware((to) => {
const isAuthenticated = false; // TODO: check if user is authenticated
if (!isAuthenticated && to.path.startsWith('/admin')) {
return navigateTo('/login');
}
});
\ No newline at end of file
import { compare } from 'bcrypt';
import { prisma } from '~/server/prisma';
export default defineEventHandler(async (event) => {
const userExists = await prisma.user.count();
if (!userExists) {
throw createError({ statusCode: 403, statusMessage: 'No users exist' });
}
const { email, password } = await readBody(event);
const user = await prisma.user.findUnique({
where: { email },
});
if (!user || !(await compare(password, user.password))) {
throw createError({ statusCode: 401, statusMessage: 'Invalid credentials' });
}
// Set up session or token logic here
return { user };
});
\ No newline at end of file
import { hash } from 'bcrypt';
import { prisma } from '~/server/prisma';
export default defineEventHandler(async (event) => {
const userExists = await prisma.user.count();
if (userExists) {
throw createError({ statusCode: 403, statusMessage: 'User already exists' });
}
const { email, name, password } = await readBody(event);
if (!/[A-Z]/.test(password) || !/[a-z]/.test(password) || !/[0-9]/.test(password) || !/[^A-Za-z0-9]/.test(password)) {
return new Response('Password must contain at least one uppercase letter, one lowercase letter, one number, and one special character', {
status: 422,
});
}
const hashedPassword = await hash(password, 10);
const user = await prisma.user.create({
data: {
email,
name,
password: hashedPassword,
},
});
return { user };
});
\ No newline at end of file
import {prisma} from "~/server/prisma";
export default defineEventHandler(async (event) => {
const userCount = await prisma.user.count();
return { userExists: userCount > 0 };
})
\ No newline at end of file
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export { prisma };
\ No newline at end of file
import { defineStore } from 'pinia';
import { useRouter } from 'vue-router';
export const useAuthStore = defineStore('auth', {
state: () => ({
user: null,
}),
actions: {
async login(email: string, password: string) {
try {
const response = await fetch('/api/auth/login', {
method: 'POST',
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ email, password }),
});
if (!response.ok) {
// Promise.reject() is used to avoid "'throw' of exception caught locally" warning
// https://stackoverflow.com/a/60725482/12680199
return Promise.reject(Error('Invalid credentials'));
}
this.user = await response.json();
const router = useRouter();
await router.push('/admin');
} catch (error) {
console.error(error);
}
},
async register(email: string, password: string, name: string) {
try {
const response = await fetch('/api/auth/register', {
method: 'POST',
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ email, password, name }),
});
if (!response.ok) {
// Promise.reject() is used to avoid "'throw' of exception caught locally" warning
// https://stackoverflow.com/a/60725482/12680199
return Promise.reject(Error('Error registering user'));
}
this.user = await response.json();
const router = useRouter();
await router.push('/admin');
} catch (error) {
console.error(error);
}
},
async logout() {
this.user = null;
const router = useRouter();
await router.push('/');
}
}
})
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment