Skip to content

Conversation

MarioJames
Copy link
Contributor

@MarioJames MarioJames commented Jul 22, 2025

💻 变更类型 | Change Type

  • ✨ feat
  • 🐛 fix
  • ♻️ refactor
  • 💄 style
  • 👷 build
  • ⚡️ perf
  • 📝 docs
  • 🔨 chore

🔀 变更说明 | Description of Change

在 LobeChat 中初始化 API-KEY 功能相关表结构及工具
本次提交包含几个方面的内容:

数据访问层
  • Schema 定义 (src/database/schemas/apiKey.ts):使用 Drizzle ORM 定义数据表结构
  • Model 层 (src/database/models/apiKey.ts):封装数据库操作逻辑
  • 迁移文件:添加数据库表结构迁移

数据库约束

  1. 主键约束: id 字段作为自增主键
  2. 唯一约束: key 字段必须全局唯一
  3. 外键约束: user_id 关联 users 表,支持级联删除
  4. 非空约束: name, key, user_id 字段不能为空
  5. 时间戳: 自动维护 created_at 和 updated_at 时间戳
    表关联关系 ER 图如下,User 与 APIKey 关联关系为 1:n
    image
服务层
  • 接口定义 (src/services/apiKey/type.ts):定义统一的服务接口
  • 客户端服务 (src/services/apiKey/client.ts):客户端模式下的服务实现
  • 服务器端服务 (src/services/apiKey/server.ts):服务器模式下的服务实现
  • 自适应选择 (src/services/apiKey/index.ts):根据运行环境自动选择服务实现
API 路由层
  • TRPC 路由 (src/server/routers/lambda/apiKey.ts):提供类型安全的 API 接口,有两个比较特殊的接口
    • create 接口:创建API-Key 时,对生成的字符串进行加密存储
    • findByKey:由于在数据库中使用密文存储,用户看到的是明文,所以在通过明文查找对应的 API-KEY 信息时,在生成查找条件时,需要进行一次明文-密文的转换
  • 输入验证:使用 Zod 进行严格的参数校验
  • 权限控制:集成用户认证中间件
工具函数
  • 密钥生成 (src/utils/apiKey.ts):安全的随机密钥生成算法
  • 格式验证:严格的密钥格式校验
  • 过期检查:密钥有效性验证逻辑

📝 补充信息 | Additional Information

页面路径:账户管理 - API Key 管理

Summary by Sourcery

Implement end-to-end API Key management functionality including database schema, ORM model, service and API routes, feature-flagged UI components, and localization support.

New Features:

  • Add database schema, migration and model for API Key management with encryption, validation, and expiration support
  • Provide TRPC router with procedures to create, list, update, delete, fetch, and validate API keys
  • Implement service layer switching between client and server modes for handling API Key operations
  • Add full UI in the profile section including a new API Key tab, table view, editable cells, date picker, create modal, and key display component
  • Introduce feature flag "api_key_manage" to control visibility of API Key management functionality

Enhancements:

  • Extend rbac_roles schema with a new JSONB metadata column

Documentation:

  • Add i18n translations for all new API Key management UI strings and tab label

- Added new components for API Key management including creation, deletion, and display.
- Introduced a new database schema for storing API Keys.
- Implemented server and client services for API Key operations.
- Integrated API Key management into the profile section with appropriate routing and feature flags.
- Enhanced localization support for API Key related UI elements.

This commit lays the groundwork for managing API Keys within the application, allowing users to create, view, and manage their keys effectively.
Copy link

vercel bot commented Jul 22, 2025

@MarioJames is attempting to deploy a commit to the LobeHub Community Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Contributor

sourcery-ai bot commented Jul 22, 2025

Reviewer's Guide

This PR adds a complete API Key management feature by introducing a new database schema and migration for api_keys, implementing an ApiKeyModel with encrypted CRUD operations, defining service interfaces and client/server implementations, exposing TRPC routes with encryption middleware, providing utility functions for key generation and validation, extending feature flags and translations, and building frontend pages and components for listing, creating, editing, and deleting API keys.

Sequence diagram for API Key creation via TRPC route

