Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client Side Authentication #6

Merged
merged 3 commits into from
May 1, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Save User State on Client
  • Loading branch information
roshanrajeev committed May 1, 2021
commit e3a54ee0466b4148855d42c0c07373ed26db957d
26 changes: 8 additions & 18 deletions components/Header/header.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,32 @@ import {useState, useEffect} from 'react'
import Link from 'next/link'
import styles from './header.module.scss'
import Router from 'next/router'
import { useAuth } from '../../contexts/authContext'
import { clientRedirect } from '../../lib/redirect'

const Header = () => {
const [isAtuenticated, setIsAtuenticated] = useState(false)

useEffect(async () => {
if(localStorage.getItem('macebook-isauth')){
setIsAtuenticated(true)
}else{
setIsAtuenticated(false)
}
})
const [user, setUser] = useAuth()

const handleLogout = async () => {
if(localStorage.getItem('macebook-isauth')){
localStorage.removeItem('macebook-isauth')
}
const res = await fetch(`${process.env.API}/logout`, {
method: 'GET',
credentials: 'include'
})
console.log(res)
Router.replace('/')
return
setUser()
clientRedirect('/')
}

return(
<nav className={styles.navbar}>
<Link href="/"><a className={styles.navbarBrand}>Logo</a></Link>
{isAtuenticated ?
{user ?
<ul className={styles.navbarNav}>
<li className={styles.navbarLink}><Link href="/feeds"><a>Home</a></Link></li>
<li className={styles.navbarLink}><Link href="/messaging"><a>Messaging</a></Link></li>
<li className={styles.navbarLink}><Link href="/notifications"><a>Notifications</a></Link></li>
<li className={styles.navbarLink}><Link href="/profile"><a>User Icon</a></Link></li>
<li className={styles.navbarLink}><Link href="/settings"><a>Settings</a></Link></li>
<li className={styles.navbarLink} onClick={handleLogout}>Logout</li>
<li className={styles.navbarLink} onClick={handleLogout}><a>Logout</a></li>
<li className={styles.navbarLink}><Link href={`/user/${user.username}`}><a><img className={styles.picture} src={user.picture}/></a></Link></li>
</ul> :
<div>
<ul className={styles.navbarNav}>
Expand Down
10 changes: 9 additions & 1 deletion components/Header/header.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,18 @@
padding: 1rem;
background-color: $color-primary;
color: $color-white;

align-items: center;

a{
text-decoration: none;
cursor: pointer;
}
}

.navbarNav{
display: flex;
flex-direction: row;
align-items: center;
list-style-type: none;
padding: 0;
margin: 0;
Expand All @@ -25,4 +28,9 @@
&:not(:last-child){
margin-right: 1rem;
}
}

.picture{
border-radius: 50%;
height: 35px;
}
29 changes: 29 additions & 0 deletions contexts/authContext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React, { useContext, useEffect, useState } from 'react'

const AuthContext = React.createContext()

export const AuthProvider = ({children}) => {
const [user, setUser] = useState()

useEffect(() => {
if(!user){
fetch(`${process.env.API}/profile`, {
method: 'GET',
credentials: 'include'
})
.then(res => res.json())
.then(user => setUser(user))
.catch(err => console.log(err))
}
}, [user])

return(
<AuthContext.Provider value={[user, setUser]}>
{children}
</AuthContext.Provider>
)
}

export const useAuth = () => {
return useContext(AuthContext)
}
10 changes: 10 additions & 0 deletions lib/redirect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Router from "next/router"

export const clientRedirect = (slug) => {
Router.replace(slug)
}

export const serverRedirect = (ctx, slug) => {
ctx.res.writeHead(301, {Location: slug})
ctx.res.end()
}
2 changes: 1 addition & 1 deletion mock/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ router.post('/login', (req, res) => {
domain: 'localhost',
expires: new Date(Date.now() + 6.048e+8)
}))
res.status(200).json({username})
res.status(200).json({user})
})

router.get('/profile', auth, (req, res) => {
Expand Down
11 changes: 11 additions & 0 deletions pages/500.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import Layout from '../components/Layout/layout'
import SEO from '../components/seo'

export default function Custom500() {
return (
<Layout>
<SEO title="Internal Server Error | Macebook"/>
<h1>500 - Internal Server Error</h1>
</Layout>
)
}
7 changes: 6 additions & 1 deletion pages/_app.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import '../styles/globals.scss'
import 'bootstrap/dist/css/bootstrap-grid.min.css'
import {AuthProvider} from '../contexts/authContext'

function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
return (
<AuthProvider>
<Component {...pageProps} />
</AuthProvider>
)
}

export default MyApp
6 changes: 3 additions & 3 deletions pages/feeds.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Layout from '../components/Layout/layout'
import SEO from '../components/seo'
import Router from 'next/router'
import styles from '../styles/pages/feeds.module.scss'
import {clientRedirect, serverRedirect} from '../lib/redirect'

const Feeds = ({feeds}) => {
return(
Expand All @@ -21,13 +22,12 @@ Feeds.getInitialProps = async (ctx) => {
})

if(res.status === 401 && !ctx.req){
Router.replace('/login')
clientRedirect('/login')
return {}
}

if(res.status === 401 && ctx.req){
ctx.res.writeHead(301, {Location: '/login'})
ctx.res.end()
serverRedirect(ctx, '/login')
return {}
}

Expand Down
17 changes: 10 additions & 7 deletions pages/login.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import {useState} from 'react'
import {useState, useEffect} from 'react'
import SEO from '../components/seo'
import Layout from '../components/Layout/layout'
import Router from 'next/router'
import {useAuth} from '../contexts/authContext'
import {clientRedirect} from '../lib/redirect'

const Login = () => {
const [username, updateUsername] = useState("charlotteli")
const [password, updatePassword] = useState("charlotteli")
const [user, setUser] = useAuth()

useEffect(() => {if(user) clientRedirect('/feeds')}, [user])

const handleClick = async (e) => {
e.preventDefault()
Expand All @@ -21,11 +25,10 @@ const Login = () => {
return alert("Invalid Username or Password")
}

if(res.status == 200){
console.log("You're Logged In!")
localStorage.setItem('macebook-isauth', true)
return Router.replace('/feeds')
}
console.log("You're Logged In!")
localStorage.setItem('macebook-isauth', true)
const data = await res.json()
setUser(data.user)
} catch (error) {
console.log("Server not responding!")
}
Expand Down
38 changes: 0 additions & 38 deletions pages/profile.js

This file was deleted.