187 lines
5.0 KiB
JavaScript
187 lines
5.0 KiB
JavaScript
import { useContext, useEffect, useMemo, useState } from 'react'
|
|
import { Alert, Button, Card, Flex, message } from 'antd'
|
|
import CheckIcon from '../../../Icons/CheckIcon'
|
|
import { useLocation, useNavigate } from 'react-router-dom'
|
|
import { LoadingOutlined } from '@ant-design/icons'
|
|
import { ApiServerContext } from '../../context/ApiServerContext'
|
|
import {
|
|
clearMarketplaceAuthState,
|
|
parseMarketplaceAuthState,
|
|
readMarketplaceAuthState
|
|
} from './authUtils'
|
|
import { AuthContext } from '../../context/AuthContext'
|
|
import AuthParticles from '../../../App/AppParticles'
|
|
import FarmControlLogo from '../../../Logos/FarmControlLogo'
|
|
import ExclamationOctagonIcon from '../../../Icons/ExclamationOctagonIcon'
|
|
import ArrowLeftIcon from '../../../Icons/ArrowLeftIcon'
|
|
|
|
const MarketplaceAuthCallback = () => {
|
|
const location = useLocation()
|
|
const navigate = useNavigate()
|
|
const { token } = useContext(AuthContext)
|
|
const { sendObjectFunction, connected } = useContext(ApiServerContext)
|
|
const [status, setStatus] = useState('loading')
|
|
const [redirectLoading, setRedirectLoading] = useState(false)
|
|
const [resultMessage, setResultMessage] = useState('')
|
|
|
|
const params = useMemo(
|
|
() => new URLSearchParams(location.search),
|
|
[location.search]
|
|
)
|
|
const rawState = params.get('state') || ''
|
|
const parsedState = parseMarketplaceAuthState(rawState)
|
|
const storedState = readMarketplaceAuthState(rawState)
|
|
const marketplaceId =
|
|
params.get('marketplaceId') ||
|
|
parsedState?.marketplaceId ||
|
|
storedState?.marketplaceId ||
|
|
''
|
|
const returnTo =
|
|
parsedState?.returnTo ||
|
|
storedState?.returnTo ||
|
|
(marketplaceId
|
|
? `/dashboard/sales/marketplaces/info?marketplaceId=${marketplaceId}`
|
|
: '/dashboard/sales/marketplaces')
|
|
|
|
useEffect(() => {
|
|
if (!connected || token == null || !token) {
|
|
return
|
|
}
|
|
|
|
const error = params.get('error') || params.get('error_description')
|
|
const code = params.get('code') || params.get('auth_code')
|
|
|
|
if (error) {
|
|
setStatus('error')
|
|
setResultMessage(error)
|
|
if (rawState) {
|
|
clearMarketplaceAuthState(rawState)
|
|
}
|
|
return
|
|
}
|
|
|
|
if (!marketplaceId) {
|
|
setStatus('error')
|
|
setResultMessage('Could not determine which marketplace to connect.')
|
|
return
|
|
}
|
|
|
|
if (!code) {
|
|
setStatus('error')
|
|
setResultMessage('Authorization code was not returned by the provider.')
|
|
return
|
|
}
|
|
|
|
let cancelled = false
|
|
|
|
const exchangeCode = async () => {
|
|
try {
|
|
const result = await sendObjectFunction(
|
|
marketplaceId,
|
|
'Marketplace',
|
|
'auth/exchange',
|
|
{
|
|
code,
|
|
state: rawState
|
|
}
|
|
)
|
|
if (!result?.success) {
|
|
throw new Error(
|
|
result?.error || 'Failed to complete marketplace authorization.'
|
|
)
|
|
}
|
|
|
|
if (cancelled) {
|
|
return
|
|
}
|
|
|
|
setStatus('success')
|
|
setResultMessage('Marketplace authorization completed successfully.')
|
|
message.success('Marketplace connected')
|
|
if (rawState) {
|
|
clearMarketplaceAuthState(rawState)
|
|
}
|
|
} catch (error) {
|
|
if (cancelled) {
|
|
return
|
|
}
|
|
|
|
console.error('Marketplace auth callback failed:', error)
|
|
setStatus('error')
|
|
setResultMessage(
|
|
error?.response?.data?.error ||
|
|
error?.message ||
|
|
'Failed to complete marketplace authorization.'
|
|
)
|
|
}
|
|
}
|
|
|
|
exchangeCode()
|
|
|
|
return () => {
|
|
cancelled = true
|
|
}
|
|
}, [marketplaceId, params, rawState, sendObjectFunction, token, connected])
|
|
|
|
return (
|
|
<>
|
|
<AuthParticles />
|
|
<Flex
|
|
align='center'
|
|
justify='center'
|
|
vertical
|
|
style={{ height: '100vh' }}
|
|
gap='large'
|
|
>
|
|
<Card style={{ borderRadius: 20 }}>
|
|
<Flex vertical align='center'>
|
|
<FarmControlLogo style={{ fontSize: '500px', height: '40px' }} />
|
|
</Flex>
|
|
</Card>
|
|
|
|
{status != 'error' && status != 'success' && (
|
|
<Alert
|
|
message='Completing provider authorization...'
|
|
icon={<LoadingOutlined />}
|
|
type='info'
|
|
showIcon
|
|
/>
|
|
)}
|
|
|
|
{status === 'success' && (
|
|
<Alert
|
|
message={resultMessage}
|
|
icon={<CheckIcon />}
|
|
type='success'
|
|
showIcon
|
|
/>
|
|
)}
|
|
|
|
{status === 'error' && (
|
|
<Alert
|
|
message={resultMessage}
|
|
icon={<ExclamationOctagonIcon />}
|
|
type='error'
|
|
showIcon
|
|
/>
|
|
)}
|
|
|
|
<Flex gap='middle'>
|
|
<Button
|
|
icon={<ArrowLeftIcon />}
|
|
onClick={() => {
|
|
setRedirectLoading(true)
|
|
navigate(returnTo)
|
|
}}
|
|
loading={redirectLoading}
|
|
disabled={status === 'loading' || redirectLoading}
|
|
size='large'
|
|
></Button>
|
|
</Flex>
|
|
</Flex>
|
|
</>
|
|
)
|
|
}
|
|
|
|
export default MarketplaceAuthCallback
|