sequenceDiagram
  actor User
  participant Frontend as Frontend (React)
  participant TRPC as TRPC API (apiKeyRouter)
  participant Model as ApiKeyModel
  participant GateKeeper as KeyVaultsGateKeeper
  participant DB as Database

  User->>Frontend: Submit create API Key form
  Frontend->>TRPC: createApiKey mutation (name, expiresAt)
  TRPC->>GateKeeper: encrypt(generatedKey)
  TRPC->>Model: create({name, expiresAt}, encryptor)
  Model->>DB: INSERT api_keys (encrypted key, name, ...)
  DB-->>Model: Inserted record
  Model-->>TRPC: Created API Key record
  TRPC-->>Frontend: API Key info (without plaintext key)
  Frontend-->>User: Show API Key created
Loading

Class diagram for API Key model and service structure

classDiagram
  class ApiKeyModel {
    - userId: string
    - db: LobeChatDatabase
    + create(params, encryptor?)
    + delete(id)
    + deleteAll()
    + query(decryptor?)
    + findByKey(key, encryptor?)
    + validateKey(key)
    + update(id, value)
    + findById(id)
    + updateLastUsed(id)
  }

  class IApiKeyService {
    + create(params)
    + delete(id)
    + deleteAll()
    + getById(id)
    + list()
    + update(id, params)
    + validate(key)
  }

  class ClientService {
    + create(params)
    + delete(id)
    + deleteAll()
    + getById(id)
    + list()
    + update(id, params)
    + validate(key)
  }

  class ServerService {
    + create(params)
    + delete(id)
    + deleteAll()
    + getById(id)
    + list()
    + update(id, params)
    + validate(key)
  }

  IApiKeyService <|.. ClientService
  IApiKeyService <|.. ServerService
  ClientService --> ApiKeyModel
Loading

File-Level Changes

Change Details Files
Database schema and migration for API keys
  • Define api_keys table with Drizzle ORM including constraints and timestamps
  • Add SQL migration for api_keys and foreign key to users
  • Export new schema in schemas index and update RBAC table metadata
  • Update migration journal and snapshot files
src/database/schemas/apiKey.ts
src/database/migrations/0029_add_apikey_manage.sql
src/database/schemas/index.ts
src/database/schemas/rbac.ts
src/database/migrations/meta/_journal.json
src/database/migrations/meta/0029_snapshot.json
ApiKeyModel with encrypted CRUD and validation
  • Implement create/delete/deleteAll with optional encryptor
  • Query with optional decryptor and map results
  • Find by key using encryption, validate format, and check expiration
  • Update key attributes and last-used timestamp scoped to user
src/database/models/apiKey.ts
Service layer interfaces and implementations
  • Define IApiKeyService interface for CRUD and validation
  • Implement ClientService using local DB model
  • Implement ServerService using TRPC lambda client
  • Auto-select client or server mode based on environment
src/services/apiKey/type.ts
src/services/apiKey/client.ts
src/services/apiKey/server.ts
src/services/apiKey/index.ts
TRPC API router with encryption context
  • Initialize ApiKeyModel and KeyVaultsGateKeeper via middleware
  • Define create, delete, list, getById, update, validate endpoints with Zod
  • Register apiKey router in main lambda router
src/server/routers/lambda/apiKey.ts
src/server/routers/lambda/index.ts
Utility functions for API key generation and validation
  • Generate a random lb-... key combining timestamp, randomness, and counter
  • Check expiration and validate key format with regex
src/utils/apiKey.ts
Feature flags, translations, and profile navigation
  • Add i18n entries for API Key UI in auth locale
  • Introduce api_key_manage flag in featureFlags schema, default, and mapping
  • Update ProfileTabs enum and conditional menu item in useCategory hook
src/locales/default/auth.ts
src/config/featureFlags/schema.ts
src/store/global/initialState.ts
src/app/[variants]/(main)/profile/hooks/useCategory.tsx
Frontend API Key management UI components and page
  • Build ApiKeyDisplay with show/copy controls
  • Implement EditableCell for inline name/date editing
  • Create ApiKeyModal and ApiKeyDatePicker for forms
  • Assemble profile apikey page with ProTable and CRUD mutations
  • Add guard and metadata on page.tsx based on feature flag
