donetick-fe/src/views/Authorization/Authenticating.jsx

140 lines
4.1 KiB
React
Raw Normal View History

import { Box, Button, CircularProgress, Container, Typography } from '@mui/joy'
import { useContext, useEffect, useState } from 'react'
import Logo from '../../Logo'
import { apiManager } from '../../utils/TokenManager'
import Cookies from 'js-cookie'
import { useRef } from 'react'
import { Link, useNavigate, useParams } from 'react-router-dom'
import { UserContext } from '../../contexts/UserContext'
import { GetUserProfile } from '../../utils/Fetcher'
const AuthenticationLoading = () => {
const { userProfile, setUserProfile } = useContext(UserContext)
const Navigate = useNavigate()
const hasCalledHandleOAuth2 = useRef(false)
const [message, setMessage] = useState('Authenticating')
const [subMessage, setSubMessage] = useState('Please wait')
const [status, setStatus] = useState('pending')
const { provider } = useParams()
useEffect(() => {
if (provider === 'oauth2' && !hasCalledHandleOAuth2.current) {
hasCalledHandleOAuth2.current = true
handleOAuth2()
} else if (provider !== 'oauth2') {
setMessage('Unknown Authentication Provider')
setSubMessage('Please contact support')
}
}, [provider])
const getUserProfileAndNavigateToHome = () => {
GetUserProfile().then(data => {
data.json().then(data => {
setUserProfile(data.res)
// check if redirect url is set in cookie:
const redirectUrl = Cookies.get('ca_redirect')
if (redirectUrl) {
Cookies.remove('ca_redirect')
Navigate(redirectUrl)
} else {
Navigate('/my/chores')
}
})
})
}
const handleOAuth2 = () => {
// get provider from params:
const urlParams = new URLSearchParams(window.location.search)
const code = urlParams.get('code')
const returnedState = urlParams.get('state')
const storedState = localStorage.getItem('authState')
if (returnedState !== storedState) {
setMessage('Authentication failed')
setSubMessage('State does not match')
setStatus('error')
return
}
if (code) {
const baseURL = apiManager.getApiURL()
fetch(`${baseURL}/auth/${provider}/callback`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
code,
state: returnedState,
}),
}).then(response => {
if (response.status === 200) {
return response.json().then(data => {
localStorage.setItem('ca_token', data.token)
localStorage.setItem('ca_expiration', data.expire)
const redirectUrl = Cookies.get('ca_redirect')
if (redirectUrl) {
Cookies.remove('ca_redirect')
Navigate(redirectUrl)
} else {
getUserProfileAndNavigateToHome()
}
})
} else {
console.error('Authentication failed')
setMessage('Authentication failed')
setSubMessage('Please try again')
setStatus('error')
}
})
}
}
return (
<Container className='flex h-full items-center justify-center'>
<Box
className='flex flex-col items-center justify-center'
sx={{
minHeight: '80vh',
}}
>
<CircularProgress
determinate={status === 'error'}
color={status === 'pending' ? 'primary' : 'danger'}
sx={{ '--CircularProgress-size': '200px' }}
>
<Logo />
</CircularProgress>
<Box
className='flex items-center gap-2'
sx={{
fontWeight: 700,
fontSize: 24,
mt: 2,
}}
>
{message}
</Box>
<Typography level='body-md' fontWeight={500} textAlign={'center'}>
{subMessage}
</Typography>
{status === 'error' && (
<Button
size='lg'
variant='outlined'
sx={{
mt: 4,
}}
>
<Link to='/login'>Go back Login</Link>
</Button>
)}
</Box>
</Container>
)
}
export default AuthenticationLoading