Skip to content
This repository has been archived by the owner on Dec 26, 2023. It is now read-only.

Commit

Permalink
add auth alert when front gets a 401 or 403
Browse files Browse the repository at this point in the history
  • Loading branch information
vieiralucas committed Jul 15, 2023
1 parent e714f9c commit 14782da
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 11 deletions.
13 changes: 7 additions & 6 deletions front/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Navigate, RouterProvider, createBrowserRouter } from 'react-router-dom'

import { RequireAuth, RequireNoAuth } from './components/RequireAuth'
import { ThemeContext, useThemeProvider } from './hooks/useTheme'
import { AuthErrorProvider } from './hooks/useAuthError'
import { ThemeProvider } from './hooks/useTheme'
import Environment from './pages/Environment'
import Environments from './pages/Environments'
import Login from './pages/Login'
Expand Down Expand Up @@ -66,12 +67,12 @@ const router = createBrowserRouter([
])

function App() {
const themeValue = useThemeProvider()

return (
<ThemeContext.Provider value={themeValue}>
<RouterProvider router={router} />
</ThemeContext.Provider>
<ThemeProvider>
<AuthErrorProvider>
<RouterProvider router={router} />
</AuthErrorProvider>
</ThemeProvider>
)
}

Expand Down
23 changes: 23 additions & 0 deletions front/src/components/AuthAlert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ExclamationTriangleIcon } from '@heroicons/react/24/solid'

function AuthAlert() {
const redirectUrl = `${window.location.protocol}//${window.location.host}`
const loginUrl = `${process.env.REACT_APP_ERGOMAKE_API}/v2/auth/login?redirectUrl=${redirectUrl}`

return (
<div className="bg-yellow-100/50 text-gray-300 p-4 border-b border-b-gray-200 dark:border-t dark:border-yellow-400 flex space-x-2 items-center justify-center font-bold">
<ExclamationTriangleIcon className="w-6 h-6 inline-block text-yellow-500 dark:text-yellow-400" />
<span className="text-gray-600 dark:text-gray-300">
You're no longer authenticated.{' '}
<a
className="text-primary-500 hover:underline hover:text-primary-400 dark:text-white"
href={loginUrl}
>
Sign in with GitHub.
</a>
</span>
</div>
)
}

export default AuthAlert
6 changes: 5 additions & 1 deletion front/src/components/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ import { useNavigate, useParams } from 'react-router-dom'
import BillingAlert from '../components/BillingAlert'
import Logo from '../components/Logo'
import WebsitePath, { Pages } from '../components/WebsitePath'
import { useAuthError } from '../hooks/useAuthError'
import { orElse } from '../hooks/useHTTPRequest'
import { Owner, useOwners } from '../hooks/useOwners'
import { Profile } from '../hooks/useProfile'
import { useTheme } from '../hooks/useTheme'
import AuthAlert from './AuthAlert'

const navigation = [
{ name: 'Repositories', href: '#', icon: FolderIcon, current: true },
Expand Down Expand Up @@ -333,6 +335,7 @@ type LayoutProps = {
}

const Layout = ({ profile, children, pages }: LayoutProps) => {
const [authError] = useAuthError()
const params = useParams<{ owner: string }>()
const [sidebarOpen, setSidebarOpen] = useState(false)

Expand Down Expand Up @@ -362,9 +365,10 @@ const Layout = ({ profile, children, pages }: LayoutProps) => {
/>

<main className="flex flex-col h-screen overflow-hidden">
{currentOwner && !currentOwner.isPaying && (
{!authError && currentOwner && !currentOwner.isPaying && (
<BillingAlert owner={currentOwner.login} />
)}
{authError && <AuthAlert />}

{children}
</main>
Expand Down
23 changes: 23 additions & 0 deletions front/src/hooks/useAuthError.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { createContext, useContext, useState } from 'react'

type UseAuthError = [boolean, (error: boolean) => void]
export const AuthErrorContext = createContext<UseAuthError>([
false,
(_: boolean) => {},
])

export const useAuthErrorProvider = (): UseAuthError => {
return useState(false)
}

export function AuthErrorProvider({ children }: { children: React.ReactNode }) {
const themeValue = useAuthErrorProvider()

return (
<AuthErrorContext.Provider value={themeValue}>
{children}
</AuthErrorContext.Provider>
)
}

export const useAuthError = () => useContext(AuthErrorContext)
12 changes: 8 additions & 4 deletions front/src/hooks/useHTTPRequest.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { useCallback, useEffect, useMemo, useState } from 'react'

import { useAuthError } from './useAuthError'

export type HTTPError =
| { _tag: 'authentication' }
| { _tag: 'unexpected'; err: Error }
Expand Down Expand Up @@ -85,6 +87,7 @@ export type UseHTTPRequest<T> = [HTTPResponse<T>, () => void]
export const useOptionalHTTPRequest = <T>(
url: string
): UseHTTPRequest<T | null> => {
const [, setAuthError] = useAuthError()
const [state, setState] = useState<HTTPResponse<T | null>>({
_tag: 'loading',
})
Expand All @@ -104,8 +107,8 @@ export const useOptionalHTTPRequest = <T>(
}

if (res.status === 401 || res.status === 403) {
setAuthError(true)
setState({ _tag: 'error', err: { _tag: 'authentication' } })
localStorage.clear()
return
}

Expand Down Expand Up @@ -139,7 +142,7 @@ export const useOptionalHTTPRequest = <T>(
return () => {
abortController.abort()
}
}, [url, state])
}, [url, state, setAuthError])

useEffect(() => {
setState({ _tag: 'loading' })
Expand Down Expand Up @@ -193,6 +196,7 @@ export type UseHTTPMutation<P, R = P> = [
export const useHTTPMutation = <P, R = P>(
url: string
): UseHTTPMutation<P, R> => {
const [, setAuthError] = useAuthError()
const [state, setState] = useState<HTTPMutationResponse<R>>({
_tag: 'pristine',
})
Expand All @@ -214,7 +218,7 @@ export const useHTTPMutation = <P, R = P>(
.then(async (res) => {
if (res.status === 401 || res.status === 403) {
setState({ _tag: 'error', err: { _tag: 'authentication' } })
localStorage.clear()
setAuthError(true)
return
}

Expand All @@ -229,7 +233,7 @@ export const useHTTPMutation = <P, R = P>(
setState({ _tag: 'error', err: { _tag: 'unexpected', err } })
})
},
[url]
[url, setAuthError]
)

return useMemo(() => [state, makeRequest], [state, makeRequest])
Expand Down
8 changes: 8 additions & 0 deletions front/src/hooks/useTheme.ts → front/src/hooks/useTheme.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,11 @@ export const useThemeProvider = (): UseTheme => {
}

export const useTheme = () => useContext(ThemeContext)

export function ThemeProvider({ children }: { children: React.ReactNode }) {
const themeValue = useThemeProvider()

return (
<ThemeContext.Provider value={themeValue}>{children}</ThemeContext.Provider>
)
}

0 comments on commit 14782da

Please sign in to comment.