src/app/[variants]/(main)/profile/apikey/index.tsx
src/app/[variants]/(main)/profile/apikey/page.tsx
src/app/[variants]/(main)/profile/apikey/features/EditableCell/index.tsx
src/app/[variants]/(main)/profile/apikey/features/ApiKeyDisplay/index.tsx
src/app/[variants]/(main)/profile/apikey/features/ApiKeyModal/index.tsx
src/app/[variants]/(main)/profile/apikey/features/ApiKeyDatePicker/index.tsx
src/app/[variants]/(main)/profile/apikey/features/index.ts

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@dosubot dosubot bot added the size:XXL This PR changes 1000+ lines, ignoring generated files. label Jul 22, 2025
@lobehubbot
Copy link
Member

👍 @MarioJames

Thank you for raising your pull request and contributing to our Community
Please make sure you have followed our contributing guidelines. We will review it as soon as possible.
If you encounter any problems, please feel free to connect with us.
非常感谢您提出拉取请求并为我们的社区做出贡献,请确保您已经遵循了我们的贡献指南,我们会尽快审查它。
如果您遇到任何问题,请随时与我们联系。

Copy link
Contributor

gru-agent bot commented Jul 22, 2025

There is too much information in the pull request to test.

@dosubot dosubot bot added the 🌠 Feature Request New feature or request | 特性与建议 label Jul 22, 2025
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @MarioJames - I've reviewed your changes - here's some feedback:

  • The regex in validateApiKeyFormat only allows hex chars (0–9, a–f) but generateApiKey produces base36 strings – update the pattern or generator so they match.
  • For better entropy and unpredictability, replace Math.random/performance.now key generation with a crypto-secure RNG (e.g. crypto.getRandomValues).
  • The SQL migration adds an accessed_at column that isn’t in your Drizzle schema – either remove it from the migration or add it to the schema so they stay in sync.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The regex in validateApiKeyFormat only allows hex chars (0–9, a–f) but generateApiKey produces base36 strings – update the pattern or generator so they match.
- For better entropy and unpredictability, replace Math.random/performance.now key generation with a crypto-secure RNG (e.g. crypto.getRandomValues).
- The SQL migration adds an accessed_at column that isn’t in your Drizzle schema – either remove it from the migration or add it to the schema so they stay in sync.

## Individual Comments

### Comment 1
<location> `src/utils/apiKey.ts:58` </location>
<code_context>
+ */
+export function validateApiKeyFormat(key: string): boolean {
+  // Check format: lb-{random}
+  const pattern = /^lb-[\da-f]{16}$/;
+  return pattern.test(key);
+}
</code_context>

<issue_to_address>
API key validation pattern restricts to hexadecimal characters.

The regex only allows a-f and 0-9, but key generation uses all lowercase letters and digits (base36). Update the pattern to match the full character set used.
</issue_to_address>

### Comment 2
<location> `src/app/[variants]/(main)/profile/apikey/index.tsx:135` </location>
<code_context>
+          }}
+          placeholder={t('apikey.display.neverExpires')}
+          type="date"
+          value={apiKey.expiresAt?.toLocaleString() || t('apikey.display.neverExpires')}
+        />
+      ),
</code_context>

<issue_to_address>
Passing a localized string as a value to EditableCell may cause type issues.

Consider passing null instead of a localized string when 'expiresAt' is null to ensure the 'value' prop remains type-consistent for date fields.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
          value={apiKey.expiresAt?.toLocaleString() || t('apikey.display.neverExpires')}
=======
          value={apiKey.expiresAt ? apiKey.expiresAt.toLocaleString() : null}
>>>>>>> REPLACE

</suggested_fix>

### Comment 3
<location> `src/app/[variants]/(main)/profile/apikey/features/ApiKeyDatePicker/index.tsx:26` </location>
<code_context>
+      key={value?.valueOf() || 'EMPTY'}
+      value={value}
+      {...props}
+      minDate={dayjs()}
+      onChange={handleOnChange}
+      placeholder={t('apikey.form.fields.expiresAt.placeholder')}
</code_context>

<issue_to_address>
Setting minDate to current time may prevent selecting today.

Using 'dayjs()' sets minDate to the current time, which can block selection of today's date later in the day. Use 'dayjs().startOf('day')' to allow selecting today.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
      minDate={dayjs()}
=======
      minDate={dayjs().startOf('day')}
