add API authorization

This commit is contained in:
Henry
2023-04-29 18:01:40 +01:00
parent 419d9634b4
commit 2a98c9510f
12 changed files with 967 additions and 111 deletions
@@ -1,14 +1,31 @@
import { createPortal } from 'react-dom'
import { useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { useState, useEffect } from 'react'
import { useDispatch } from 'react-redux'
import PropTypes from 'prop-types'
import { Tabs, Tab, Dialog, DialogContent, DialogTitle, Box } from '@mui/material'
import { CopyBlock, atomOneDark } from 'react-code-blocks'
// Project import
import { Dropdown } from 'ui-component/dropdown/Dropdown'
// Const
import { baseURL } from 'store/constant'
import { SET_CHATFLOW } from 'store/actions'
// Images
import pythonSVG from 'assets/images/python.svg'
import javascriptSVG from 'assets/images/javascript.svg'
import cURLSVG from 'assets/images/cURL.svg'
// API
import apiKeyApi from 'api/apikey'
import chatflowsApi from 'api/chatflows'
// Hooks
import useApi from 'hooks/useApi'
function TabPanel(props) {
const { children, value, index, ...other } = props
return (
@@ -39,8 +56,36 @@ function a11yProps(index) {
const APICodeDialog = ({ show, dialogProps, onCancel }) => {
const portalElement = document.getElementById('portal')
const navigate = useNavigate()
const dispatch = useDispatch()
const codes = ['Python', 'JavaScript', 'cURL']
const [value, setValue] = useState(0)
const [keyOptions, setKeyOptions] = useState([])
const [apiKeys, setAPIKeys] = useState([])
const [chatflowApiKeyId, setChatflowApiKeyId] = useState('')
const [selectedApiKey, setSelectedApiKey] = useState({})
const getAllAPIKeysApi = useApi(apiKeyApi.getAllAPIKeys)
const updateChatflowApi = useApi(chatflowsApi.updateChatflow)
const onApiKeySelected = (keyValue) => {
if (keyValue === 'addnewkey') {
navigate('/apikey')
return
}
setChatflowApiKeyId(keyValue)
setSelectedApiKey(apiKeys.find((key) => key.id === keyValue))
const updateBody = {
apikeyid: keyValue
}
updateChatflowApi.request(dialogProps.chatflowid, updateBody)
}
useEffect(() => {
if (updateChatflowApi.data) {
dispatch({ type: SET_CHATFLOW, chatflow: updateChatflowApi.data })
}
}, [updateChatflowApi.data, dispatch])
const handleChange = (event, newValue) => {
setValue(newValue)
@@ -83,6 +128,46 @@ output = query({
return ''
}
const getCodeWithAuthorization = (codeLang) => {
if (codeLang === 'Python') {
return `import requests
API_URL = "${baseURL}/api/v1/prediction/${dialogProps.chatflowid}"
headers = {"Authorization": "Bearer ${selectedApiKey?.apiKey}"}
def query(payload):
response = requests.post(API_URL, headers=headers, json=payload)
return response.json()
output = query({
"question": "Hey, how are you?",
})
`
} else if (codeLang === 'JavaScript') {
return `async function query(data) {
const response = await fetch(
"${baseURL}/api/v1/prediction/${dialogProps.chatflowid}",
{
headers: { Authorization: "Bearer ${selectedApiKey?.apiKey}" },
method: "POST",
body: {
"question": "Hey, how are you?"
},
}
);
const result = await response.json();
return result;
}
`
} else if (codeLang === 'cURL') {
return `curl ${baseURL}/api/v1/prediction/${dialogProps.chatflowid} \\
-X POST \\
-d '{"question": "Hey, how are you?"}'
-H "Authorization: Bearer ${selectedApiKey?.apiKey}"`
}
return ''
}
const getLang = (codeLang) => {
if (codeLang === 'Python') {
return 'python'
@@ -105,6 +190,40 @@ output = query({
return pythonSVG
}
useEffect(() => {
if (getAllAPIKeysApi.data) {
const options = [
{
label: 'No Authorization',
name: ''
}
]
for (const key of getAllAPIKeysApi.data) {
options.push({
label: key.keyName,
name: key.id
})
}
options.push({
label: '- Add New Key -',
name: 'addnewkey'
})
setKeyOptions(options)
setAPIKeys(getAllAPIKeysApi.data)
if (dialogProps.chatflowApiKeyId) {
setChatflowApiKeyId(dialogProps.chatflowApiKeyId)
setSelectedApiKey(getAllAPIKeysApi.data.find((key) => key.id === dialogProps.chatflowApiKeyId))
}
}
}, [dialogProps, getAllAPIKeysApi.data])
useEffect(() => {
if (show) getAllAPIKeysApi.request()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [show])
const component = show ? (
<Dialog
open={show}
@@ -118,29 +237,42 @@ output = query({
{dialogProps.title}
</DialogTitle>
<DialogContent>
<Tabs value={value} onChange={handleChange} aria-label='tabs'>
{codes.map((codeLang, index) => (
<Tab
icon={
<img
style={{ objectFit: 'cover', height: 'auto', width: 'auto', marginLeft: 10 }}
src={getSVG(codeLang)}
alt='code'
/>
}
iconPosition='left'
key={index}
label={codeLang}
{...a11yProps(index)}
></Tab>
))}
</Tabs>
<div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
<div style={{ flex: 80 }}>
<Tabs value={value} onChange={handleChange} aria-label='tabs'>
{codes.map((codeLang, index) => (
<Tab
icon={
<img
style={{ objectFit: 'cover', height: 'auto', width: 'auto' }}
src={getSVG(codeLang)}
alt='code'
/>
}
iconPosition='start'
key={index}
label={codeLang}
{...a11yProps(index)}
></Tab>
))}
</Tabs>
</div>
<div style={{ flex: 20 }}>
<Dropdown
name='SelectKey'
disableClearable={true}
options={keyOptions}
onSelect={(newValue) => onApiKeySelected(newValue)}
value={dialogProps.chatflowApiKeyId ?? chatflowApiKeyId ?? 'Choose an API key'}
/>
</div>
</div>
<div style={{ marginTop: 10 }}></div>
{codes.map((codeLang, index) => (
<TabPanel key={index} value={value} index={index}>
<CopyBlock
theme={atomOneDark}
text={getCode(codeLang)}
text={chatflowApiKeyId ? getCodeWithAuthorization(codeLang) : getCode(codeLang)}
language={getLang(codeLang)}
showLineNumbers={false}
wrapLines