This content originally appeared on flaviocopes.com and was authored by flaviocopes.com
This post is part of a new series where we build a clone of Airbnb with Next.js. See the first post here.
- Part 1: Let’s start by installing Next.js
- Part 2: Build the list of houses
- Part 3: Build the house detail view
- Part 4: CSS and navigation bar
- Part 5: Start with the date picker
- Part 6: Add the sidebar
- Part 7: Add react-day-picker
- Part 8: Add the calendar to the page
- Part 9: Configure the DayPickerInput component
- Part 10: Sync the start and end dates
- Part 11: Show the price for the chosen dates
- Part 12: Login and signup forms
- Part 13: Activate the modal
- Part 14: Send registration data to the server
- Part 15: Add postgres
- Part 16: Implement model and DB connection
- Part 17: Create a session token
Let’s now implement login!
It’s going to be very similar to the registration, except we call /api/auth/login
, and we don’t have to handle the password confirmation. And contrary to registration, we fail if the user is not there yet.
Let’s first install the cookies
package from npm:
npm install cookies
Now create a pages/api/auth/login.js
file.
In there, we first receive the email
and password
fields from the request, and we see if we can find a user with that email. If not, we return an error message:
import { User, sequelize } from '../../../model.js'
export default async (req, res) => {
if (req.method !== 'POST') {
res.status(405).end() //Method Not Allowed
return
}
const { email, password } = req.body
let user = await User.findOne({ where: { email } })
if (!user) {
res.end(JSON.stringify({ status: 'error', message: 'User does not exist' }))
return
}
}
If the user exists, we check if the password is valid:
const isPasswordValid = await user.isPasswordValid(password)
if (!isPasswordValid) {
res.end(JSON.stringify({ status: 'error', message: 'Password not valid' }))
return
}
If the password is valid, we check the session is not expired. If it’s expired, we generate a new session token and a new expiration date. If not, we just expand the expiration date of 30 days:
let sessionToken = null
const sessionExpiration = new Date()
sessionExpiration.setDate(sessionExpiration.getDate() + 30)
if (new Date(user.session_expiration) < new Date()) {
sessionToken = randomString(255)
User.update(
{
session_token: sessionToken,
session_expiration: sessionExpiration
},
{ where: { email } }
)
} else {
sessionToken = user.session_token
User.update(
{
session_expiration: sessionExpiration
},
{ where: { email } }
)
}
Finally we create a cookie and store the session token in there, and we terminate the network request:
const cookies = new Cookies(req, res)
cookies.set('nextbnb_session', sessionToken, {
httpOnly: true // true by default
})
res.end(JSON.stringify({ status: 'success', message: 'Logged in' }))
Here’s the full source code of login.js
:
import { User, sequelize } from '../../../model.js'
import Cookies from 'cookies'
const randomString = (length) => {
const chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
let result = ''
for (let i = length; i > 0; --i) {
result += chars[Math.floor(Math.random() * chars.length)]
}
return result
}
export default async (req, res) => {
if (req.method !== 'POST') {
res.status(405).end() //Method Not Allowed
return
}
const { email, password } = req.body
let user = await User.findOne({ where: { email } })
if (!user) {
res.end(JSON.stringify({ status: 'error', message: 'User does not exist' }))
return
}
const isPasswordValid = await user.isPasswordValid(password)
if (!isPasswordValid) {
res.end(JSON.stringify({ status: 'error', message: 'Password not valid' }))
return
}
let sessionToken = null
const sessionExpiration = new Date()
sessionExpiration.setDate(sessionExpiration.getDate() + 30)
if (new Date(user.session_expiration) < new Date()) {
sessionToken = randomString(255)
User.update(
{
session_token: sessionToken,
session_expiration: sessionExpiration
},
{ where: { email } }
)
} else {
sessionToken = user.session_token
User.update(
{
session_expiration: sessionExpiration
},
{ where: { email } }
)
}
const cookies = new Cookies(req, res)
cookies.set('nextbnb_session', sessionToken, {
httpOnly: true // true by default
})
res.end(JSON.stringify({ status: 'success', message: 'Logged in' }))
}
In the components/LoginModal.js
file, we are going to to like we did for the registration form and use useState
to create 2 state variables for the email and the password, and we’re going to use Axios to perform the network request to /api/auth/login
when the form is submitted:
import { useState } from 'react'
import axios from 'axios'
export default function LoginModal(props) {
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const submit = async () => {
const response = await axios.post('/api/auth/login', {
email,
password
})
console.log(response)
if (response.data.status === 'error') {
alert(response.data.message)
}
}
return (
<>
<h2>Log in</h2>
<div>
<form
onSubmit={(event) => {
submit()
event.preventDefault()
}}
>
<input
id="email"
type="email"
placeholder="Email address"
onChange={(event) => setEmail(event.target.value)}
/>
<input
id="password"
type="password"
placeholder="Password"
onChange={(event) => setPassword(event.target.value)}
/>
<button>Log in</button>
</form>
</div>
<p>
Don't have an account yet?{' '}
<a href="javascript:;" onClick={() => props.showSignup()}>
Sign up
</a>
</p>
</>
)
}
This content originally appeared on flaviocopes.com and was authored by flaviocopes.com

flaviocopes.com | Sciencx (2021-12-18T05:00:00+00:00) Airbnb clone, implement login. Retrieved from https://www.scien.cx/2021/12/18/airbnb-clone-implement-login/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.