>>>>>>> REPLACE

</suggested_fix>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Copy link

codecov bot commented Jul 22, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 85.57%. Comparing base (9d7c601) to head (704c315).
Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##             main    #8535     +/-   ##
=========================================
  Coverage   85.57%   85.57%             
=========================================
  Files         909      910      +1     
  Lines       69019    69039     +20     
  Branches     6395     4763   -1632     
=========================================
+ Hits        59060    59080     +20     
  Misses       9959     9959             
Flag Coverage Δ
app 85.57% <100.00%> (+<0.01%) ⬆️
server 96.26% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link

vercel bot commented Jul 23, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
lobe-chat-database ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 28, 2025 6:48am

MarioJames and others added 3 commits July 24, 2025 20:28
- Added a conditional check to create the "api_keys" table only if it does not already exist.
- Ensured the foreign key constraint for "user_id" references the "users" table remains intact.

This change enhances the migration process by preventing errors during table creation if the table already exists.
MarioJames and others added 2 commits July 26, 2025 22:50
- Introduced a new Client component for managing API keys, including creation, updating, and deletion functionalities.
- Replaced the previous page component with the new Client component in the API key management page.
- Removed obsolete client and server service files related to API key management, streamlining the service layer.

This update enhances the user experience by providing a dedicated interface for API key operations.
@arvinxx arvinxx merged commit fdaa725 into lobehub:main Jul 28, 2025
15 of 16 checks passed
@lobehubbot
Copy link
Member

❤️ Great PR @MarioJames ❤️

The growth of project is inseparable from user feedback and contribution, thanks for your contribution! If you are interesting with the lobehub developer community, please join our discord and then dm @arvinxx or @canisminor1990. They will invite you to our private developer channel. We are talking about the lobe-chat development or sharing ai newsletter around the world.
项目的成长离不开用户反馈和贡献,感谢您的贡献! 如果您对 LobeHub 开发者社区感兴趣,请加入我们的 discord,然后私信 @arvinxx@canisminor1990。他们会邀请您加入我们的私密开发者频道。我们将会讨论关于 Lobe Chat 的开发,分享和讨论全球范围内的 AI 消息。

github-actions bot pushed a commit that referenced this pull request Jul 28, 2025
## [Version&nbsp;1.105.0](v1.104.5...v1.105.0)
<sup>Released on **2025-07-28**</sup>

#### ✨ Features

- **misc**: Implement API Key management functionality.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### What's improved

