From 7db0430f8abdd46fb247f7561885c99174552096 Mon Sep 17 00:00:00 2001 From: mushan0x0 Date: Sat, 16 Dec 2023 19:45:42 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20supports=20setting=20=20mul?= =?UTF-8?q?tiple=20access=20code=20(#647)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨ feat: `ACCESS_CODE` supports setting multiple * 📝 docs: Update the `ACCESS_CODE` documentation * ✅ test: Add `ACCESS_CODE` testing --- README.md | 2 +- README.zh-CN.md | 2 +- docs/Deployment/Deploy-with-Azure-OpenAI.md | 14 ++--- .../Deploy-with-Azure-OpenAI.zh-CN.md | 14 ++--- docs/Deployment/Environment-Variable.md | 4 +- src/app/api/auth.ts | 6 +-- src/app/api/config.test.ts | 51 +++++++++++++++++++ src/config/server.ts | 6 +-- 8 files changed, 75 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 90cf6ed2f5d1..d6515a6f6fb9 100644 --- a/README.md +++ b/README.md @@ -395,7 +395,7 @@ This project provides some additional configuration items set with environment v | `OPENAI_API_KEY` | Yes | This is the API key you apply on the OpenAI account page | `sk-xxxxxx...xxxxxx` | | `OPENAI_PROXY_URL` | No | If you manually configure the OpenAI interface proxy, you can use this configuration item to override the default OpenAI API request base URL | `https://api.chatanywhere.cn/v1`
The default value is
`https://api.openai.com/v1` | | `OPENAI_FUNCTION_REGIONS` | No | When you deploy Lobe-Chat using Vercel and need to specify the region for the Edge Function that handles requests to the OpenAI API, you can use this configuration. The value should be a comma-separated array of strings. | `iad1,sfo1` | -| `ACCESS_CODE` | No | Add a password to access this service; you can set a long password to avoid leaking | `awCTe)re_r74` or `rtrt_ewee3@09!` | +| `ACCESS_CODE` | No | Add a password to access this service; you can set a long password to avoid leaking. If this value contains a comma, it is a password array. | `awCTe)re_r74` or `rtrt_ewee3@09!` or `code1,code2,code3` | > \[!NOTE] > diff --git a/README.zh-CN.md b/README.zh-CN.md index 9c013eaa840f..34e548eec3b9 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -367,7 +367,7 @@ $ docker run -d -p 3210:3210 \ | `OPENAI_API_KEY` | 必选 | 这是你在 OpenAI 账户页面申请的 API 密钥 | `sk-xxxxxx...xxxxxx` | | `OPENAI_PROXY_URL` | 可选 | 如果你手动配置了 OpenAI 接口代理,可以使用此配置项来覆盖默认的 OpenAI API 请求基础 URL | `https://api.chatanywhere.cn/v1`
默认值:
`https://api.openai.com/v1` | | `OPENAI_FUNCTION_REGIONS` | 可选 | 当你使用 Vercel 部署 Lobe-Chat,而且有需求指定响应调用 OpenAI 接口的请求的 Edge Function 的 Region 时,可以使用该配置进行配置,该值的类型为逗号分隔的字符串数组 | `iad1,sfo1` | -| `ACCESS_CODE` | 可选 | 添加访问此服务的密码,你可以设置一个长密码以防被爆破 | `awCTe)re_r74` or `rtrt_ewee3@09!` | +| `ACCESS_CODE` | 可选 | 添加访问此服务的密码,你可以设置一个长密码以防被爆破,该值用逗号分隔时为密码数组 | `awCTe)re_r74` or `rtrt_ewee3@09!` or `code1,code2,code3` | > \[!NOTE] > diff --git a/docs/Deployment/Deploy-with-Azure-OpenAI.md b/docs/Deployment/Deploy-with-Azure-OpenAI.md index 0a2ae347575d..fdc23c76552d 100644 --- a/docs/Deployment/Deploy-with-Azure-OpenAI.md +++ b/docs/Deployment/Deploy-with-Azure-OpenAI.md @@ -37,13 +37,13 @@ After completing the above field configuration, click on "Check". If the prompt If you want the deployed version to be directly configured with Azure OpenAI for end users to use immediately, you need to configure the following environment variables at deployment: -| Environment Variable | Required | Description | Default Value | Example | -| -------------------- | -------- | --------------------------------------------------------------------------------- | ------------------ | -------------------------------------------------------------- | -| `USE_AZURE_OPENAI` | Yes | Set this value to `1` to enable Azure OpenAI configuration | - | `1` | -| `AZURE_API_KEY` | Yes | This is the API key you applied for on the Azure OpenAI account page | - | `c55168be3874490ef0565d9779ecd5a6` | -| `OPENAI_PROXY_URL` | Yes | Azure API address, can be found in the "Keys and Endpoints" section | - | `https://docs-test-001.openai.azure.com` | -| `AZURE_API_VERSION` | No | Azure's API version, follows the YYYY-MM-DD format | 2023-08-01-preview | `2023-05-15`, refer to [latest version][azure-api-version-url] | -| `ACCESS_CODE` | No | Add a password to access this service, the password should be 6 digits or letters | - | `awCT74` or `e3@09!` | +| Environment Variable | Required | Description | Default Value | Example | +| -------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | -------------------------------------------------------------- | +| `USE_AZURE_OPENAI` | Yes | Set this value to `1` to enable Azure OpenAI configuration | - | `1` | +| `AZURE_API_KEY` | Yes | This is the API key you applied for on the Azure OpenAI account page | - | `c55168be3874490ef0565d9779ecd5a6` | +| `OPENAI_PROXY_URL` | Yes | Azure API address, can be found in the "Keys and Endpoints" section | - | `https://docs-test-001.openai.azure.com` | +| `AZURE_API_VERSION` | No | Azure's API version, follows the YYYY-MM-DD format | 2023-08-01-preview | `2023-05-15`, refer to [latest version][azure-api-version-url] | +| `ACCESS_CODE` | No | Add a password to access this service; you can set a long password to avoid leaking. If this value contains a comma, it is a password array. | - | `awCT74` or `e3@09!` or `code1,code2,code3` | > \[!NOTE] > diff --git a/docs/Deployment/Deploy-with-Azure-OpenAI.zh-CN.md b/docs/Deployment/Deploy-with-Azure-OpenAI.zh-CN.md index 45cd148755af..3c31e2761219 100644 --- a/docs/Deployment/Deploy-with-Azure-OpenAI.zh-CN.md +++ b/docs/Deployment/Deploy-with-Azure-OpenAI.zh-CN.md @@ -37,13 +37,13 @@ LobeChat 支持使用 [Azure OpenAI][azure-openai-url] 作为 OpenAI 的模型 如果你希望部署的版本直接配置好 Azure OpenAI,让终端用户直接使用,那么你需要在部署时配置以下环境变量: -| 环境变量 | 类型 | 描述 | 默认值 | 示例 | -| ------------------- | ---- | --------------------------------------------------------------------------- | ------------------ | -------------------------------------------------- | -| `USE_AZURE_OPENAI` | 必选 | 设置改值为 `1` 开启 Azure OpenAI 配置 | - | `1` | -| `AZURE_API_KEY` | 必选 | 这是你在 Azure OpenAI 账户页面申请的 API 密钥 | - | `c55168be3874490ef0565d9779ecd5a6` | -| `OPENAI_PROXY_URL` | 必选 | Azure API 地址,从 Azure 门户检查资源时,可在 “密钥和终结点” 部分中找到此值 | - | `https://docs-test-001.openai.azure.com` | -| `AZURE_API_VERSION` | 可选 | Azure 的 API 版本,遵循 YYYY-MM-DD 格式 | 2023-08-01-preview | `2023-05-15`,查阅[最新版本][azure-api-verion-url] | -| `ACCESS_CODE` | 可选 | 添加访问此服务的密码,密码应为 6 位数字或字母 | - | `awCT74` 或 `e3@09!` | +| 环境变量 | 类型 | 描述 | 默认值 | 示例 | +| ------------------- | ---- | -------------------------------------------------------------------------------- | ------------------ | -------------------------------------------------- | +| `USE_AZURE_OPENAI` | 必选 | 设置改值为 `1` 开启 Azure OpenAI 配置 | - | `1` | +| `AZURE_API_KEY` | 必选 | 这是你在 Azure OpenAI 账户页面申请的 API 密钥 | - | `c55168be3874490ef0565d9779ecd5a6` | +| `OPENAI_PROXY_URL` | 必选 | Azure API 地址,从 Azure 门户检查资源时,可在 “密钥和终结点” 部分中找到此值 | - | `https://docs-test-001.openai.azure.com` | +| `AZURE_API_VERSION` | 可选 | Azure 的 API 版本,遵循 YYYY-MM-DD 格式 | 2023-08-01-preview | `2023-05-15`,查阅[最新版本][azure-api-verion-url] | +| `ACCESS_CODE` | 可选 | 添加访问此服务的密码,你可以设置一个长密码以防被爆破,该值用逗号分隔时为密码数组 | - | `awCT74` 或 `e3@09!` or `code1,code2,code3` | > \[!NOTE] > diff --git a/docs/Deployment/Environment-Variable.md b/docs/Deployment/Environment-Variable.md index 72e8316a3b28..ce195e617d9c 100644 --- a/docs/Deployment/Environment-Variable.md +++ b/docs/Deployment/Environment-Variable.md @@ -27,9 +27,9 @@ LobeChat provides additional configuration options during deployment, which can ### `ACCESS_CODE` - Type: Optional -- Description: Add a password to access the LobeChat service, ; you can set a long password to avoid leaking. +- Description: Add a password to access the LobeChat service, ; you can set a long password to avoid leaking. If this value contains a comma, it is a password array. - Default: `-` -- Example: `awCTe)re_r74` or `rtrt_ewee3@09!` +- Example: `awCTe)re_r74` or `rtrt_ewee3@09!` or `code1,code2,code3` ### `NEXT_PUBLIC_CUSTOM_MODELS` diff --git a/src/app/api/auth.ts b/src/app/api/auth.ts index e997953918be..1168aed807af 100644 --- a/src/app/api/auth.ts +++ b/src/app/api/auth.ts @@ -7,7 +7,7 @@ interface AuthConfig { } export const checkAuth = ({ apiKey, accessCode }: AuthConfig) => { - const { ACCESS_CODE } = getServerConfig(); + const { ACCESS_CODES } = getServerConfig(); // if apiKey exist if (apiKey) { @@ -15,9 +15,9 @@ export const checkAuth = ({ apiKey, accessCode }: AuthConfig) => { } // if accessCode doesn't exist - if (!ACCESS_CODE) return { auth: true }; + if (!ACCESS_CODES.length) return { auth: true }; - if (accessCode !== ACCESS_CODE) { + if (!accessCode || !ACCESS_CODES.includes(accessCode)) { return { auth: false, error: ChatErrorType.InvalidAccessCode }; } diff --git a/src/app/api/config.test.ts b/src/app/api/config.test.ts index 503d0b2a521e..8a7fdfbb3b92 100644 --- a/src/app/api/config.test.ts +++ b/src/app/api/config.test.ts @@ -1,5 +1,6 @@ import { describe, expect, it, vi } from 'vitest'; +import { checkAuth } from './auth'; import { getPreferredRegion } from './config'; // Stub the global process object to safely mock environment variables @@ -40,3 +41,53 @@ describe('getPreferredRegion', () => { expect(preferredRegion).toStrictEqual(['ida1', 'sfo1']); }); }); + +describe('ACCESS_CODE', () => { + let auth = false; + + beforeEach(() => { + auth = false; + process.env.ACCESS_CODE = undefined; + // Reset environment variables before each test case + vi.restoreAllMocks(); + }); + + it('set multiple access codes', () => { + process.env.ACCESS_CODE = ',code1,code2,code3'; + ({ auth } = checkAuth({ accessCode: 'code1' })); + expect(auth).toBe(true); + ({ auth } = checkAuth({ accessCode: 'code2' })); + expect(auth).toBe(true); + ({ auth } = checkAuth({ accessCode: 'code1,code2' })); + expect(auth).toBe(false); + }); + + it('set individual access code', () => { + process.env.ACCESS_CODE = 'code1'; + ({ auth } = checkAuth({ accessCode: 'code1' })); + expect(auth).toBe(true); + ({ auth } = checkAuth({ accessCode: 'code2' })); + expect(auth).toBe(false); + }); + + it('no access code', () => { + ({ auth } = checkAuth({ accessCode: 'code1' })); + expect(auth).toBe(true); + ({ auth } = checkAuth({})); + expect(auth).toBe(true); + }); + + it('empty access code', () => { + process.env.ACCESS_CODE = ''; + ({ auth } = checkAuth({ accessCode: 'code1' })); + expect(auth).toBe(true); + ({ auth } = checkAuth({})); + expect(auth).toBe(true); + + process.env.ACCESS_CODE = ',,'; + ({ auth } = checkAuth({ accessCode: 'code1' })); + expect(auth).toBe(true); + ({ auth } = checkAuth({})); + expect(auth).toBe(true); + }); +}); diff --git a/src/config/server.ts b/src/config/server.ts index 90b7cf741bdc..d068f182a0b6 100644 --- a/src/config/server.ts +++ b/src/config/server.ts @@ -33,12 +33,12 @@ export const getServerConfig = () => { regions = process.env.OPENAI_FUNCTION_REGIONS.split(','); } - const ACCESS_CODE = process.env.ACCESS_CODE; + const ACCESS_CODES = process.env.ACCESS_CODE?.split(',').filter(Boolean) || []; return { - ACCESS_CODE, + ACCESS_CODES, - SHOW_ACCESS_CODE_CONFIG: !!ACCESS_CODE, + SHOW_ACCESS_CODE_CONFIG: !!ACCESS_CODES.length, OPENAI_API_KEY: process.env.OPENAI_API_KEY, OPENAI_PROXY_URL: process.env.OPENAI_PROXY_URL,