diff --git a/.env.example b/.env.example deleted file mode 100644 index 73eec69b..00000000 --- a/.env.example +++ /dev/null @@ -1,4 +0,0 @@ -DATABASE_URL="YOUR_DATABASE_URL" - -# This env var must be prefixed with `VITE_` in order to work in the client / Vite React app. -VITE_PORT=4000 diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 68676dd3..8b2bc8d8 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -6,9 +6,10 @@ generator client { } datasource db { - provider = "postgresql" - url = env("DATABASE_URL") - shadowDatabaseUrl = env("SHADOW_DATABASE_URL") + provider = "postgresql" + url = env("DATABASE_URL") + + directUrl = env("postgresql://blog_owner:ZtmOEIzsa23p@ep-lingering-queen-a54h1djp.us-east-2.aws.neon.tech/blog?sslmode=require") } model User { diff --git a/src/client/App.jsx b/src/client/App.jsx index bae3b635..cb4ec26a 100644 --- a/src/client/App.jsx +++ b/src/client/App.jsx @@ -34,16 +34,85 @@ function App() { * */ const handleRegister = async ({ username, password }) => { - + try { + const response = await fetch(`${apiUrl}/user/register`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ username, password }), + }); + + if (!response.ok) { + throw new Error('Registration failed'); + } + + const data = await response.json(); + console.log('User registered:', data); + // You might want to automatically log in the user or show a success message + } catch (error) { + console.error('Registration error:', error); + // Handle the error (e.g., show an error message to the user) + } }; const handleLogin = async ({ username, password }) => { - + try { + const response = await fetch(`${apiUrl}/user/login`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ username, password }), + }); + + if (!response.ok) { + throw new Error('Login failed'); + } + + const { data: token } = await response.json(); + + // Save the token in local storage + localStorage.setItem('token', token); + + console.log('User logged in successfully'); + // You might want to update the app state to reflect that the user is logged in + } catch (error) { + console.error('Login error:', error); + // Handle the error (e.g., show an error message to the user) + } }; - const handleCreateMovie = async ({ title, description, runtimeMins }) => { - - } + try { + const token = localStorage.getItem('token'); + if (!token) { + throw new Error('No token found. Please login first.'); + } + + const response = await fetch(`${apiUrl}/movie`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}` + }, + body: JSON.stringify({ title, description, runtimeMins }), + }); + + if (!response.ok) { + throw new Error('Failed to create movie'); + } + + const { data: newMovie } = await response.json(); + + // Update the movies state to include the new movie + setMovies(prevMovies => [...prevMovies, newMovie]); + + console.log('Movie created successfully'); + } catch (error) { + console.error('Create movie error:', error); + // Handle the error (e.g., show an error message to the user) + } + }; return (
diff --git a/src/server/controllers/user.js b/src/server/controllers/user.js index 05db4183..41720611 100644 --- a/src/server/controllers/user.js +++ b/src/server/controllers/user.js @@ -8,29 +8,53 @@ const jwtSecret = 'mysecret'; const register = async (req, res) => { const { username, password } = req.body; - const createdUser = null; - - res.json({ data: createdUser }); + try { + // Hash the password + const hashedPassword = await bcrypt.hash(password, 10); + + // Create a new user + const createdUser = await prisma.user.create({ + data: { + username, + password: hashedPassword, + }, + }); + + // Remove the password from the response + const { password: _, ...userWithoutPassword } = createdUser; + + res.json({ data: userWithoutPassword }); + } catch (error) { + console.error('Registration error:', error); + res.status(500).json({ error: 'Registration failed' }); + } }; const login = async (req, res) => { const { username, password } = req.body; - const foundUser = null; + try { + const foundUser = await prisma.user.findUnique({ + where: { username }, + }); - if (!foundUser) { - return res.status(401).json({ error: 'Invalid username or password.' }); - } + if (!foundUser) { + return res.status(401).json({ error: 'Invalid username or password.' }); + } - const passwordsMatch = false; + const passwordsMatch = await bcrypt.compare(password, foundUser.password); - if (!passwordsMatch) { - return res.status(401).json({ error: 'Invalid username or password.' }); - } + if (!passwordsMatch) { + return res.status(401).json({ error: 'Invalid username or password.' }); + } - const token = null; + const token = jwt.sign({ username: foundUser.username }, jwtSecret, { expiresIn: '1h' }); - res.json({ data: token }); + res.json({ data: token }); + } catch (error) { + console.error('Login error:', error); + res.status(500).json({ error: 'Login failed' }); + } }; export { diff --git a/src/server/routers/movie.js b/src/server/routers/movie.js index a606c4c9..d5b63c04 100644 --- a/src/server/routers/movie.js +++ b/src/server/routers/movie.js @@ -1,6 +1,49 @@ import express from 'express'; import { getAllMovies, createMovie } from '../controllers/movie.js'; +import jwt from 'jsonwebtoken'; +import { PrismaClient } from '@prisma/client' +const prisma = new PrismaClient(); +const jwtSecret = 'mysecret'; + +const createMovie = async (req, res) => { + const { title, description, runtimeMins } = req.body; + + try { + // 1. Get the token from the appropriate request header + const token = req.headers.authorization?.split(' ')[1]; + + if (!token) { + return res.status(401).json({ error: 'No token provided' }); + } + + // 2. Verify the token using the jsonwebtoken library + const decoded = jwt.verify(token, jwtSecret); + + // 3. Create the movie and store the result in the createdMovie variable + const createdMovie = await prisma.movie.create({ + data: { + title, + description, + runtimeMins: parseInt(runtimeMins), + createdBy: decoded.username, // Assuming the username is stored in the token + }, + }); + + res.json({ data: createdMovie }); + } catch (error) { + console.error('Create movie error:', error); + if (error.name === 'JsonWebTokenError') { + return res.status(401).json({ error: 'Invalid token provided.' }); + } + res.status(500).json({ error: 'Failed to create movie' }); + } +}; + +export { + getAllMovies, + createMovie +}; const router = express.Router(); router.get('/', getAllMovies);