* **misc**: Implement API Key management functionality, closes [#8535](#8535) ([fdaa725](fdaa725))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
@lobehubbot
Copy link
Member

🎉 This PR is included in version 1.105.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

github-actions bot pushed a commit to jaworldwideorg/OneJA-Bot that referenced this pull request Jul 28, 2025
## [Version&nbsp;1.104.0](v1.103.3...v1.104.0)
<sup>Released on **2025-07-28**</sup>

#### ✨ Features

- **misc**: Implement API Key management functionality, support custom hotkey on desktop.

#### 🐛 Bug Fixes

- **misc**: Fix update hotkey invalid when input mod in desktop, update convertUsage to handle XAI provider and adjust OpenAIStream to pass provider.

#### 💄 Styles

- **misc**: Add Gemini 2.5 Flash-Lite GA model, fix setting window layout size, fix setting window layout when in desktop was disappear, update i18n.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### What's improved

* **misc**: Implement API Key management functionality, closes [lobehub#8535](https://github.com/jaworldwideorg/OneJA-Bot/issues/8535) ([fdaa725](fdaa725))
* **misc**: Support custom hotkey on desktop, closes [lobehub#8559](https://github.com/jaworldwideorg/OneJA-Bot/issues/8559) ([b50f121](b50f121))

#### What's fixed

* **misc**: Fix update hotkey invalid when input mod in desktop, closes [lobehub#8572](https://github.com/jaworldwideorg/OneJA-Bot/issues/8572) ([07f3e6a](07f3e6a))
* **misc**: Update convertUsage to handle XAI provider and adjust OpenAIStream to pass provider, closes [lobehub#8557](https://github.com/jaworldwideorg/OneJA-Bot/issues/8557) ([d1e4a54](d1e4a54))

#### Styles

* **misc**: Add Gemini 2.5 Flash-Lite GA model, closes [lobehub#8539](https://github.com/jaworldwideorg/OneJA-Bot/issues/8539) ([404ac21](404ac21))
* **misc**: Fix setting window layout size, closes [lobehub#8483](https://github.com/jaworldwideorg/OneJA-Bot/issues/8483) ([4902341](4902341))
* **misc**: Fix setting window layout when in desktop was disappear, closes [lobehub#8585](https://github.com/jaworldwideorg/OneJA-Bot/issues/8585) ([74ab822](74ab822))
* **misc**: Update i18n, closes [lobehub#8579](https://github.com/jaworldwideorg/OneJA-Bot/issues/8579) ([2eccbc7](2eccbc7))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
bbbugg pushed a commit to bbbugg/lobe-chat that referenced this pull request Aug 14, 2025
* ✨ feat: Implement API Key management functionality

- Added new components for API Key management including creation, deletion, and display.
- Introduced a new database schema for storing API Keys.
- Implemented server and client services for API Key operations.
- Integrated API Key management into the profile section with appropriate routing and feature flags.
- Enhanced localization support for API Key related UI elements.

This commit lays the groundwork for managing API Keys within the application, allowing users to create, view, and manage their keys effectively.

* fix: server config unit test

* ✨ feat(database): Create api_keys table with conditional existence check

- Added a conditional check to create the "api_keys" table only if it does not already exist.
- Ensured the foreign key constraint for "user_id" references the "users" table remains intact.

This change enhances the migration process by preventing errors during table creation if the table already exists.

* feat: Implement API Key management interface

- Introduced a new Client component for managing API keys, including creation, updating, and deletion functionalities.
- Replaced the previous page component with the new Client component in the API key management page.
- Removed obsolete client and server service files related to API key management, streamlining the service layer.

This update enhances the user experience by providing a dedicated interface for API key operations.
bbbugg pushed a commit to bbbugg/lobe-chat that referenced this pull request Aug 14, 2025
## [Version&nbsp;1.105.0](lobehub/lobe-chat@v1.104.5...v1.105.0)
<sup>Released on **2025-07-28**</sup>

#### ✨ Features

- **misc**: Implement API Key management functionality.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### What's improved

* **misc**: Implement API Key management functionality, closes [lobehub#8535](lobehub#8535) ([9d49c7b](lobehub@9d49c7b))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
cy948 pushed a commit to cy948/lobe-chat that referenced this pull request Aug 23, 2025
* ✨ feat: Implement API Key management functionality

- Added new components for API Key management including creation, deletion, and display.
- Introduced a new database schema for storing API Keys.
- Implemented server and client services for API Key operations.
- Integrated API Key management into the profile section with appropriate routing and feature flags.
- Enhanced localization support for API Key related UI elements.

This commit lays the groundwork for managing API Keys within the application, allowing users to create, view, and manage their keys effectively.

* fix: server config unit test

* ✨ feat(database): Create api_keys table with conditional existence check

- Added a conditional check to create the "api_keys" table only if it does not already exist.
- Ensured the foreign key constraint for "user_id" references the "users" table remains intact.

This change enhances the migration process by preventing errors during table creation if the table already exists.

* feat: Implement API Key management interface

- Introduced a new Client component for managing API keys, including creation, updating, and deletion functionalities.
- Replaced the previous page component with the new Client component in the API key management page.
- Removed obsolete client and server service files related to API key management, streamlining the service layer.

This update enhances the user experience by providing a dedicated interface for API key operations.
cy948 pushed a commit to cy948/lobe-chat that referenced this pull request Aug 23, 2025
## [Version&nbsp;1.105.0](lobehub/lobe-chat@v1.104.5...v1.105.0)
<sup>Released on **2025-07-28**</sup>

#### ✨ Features

- **misc**: Implement API Key management functionality.

<br/>

<details>
<summary><kbd>Improvements and Fixes</kbd></summary>

#### What's improved

* **misc**: Implement API Key management functionality, closes [lobehub#8535](lobehub#8535) ([fdaa725](lobehub@fdaa725))

</details>

<div align="right">

[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)

</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🌠 Feature Request New feature or request | 特性与建议 released size:XXL This PR changes 1000+ lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants