Feature: Option to add apikeys to the DB instead of api.json. (#2783)

* Feature: Option to add apikeys to the DB instead of api.json.

* add api storage type env variable

* code cleanup and simplification.

* md table fixes

---------

Co-authored-by: Henry <hzj94@hotmail.com>
This commit is contained in:
Vinod Kiran
2024-07-26 22:22:12 +05:30
committed by GitHub
parent e5018d2743
commit 2dd1791ec2
26 changed files with 647 additions and 38 deletions
+45
View File
@@ -4,6 +4,7 @@ import moment from 'moment'
import fs from 'fs'
import path from 'path'
import logger from './logger'
import { appConfig } from '../AppConfig'
/**
* Returns the api key path
@@ -50,6 +51,9 @@ export const compareKeys = (storedKey: string, suppliedKey: string): boolean =>
* @returns {Promise<ICommonObject[]>}
*/
export const getAPIKeys = async (): Promise<ICommonObject[]> => {
if (appConfig.apiKeys.storageType !== 'json') {
return []
}
try {
const content = await fs.promises.readFile(getAPIKeyPath(), 'utf8')
return JSON.parse(content)
@@ -94,6 +98,47 @@ export const addAPIKey = async (keyName: string): Promise<ICommonObject[]> => {
return content
}
/**
* import API keys
* @param {[]} keys
* @returns {Promise<ICommonObject[]>}
*/
export const importKeys = async (keys: any[], importMode: string): Promise<ICommonObject[]> => {
const allApiKeys = await getAPIKeys()
// if importMode is errorIfExist, check for existing keys and raise error before any modification to the file
if (importMode === 'errorIfExist') {
for (const key of keys) {
const keyNameExists = allApiKeys.find((k) => k.keyName === key.keyName)
if (keyNameExists) {
throw new Error(`Key with name ${key.keyName} already exists`)
}
}
}
for (const key of keys) {
// Check if keyName already exists, if overwrite is false, raise an error else overwrite the key
const keyNameExists = allApiKeys.find((k) => k.keyName === key.keyName)
if (keyNameExists) {
const keyIndex = allApiKeys.findIndex((k) => k.keyName === key.keyName)
switch (importMode) {
case 'overwriteIfExist':
allApiKeys[keyIndex] = key
continue
case 'ignoreIfExist':
// ignore this key and continue
continue
case 'errorIfExist':
// should not reach here as we have already checked for existing keys
throw new Error(`Key with name ${key.keyName} already exists`)
default:
throw new Error(`Unknown overwrite option ${importMode}`)
}
}
allApiKeys.push(key)
}
await fs.promises.writeFile(getAPIKeyPath(), JSON.stringify(allApiKeys), 'utf8')
return allApiKeys
}
/**
* Get API Key details
* @param {string} apiKey
+4 -4
View File
@@ -1,7 +1,7 @@
import { Request } from 'express'
import { ChatFlow } from '../database/entities/ChatFlow'
import { getAPIKeys, compareKeys } from './apiKey'
import { compareKeys } from './apiKey'
import apikeyService from '../services/apikey'
/**
* Validate API Key
* @param {Request} req
@@ -17,8 +17,8 @@ export const utilValidateKey = async (req: Request, chatflow: ChatFlow) => {
const suppliedKey = authorizationHeader.split(`Bearer `).pop()
if (suppliedKey) {
const keys = await getAPIKeys()
const apiSecret = keys.find((key) => key.id === chatFlowApiKeyId)?.apiSecret
const keys = await apikeyService.getAllApiKeys()
const apiSecret = keys.find((key: any) => key.id === chatFlowApiKeyId)?.apiSecret
if (!compareKeys(apiSecret, suppliedKey)) return false
return true
}