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

Add ability to authenticated using JWT #7

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
1 change: 0 additions & 1 deletion components/MainLayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import MainLayoutFooter from './MainLayoutFooter'
export default function MainLayout({ children }) {
return (
<div className="font-body bg-gray-100 text-gray-900 leading-normal">

<MainLayoutNav />

{ children }
Expand Down
34 changes: 32 additions & 2 deletions components/MainLayoutNav.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Link from 'next/link'
import { auth, logout } from '../lib/auth'

export default function MainLayoutNav({ children }) {
return (
Expand Down Expand Up @@ -42,7 +43,7 @@ export default function MainLayoutNav({ children }) {
</div>
</div>

<div className="flex items-center">
{ !auth && <div className="flex items-center">
<Link href="/login">
<a className="flex flex-row items-center px-3 py-2 font-medium rounded-md hover:text-gray-600 focus:outline-none focus:text-gray-800">
Login
Expand All @@ -54,7 +55,36 @@ export default function MainLayoutNav({ children }) {
Register
</a>
</Link>
</div>
</div>}

{auth && <div className="flex items-center ml-2">
<div className="relative ml-3">
<div onClick={logout}>
<button className="flex items-center max-w-xs font-medium focus:outline-none focus:shadow-solid" aria-label="User menu" aria-haspopup="true">
<span className="mr-3 hover:text-gray-600 focus:outline-none focus:text-gray-800">dd</span>

<img className="w-10 h-10 rounded-full" alt="Profile Picture" />
</button>
</div>

{/* <div v-show="navigation.profile.open" className="absolute right-0 w-48 mt-2 origin-top-right rounded-md shadow-lg">
<div className="py-1 bg-white rounded-md shadow-xs">
<!-- <a href="#" className="flex flex-row items-center px-4 py-2 text-sm text-gray-700 focus:text-gray-900 hover:text-gray-900 focus:outline-none hover:bg-gray-100 focus:bg-gray-100">
<svg xmlns="http://www.w3.org/2000/svg" className="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path><circle cx="12" cy="7" r="4"></circle></svg>
<span className="ml-2">{{ $t('BrandDefault.nav.your_profile') }}</span>
</a>
<a href="#" className="flex flex-row items-center px-4 py-2 text-sm text-gray-700 focus:text-gray-900 hover:text-gray-900 focus:outline-none hover:bg-gray-100 focus:bg-gray-100">
<svg xmlns="http://www.w3.org/2000/svg" className="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>
<span className="ml-2">{{ $t('BrandDefault.nav.settings') }}</span>
</a> -->

<a @click="logout" href="#" className="w-100 flex flex-row items-center px-4 py-2 text-sm text-red-500 hover:text-red-700 hover:bg-red-100 focus:outline-none focus:text-red-700 focus:bg-red-100">
<svg xmlns="http://www.w3.org/2000/svg" className="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path><polyline points="16 17 21 12 16 7"></polyline><line x1="21" y1="12" x2="9" y2="12"></line></svg>
<span className="ml-2">{{ $t('BrandDefault.nav.logout') }}</span>
</a>
</div> */}
</div>
</div>}
</div>

</div>
Expand Down
23 changes: 23 additions & 0 deletions contexts/AuthContext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React, { useState } from 'react'

export const AuthContext = React.createContext()

const defaultState = {
user: null,
}

const AuthContextProvider = ({children}) => {
const [session, setSession] = useState(defaultState)

function setUser(user) {
setSession({...session, user})
}

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

export default AuthContextProvider
78 changes: 78 additions & 0 deletions lib/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { useEffect, useContext } from 'react'
import Router from 'next/router'
import nextCookie from 'next-cookies'
import cookie from 'js-cookie'
import { isServer } from './isServer'

export const setUserToken = (token) => {
cookie.set('token', token, { expires: 1 })
}

export const fetchUser = async (ctx) => {
const token = auth(ctx)

const response = await fetch('http://api.leer-platform.test/v1/auth/user/current', {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + token,
},
})

const { data } = await response.json()

return data
}

export const auth = ctx => {
const { token } = nextCookie(ctx)

if (!token) {
if (isServer()) {
ctx.res.writeHead(302, { Location: '/login' })
ctx.res.end()
} else {
Router.push('/login')
}
}

return token
}

export const logout = () => {
cookie.remove('token')
// to support logging out from all windows
window.localStorage.setItem('logout', Date.now())
Router.push('/login')
}

export const withAuthSync = WrappedComponent => {
const AuthComponent = props => {
const syncLogout = event => {
if (event.key === 'logout') {
console.log('logged out from storage!')
Router.push('/login')
}
}

useEffect(() => {
window.addEventListener('storage', syncLogout)

return () => {
window.removeEventListener('storage', syncLogout)
window.localStorage.removeItem('logout')
}
}, [])

return <WrappedComponent {...props} />
}

// AuthComponent.getInitialProps = async ctx => {
// const componentProps =
// WrappedComponent.getInitialProps &&
// (await WrappedComponent.getInitialProps(ctx))

// return { ...componentProps }
// }

return AuthComponent
}
1 change: 1 addition & 0 deletions lib/isServer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const isServer = typeof window === "undefined"
Loading