API Keys: Displaying the names of the chatflows associated with the keys and Warning the user before deletion.

This commit is contained in:
vinodkiran 2023-11-18 16:47:15 +05:30
parent 34702a9ba2
commit 28f5d94c13
2 changed files with 104 additions and 64 deletions

View File

@ -1135,28 +1135,50 @@ export class App {
// API Keys
// ----------------------------------------
const addChatflowsCount = async (keys: any, res: Response) => {
if (keys) {
const updatedKeys: any[] = []
//iterate through keys and get chatflows
for (const key of keys) {
const chatflows = await this.AppDataSource.getRepository(ChatFlow)
.createQueryBuilder('cf')
.where('cf.apikeyid = :apikeyid', { apikeyid: key.id })
.getMany()
const linkedChatFlows: any[] = []
chatflows.map((cf) => {
linkedChatFlows.push({
flowName: cf.name
})
})
key.chatFlows = linkedChatFlows
updatedKeys.push(key)
}
return res.json(updatedKeys)
}
return res.json(keys)
}
// Get api keys
this.app.get('/api/v1/apikey', async (req: Request, res: Response) => {
const keys = await getAPIKeys()
return res.json(keys)
return addChatflowsCount(keys, res)
})
// Add new api key
this.app.post('/api/v1/apikey', async (req: Request, res: Response) => {
const keys = await addAPIKey(req.body.keyName)
return res.json(keys)
return addChatflowsCount(keys, res)
})
// Update api key
this.app.put('/api/v1/apikey/:id', async (req: Request, res: Response) => {
const keys = await updateAPIKey(req.params.id, req.body.keyName)
return res.json(keys)
return addChatflowsCount(keys, res)
})
// Delete new api key
this.app.delete('/api/v1/apikey/:id', async (req: Request, res: Response) => {
const keys = await deleteAPIKey(req.params.id)
return res.json(keys)
return addChatflowsCount(keys, res)
})
// Verify api key

View File

@ -6,6 +6,7 @@ import { enqueueSnackbar as enqueueSnackbarAction, closeSnackbar as closeSnackba
import {
Button,
Box,
Chip,
Stack,
Table,
TableBody,
@ -37,7 +38,7 @@ import useConfirm from 'hooks/useConfirm'
import useNotifier from 'utils/useNotifier'
// Icons
import { IconTrash, IconEdit, IconCopy, IconX, IconPlus, IconEye, IconEyeOff } from '@tabler/icons'
import { IconTrash, IconEdit, IconCopy, IconCornerDownRight, IconX, IconPlus, IconEye, IconEyeOff } from '@tabler/icons'
import APIEmptySVG from 'assets/images/api_empty.svg'
// ==============================|| APIKey ||============================== //
@ -106,7 +107,10 @@ const APIKey = () => {
const deleteKey = async (key) => {
const confirmPayload = {
title: `Delete`,
description: `Delete key ${key.keyName}?`,
description:
key.chatFlows.length === 0
? `Delete key [${key.keyName}] ? `
: `Delete key [${key.keyName}] ?\n There are ${key.chatFlows.length} chatflows using this key.`,
confirmButtonName: 'Delete',
cancelButtonName: 'Cancel'
}
@ -193,6 +197,7 @@ const APIKey = () => {
<TableRow>
<TableCell>Key Name</TableCell>
<TableCell>API Key</TableCell>
<TableCell>Usage</TableCell>
<TableCell>Created</TableCell>
<TableCell> </TableCell>
<TableCell> </TableCell>
@ -200,65 +205,78 @@ const APIKey = () => {
</TableHead>
<TableBody>
{apiKeys.map((key, index) => (
<TableRow key={index} sx={{ '&:last-child td, &:last-child th': { border: 0 } }}>
<TableCell component='th' scope='row'>
{key.keyName}
</TableCell>
<TableCell>
{showApiKeys.includes(key.apiKey)
? key.apiKey
: `${key.apiKey.substring(0, 2)}${'•'.repeat(18)}${key.apiKey.substring(
key.apiKey.length - 5
)}`}
<IconButton
title='Copy'
color='success'
onClick={(event) => {
navigator.clipboard.writeText(key.apiKey)
setAnchorEl(event.currentTarget)
setTimeout(() => {
handleClosePopOver()
}, 1500)
}}
>
<IconCopy />
</IconButton>
<IconButton title='Show' color='inherit' onClick={() => onShowApiKeyClick(key.apiKey)}>
{showApiKeys.includes(key.apiKey) ? <IconEyeOff /> : <IconEye />}
</IconButton>
<Popover
open={openPopOver}
anchorEl={anchorEl}
onClose={handleClosePopOver}
anchorOrigin={{
vertical: 'top',
horizontal: 'right'
}}
transformOrigin={{
vertical: 'top',
horizontal: 'left'
}}
>
<Typography
variant='h6'
sx={{ pl: 1, pr: 1, color: 'white', background: theme.palette.success.dark }}
<>
<TableRow key={index} sx={{ '&:last-child td, &:last-child th': { border: 0 } }}>
<TableCell component='th' scope='row'>
{key.keyName}
</TableCell>
<TableCell>
{showApiKeys.includes(key.apiKey)
? key.apiKey
: `${key.apiKey.substring(0, 2)}${'•'.repeat(18)}${key.apiKey.substring(
key.apiKey.length - 5
)}`}
<IconButton
title='Copy'
color='success'
onClick={(event) => {
navigator.clipboard.writeText(key.apiKey)
setAnchorEl(event.currentTarget)
setTimeout(() => {
handleClosePopOver()
}, 1500)
}}
>
Copied!
</Typography>
</Popover>
</TableCell>
<TableCell>{key.createdAt}</TableCell>
<TableCell>
<IconButton title='Edit' color='primary' onClick={() => edit(key)}>
<IconEdit />
</IconButton>
</TableCell>
<TableCell>
<IconButton title='Delete' color='error' onClick={() => deleteKey(key)}>
<IconTrash />
</IconButton>
</TableCell>
</TableRow>
<IconCopy />
</IconButton>
<IconButton title='Show' color='inherit' onClick={() => onShowApiKeyClick(key.apiKey)}>
{showApiKeys.includes(key.apiKey) ? <IconEyeOff /> : <IconEye />}
</IconButton>
<Popover
open={openPopOver}
anchorEl={anchorEl}
onClose={handleClosePopOver}
anchorOrigin={{
vertical: 'top',
horizontal: 'right'
}}
transformOrigin={{
vertical: 'top',
horizontal: 'left'
}}
>
<Typography
variant='h6'
sx={{ pl: 1, pr: 1, color: 'white', background: theme.palette.success.dark }}
>
Copied!
</Typography>
</Popover>
</TableCell>
<TableCell>{key.chatFlows.length}</TableCell>
<TableCell>{key.createdAt}</TableCell>
<TableCell>
<IconButton title='Edit' color='primary' onClick={() => edit(key)}>
<IconEdit />
</IconButton>
</TableCell>
<TableCell>
<IconButton title='Delete' color='error' onClick={() => deleteKey(key)}>
<IconTrash />
</IconButton>
</TableCell>
</TableRow>
{key.chatFlows.length > 0 && (
<TableRow sx={{ verticalAlign: 'middle' }}>
<TableCell colSpan={6}>
<IconCornerDownRight />{' '}
{key.chatFlows.map((flow, index) => (
<Chip key={index} label={flow.flowName} />
))}
</TableCell>
</TableRow>
)}
</>
))}
</TableBody>
</Table>