@lobehub/chat 1.36.39 → 1.36.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/changelog/v1.json +9 -0
- package/locales/ar/common.json +7 -3
- package/locales/bg-BG/common.json +7 -3
- package/locales/de-DE/common.json +7 -3
- package/locales/en-US/common.json +7 -3
- package/locales/es-ES/common.json +7 -3
- package/locales/fa-IR/common.json +7 -3
- package/locales/fr-FR/common.json +7 -3
- package/locales/it-IT/common.json +7 -3
- package/locales/ja-JP/common.json +7 -3
- package/locales/ko-KR/common.json +7 -3
- package/locales/nl-NL/common.json +7 -3
- package/locales/pl-PL/common.json +7 -3
- package/locales/pt-BR/common.json +7 -3
- package/locales/ru-RU/common.json +7 -3
- package/locales/tr-TR/common.json +7 -3
- package/locales/vi-VN/common.json +7 -3
- package/locales/zh-CN/common.json +8 -4
- package/locales/zh-TW/common.json +7 -3
- package/package.json +1 -2
- package/src/database/schemas/user.ts +1 -0
- package/src/database/server/models/__tests__/user.test.ts +23 -19
- package/src/database/server/models/session.ts +3 -1
- package/src/database/server/models/user.ts +25 -58
- package/src/locales/default/common.ts +6 -3
- package/src/server/modules/KeyVaultsEncrypt/index.ts +23 -0
- package/src/server/routers/lambda/user.ts +19 -2
- package/src/server/services/user/index.ts +5 -0
package/CHANGELOG.md
CHANGED
@@ -2,6 +2,31 @@
|
|
2
2
|
|
3
3
|
# Changelog
|
4
4
|
|
5
|
+
### [Version 1.36.40](https://github.com/lobehub/lobe-chat/compare/v1.36.39...v1.36.40)
|
6
|
+
|
7
|
+
<sup>Released on **2024-12-20**</sup>
|
8
|
+
|
9
|
+
#### ♻ Code Refactoring
|
10
|
+
|
11
|
+
- **misc**: Seperate user keyVaults encrpyto from user model.
|
12
|
+
|
13
|
+
<br/>
|
14
|
+
|
15
|
+
<details>
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
17
|
+
|
18
|
+
#### Code refactoring
|
19
|
+
|
20
|
+
- **misc**: Seperate user keyVaults encrpyto from user model, closes [#5102](https://github.com/lobehub/lobe-chat/issues/5102) ([09b63cf](https://github.com/lobehub/lobe-chat/commit/09b63cf))
|
21
|
+
|
22
|
+
</details>
|
23
|
+
|
24
|
+
<div align="right">
|
25
|
+
|
26
|
+
[](#readme-top)
|
27
|
+
|
28
|
+
</div>
|
29
|
+
|
5
30
|
### [Version 1.36.39](https://github.com/lobehub/lobe-chat/compare/v1.36.38...v1.36.39)
|
6
31
|
|
7
32
|
<sup>Released on **2024-12-20**</sup>
|
package/changelog/v1.json
CHANGED
package/locales/ar/common.json
CHANGED
@@ -10,7 +10,9 @@
|
|
10
10
|
}
|
11
11
|
},
|
12
12
|
"appLoading": {
|
13
|
+
"appIdle": "جاهز للإطلاق",
|
13
14
|
"appInitializing": "جارٍ تشغيل التطبيق...",
|
15
|
+
"failed": "عذرًا، فشل تحميل التطبيق، يرجى مراجعة التفاصيل للتحقق من المشكلة",
|
14
16
|
"finished": "تم الانتهاء من تهيئة قاعدة البيانات",
|
15
17
|
"goToChat": "جارٍ تحميل صفحة الدردشة...",
|
16
18
|
"initAuth": "جارٍ تهيئة خدمة المصادقة...",
|
@@ -19,7 +21,8 @@
|
|
19
21
|
"loadingDependencies": "جارٍ تهيئة الاعتمادات...",
|
20
22
|
"loadingWasm": "جارٍ تحميل وحدة WASM...",
|
21
23
|
"migrating": "جارٍ تنفيذ ترحيل الجداول...",
|
22
|
-
"ready": "قاعدة البيانات جاهزة"
|
24
|
+
"ready": "قاعدة البيانات جاهزة",
|
25
|
+
"showDetail": "عرض التفاصيل"
|
23
26
|
},
|
24
27
|
"autoGenerate": "توليد تلقائي",
|
25
28
|
"autoGenerateTooltip": "إكمال تلقائي بناءً على الكلمات المقترحة لوصف المساعد",
|
@@ -36,9 +39,10 @@
|
|
36
39
|
"title": "تهيئة قاعدة بيانات PGlite"
|
37
40
|
},
|
38
41
|
"error": {
|
39
|
-
"desc": "نعتذر، حدث خطأ أثناء عملية تهيئة قاعدة بيانات Pglite. يرجى النقر على
|
42
|
+
"desc": "نعتذر، حدث خطأ أثناء عملية تهيئة قاعدة بيانات Pglite. يرجى النقر على الزر لإعادة المحاولة. إذا استمرت المشكلة بعد عدة محاولات، يرجى <1>تقديم مشكلة</1>، وسنساعدك في حلها في أسرع وقت ممكن",
|
43
|
+
"detail": "سبب الخطأ: [{{type}}] {{message}}، التفاصيل كالتالي:",
|
40
44
|
"retry": "إعادة المحاولة",
|
41
|
-
"title": "فشل
|
45
|
+
"title": "فشل تهيئة قاعدة البيانات"
|
42
46
|
},
|
43
47
|
"initing": {
|
44
48
|
"error": "حدث خطأ، يرجى إعادة المحاولة",
|
@@ -10,7 +10,9 @@
|
|
10
10
|
}
|
11
11
|
},
|
12
12
|
"appLoading": {
|
13
|
+
"appIdle": "Подготовка за стартиране",
|
13
14
|
"appInitializing": "Приложението се стартира...",
|
15
|
+
"failed": "Съжаляваме, приложението не успя да се инициализира. Моля, прегледайте детайлите за отстраняване на проблема.",
|
14
16
|
"finished": "Инициализацията на базата данни е завършена",
|
15
17
|
"goToChat": "Зареждане на страницата за разговори...",
|
16
18
|
"initAuth": "Инициализиране на услугата за удостоверяване...",
|
@@ -19,7 +21,8 @@
|
|
19
21
|
"loadingDependencies": "Инициализиране на зависимостите...",
|
20
22
|
"loadingWasm": "Зареждане на WASM модула...",
|
21
23
|
"migrating": "Извършване на миграция на таблиците...",
|
22
|
-
"ready": "Базата данни е готова"
|
24
|
+
"ready": "Базата данни е готова",
|
25
|
+
"showDetail": "Покажи подробности"
|
23
26
|
},
|
24
27
|
"autoGenerate": "Автоматично генериране",
|
25
28
|
"autoGenerateTooltip": "Автоматично генериране на описание на агент въз основа на подкани",
|
@@ -36,9 +39,10 @@
|
|
36
39
|
"title": "Инициализиране на PGlite базата данни"
|
37
40
|
},
|
38
41
|
"error": {
|
39
|
-
"desc": "
|
42
|
+
"desc": "Извинявайте, но възникна проблем по време на инициализацията на Pglite базата данни. Моля, натиснете бутона, за да опиташ отново. Ако проблемът продължава след многократни опити, моля <1>подайте проблем</1>, и ние ще ви помогнем възможно най-скоро.",
|
43
|
+
"detail": "Причина за грешка: [{{type}}] {{message}}. Подробности по-долу:",
|
40
44
|
"retry": "Опитай отново",
|
41
|
-
"title": "
|
45
|
+
"title": "Неуспешна инициализация на базата данни"
|
42
46
|
},
|
43
47
|
"initing": {
|
44
48
|
"error": "Възникна грешка, моля опитайте отново",
|
@@ -10,7 +10,9 @@
|
|
10
10
|
}
|
11
11
|
},
|
12
12
|
"appLoading": {
|
13
|
+
"appIdle": "Bereit zum Starten",
|
13
14
|
"appInitializing": "Anwendung wird gestartet...",
|
15
|
+
"failed": "Es tut uns leid, die Anwendung konnte nicht initialisiert werden. Bitte sehen Sie sich die Details zur Fehlerbehebung an.",
|
14
16
|
"finished": "Datenbankinitialisierung abgeschlossen",
|
15
17
|
"goToChat": "Lade die Chat-Seite...",
|
16
18
|
"initAuth": "Initialisiere den Authentifizierungsdienst...",
|
@@ -19,7 +21,8 @@
|
|
19
21
|
"loadingDependencies": "Abhängigkeiten werden initialisiert...",
|
20
22
|
"loadingWasm": "WASM-Module werden geladen...",
|
21
23
|
"migrating": "Datenbankmigration wird durchgeführt...",
|
22
|
-
"ready": "Datenbank ist bereit"
|
24
|
+
"ready": "Datenbank ist bereit",
|
25
|
+
"showDetail": "Details anzeigen"
|
23
26
|
},
|
24
27
|
"autoGenerate": "Automatisch generieren",
|
25
28
|
"autoGenerateTooltip": "Assistentenbeschreibung automatisch auf Basis von Vorschlägen vervollständigen",
|
@@ -36,9 +39,10 @@
|
|
36
39
|
"title": "Initialisiere PGlite-Datenbank"
|
37
40
|
},
|
38
41
|
"error": {
|
39
|
-
"desc": "Es tut uns leid, während
|
42
|
+
"desc": "Es tut uns leid, während des Initialisierungsprozesses der Pglite-Datenbank ist ein Fehler aufgetreten. Bitte klicken Sie auf die Schaltfläche, um es erneut zu versuchen. Wenn der Fehler nach mehreren Versuchen weiterhin auftritt, <1>reichen Sie bitte ein Problem ein</1>, und wir werden Ihnen umgehend bei der Untersuchung helfen.",
|
43
|
+
"detail": "Fehlerursache: [{{type}}] {{message}}. Einzelheiten sind wie folgt:",
|
40
44
|
"retry": "Erneut versuchen",
|
41
|
-
"title": "
|
45
|
+
"title": "Datenbankinitialisierung fehlgeschlagen"
|
42
46
|
},
|
43
47
|
"initing": {
|
44
48
|
"error": "Ein Fehler ist aufgetreten, bitte versuchen Sie es erneut",
|
@@ -10,7 +10,9 @@
|
|
10
10
|
}
|
11
11
|
},
|
12
12
|
"appLoading": {
|
13
|
+
"appIdle": "Ready to start",
|
13
14
|
"appInitializing": "Application is starting...",
|
15
|
+
"failed": "Sorry, the application initialization failed. Please check the details for troubleshooting.",
|
14
16
|
"finished": "Database initialization completed",
|
15
17
|
"goToChat": "Loading chat page...",
|
16
18
|
"initAuth": "Initializing authentication service...",
|
@@ -19,7 +21,8 @@
|
|
19
21
|
"loadingDependencies": "Initializing dependencies...",
|
20
22
|
"loadingWasm": "Loading WASM module...",
|
21
23
|
"migrating": "Performing database migration...",
|
22
|
-
"ready": "Database is ready"
|
24
|
+
"ready": "Database is ready",
|
25
|
+
"showDetail": "View details"
|
23
26
|
},
|
24
27
|
"autoGenerate": "Auto Generate",
|
25
28
|
"autoGenerateTooltip": "Auto-generate assistant description based on prompts",
|
@@ -36,9 +39,10 @@
|
|
36
39
|
"title": "Initializing PGlite Database"
|
37
40
|
},
|
38
41
|
"error": {
|
39
|
-
"desc": "We apologize, an
|
42
|
+
"desc": "We apologize, an error occurred during the Pglite database initialization process. Please click the button to retry. If the error persists after multiple attempts, please <1>submit an issue</1>, and we will assist you as soon as possible.",
|
43
|
+
"detail": "Error reason: [{{type}}] {{message}}. Details are as follows:",
|
40
44
|
"retry": "Retry",
|
41
|
-
"title": "Database
|
45
|
+
"title": "Database Initialization Failed"
|
42
46
|
},
|
43
47
|
"initing": {
|
44
48
|
"error": "An error occurred, please try again",
|
@@ -10,7 +10,9 @@
|
|
10
10
|
}
|
11
11
|
},
|
12
12
|
"appLoading": {
|
13
|
+
"appIdle": "Listo para iniciar",
|
13
14
|
"appInitializing": "Iniciando la aplicación...",
|
15
|
+
"failed": "Lo siento, la inicialización de la aplicación ha fallado. Por favor, consulta los detalles para investigar.",
|
14
16
|
"finished": "Inicialización de la base de datos completada",
|
15
17
|
"goToChat": "Cargando la página de chat...",
|
16
18
|
"initAuth": "Inicializando el servicio de autenticación...",
|
@@ -19,7 +21,8 @@
|
|
19
21
|
"loadingDependencies": "Inicializando dependencias...",
|
20
22
|
"loadingWasm": "Cargando módulo WASM...",
|
21
23
|
"migrating": "Ejecutando migración de tablas de datos...",
|
22
|
-
"ready": "Base de datos lista"
|
24
|
+
"ready": "Base de datos lista",
|
25
|
+
"showDetail": "Ver detalles"
|
23
26
|
},
|
24
27
|
"autoGenerate": "Generación automática",
|
25
28
|
"autoGenerateTooltip": "Completar automáticamente la descripción del asistente basándose en las sugerencias",
|
@@ -36,9 +39,10 @@
|
|
36
39
|
"title": "Inicializando la base de datos PGlite"
|
37
40
|
},
|
38
41
|
"error": {
|
39
|
-
"desc": "Lo sentimos, ha ocurrido
|
42
|
+
"desc": "Lo sentimos, ha ocurrido una excepción en el proceso de inicialización de la base de datos Pglite. Por favor, haga clic en el botón para intentar de nuevo. Si después de varios intentos sigue ocurriendo el mismo error, por favor <1>envíe un problema</1>, y lo resolveremos lo antes posible.",
|
43
|
+
"detail": "Razón del error: [{{type}}] {{message}}. Detalles a continuación:",
|
40
44
|
"retry": "Reintentar",
|
41
|
-
"title": "
|
45
|
+
"title": "Falló la inicialización de la base de datos"
|
42
46
|
},
|
43
47
|
"initing": {
|
44
48
|
"error": "Ha ocurrido un error, por favor reintente",
|
@@ -10,7 +10,9 @@
|
|
10
10
|
}
|
11
11
|
},
|
12
12
|
"appLoading": {
|
13
|
+
"appIdle": "در حال آمادهسازی برای راهاندازی",
|
13
14
|
"appInitializing": "در حال راهاندازی برنامه...",
|
15
|
+
"failed": "متأسفیم، راهاندازی برنامه با شکست مواجه شد، لطفاً برای بررسی جزئیات به آن مراجعه کنید",
|
14
16
|
"finished": "راهاندازی پایگاه داده کامل شد",
|
15
17
|
"goToChat": "در حال بارگذاری صفحه گفتگو...",
|
16
18
|
"initAuth": "در حال راهاندازی سرویس احراز هویت...",
|
@@ -19,7 +21,8 @@
|
|
19
21
|
"loadingDependencies": "در حال بارگذاری وابستگیها...",
|
20
22
|
"loadingWasm": "در حال بارگذاری ماژول WASM...",
|
21
23
|
"migrating": "در حال اجرای مهاجرت جداول داده...",
|
22
|
-
"ready": "پایگاه داده آماده است"
|
24
|
+
"ready": "پایگاه داده آماده است",
|
25
|
+
"showDetail": "مشاهده جزئیات"
|
23
26
|
},
|
24
27
|
"autoGenerate": "تکمیل خودکار",
|
25
28
|
"autoGenerateTooltip": "تکمیل خودکار توضیحات دستیار بر اساس کلمات راهنما",
|
@@ -36,9 +39,10 @@
|
|
36
39
|
"title": "راهاندازی پایگاه داده PGlite"
|
37
40
|
},
|
38
41
|
"error": {
|
39
|
-
"desc": "متأسفیم، در
|
42
|
+
"desc": "متأسفیم، در روند初始化 پایگاه داده Pglite خطایی رخ داده است. لطفاً دکمه را برای تلاش مجدد فشار دهید. اگر پس از چندین بار تلاش، هنوز خطا تکرار شد، لطفاً <1>مسئله را گزارش کنید</1>، ما در اولین فرصت به شما کمک خواهیم کرد.",
|
43
|
+
"detail": "علت خطا: [{{type}}] {{message}}، جزئیات به شرح زیر است:",
|
40
44
|
"retry": "تکرار",
|
41
|
-
"title": "
|
45
|
+
"title": "خطای در初始化 پایگاه داده"
|
42
46
|
},
|
43
47
|
"initing": {
|
44
48
|
"error": "خطایی رخ داده است، لطفاً دوباره تلاش کنید",
|
@@ -10,7 +10,9 @@
|
|
10
10
|
}
|
11
11
|
},
|
12
12
|
"appLoading": {
|
13
|
+
"appIdle": "Préparation du démarrage",
|
13
14
|
"appInitializing": "L'application se charge...",
|
15
|
+
"failed": "Désolé, l'initialisation de l'application a échoué. Veuillez consulter les détails pour résoudre le problème.",
|
14
16
|
"finished": "Initialisation de la base de données terminée",
|
15
17
|
"goToChat": "Chargement de la page de chat...",
|
16
18
|
"initAuth": "Initialisation du service d'authentification...",
|
@@ -19,7 +21,8 @@
|
|
19
21
|
"loadingDependencies": "Chargement des dépendances...",
|
20
22
|
"loadingWasm": "Chargement du module WASM...",
|
21
23
|
"migrating": "Exécution de la migration des tables de données...",
|
22
|
-
"ready": "La base de données est prête"
|
24
|
+
"ready": "La base de données est prête",
|
25
|
+
"showDetail": "Voir les détails"
|
23
26
|
},
|
24
27
|
"autoGenerate": "Générer automatiquement",
|
25
28
|
"autoGenerateTooltip": "Générer automatiquement la description de l'agent basée sur les suggestions",
|
@@ -36,9 +39,10 @@
|
|
36
39
|
"title": "Initialisation de la base de données PGlite"
|
37
40
|
},
|
38
41
|
"error": {
|
39
|
-
"desc": "Nous sommes désolés, une erreur
|
42
|
+
"desc": "Nous sommes désolés, une erreur est survenue lors de l'initialisation de la base de données Pglite. Veuillez cliquer sur le bouton pour réessayer. Si l'erreur persiste après plusieurs tentatives, veuillez <1>soumettre un problème</1>, nous vous aiderons à le résoudre dans les meilleurs délais.",
|
43
|
+
"detail": "Raison de l'erreur : [[{{type}}] {{message}}. Détails ci-dessous :",
|
40
44
|
"retry": "Réessayer",
|
41
|
-
"title": "Échec de
|
45
|
+
"title": "Échec de l'initialisation de la base de données"
|
42
46
|
},
|
43
47
|
"initing": {
|
44
48
|
"error": "Une erreur s'est produite, veuillez réessayer",
|
@@ -10,7 +10,9 @@
|
|
10
10
|
}
|
11
11
|
},
|
12
12
|
"appLoading": {
|
13
|
+
"appIdle": "Pronto per avviare",
|
13
14
|
"appInitializing": "Avvio dell'app in corso...",
|
15
|
+
"failed": "Ci dispiace, l'inizializzazione dell'applicazione è fallita. Si prega di controllare i dettagli per la risoluzione.",
|
14
16
|
"finished": "Inizializzazione del database completata",
|
15
17
|
"goToChat": "Caricamento della pagina di chat in corso...",
|
16
18
|
"initAuth": "Inizializzazione del servizio di autenticazione...",
|
@@ -19,7 +21,8 @@
|
|
19
21
|
"loadingDependencies": "Inizializzazione delle dipendenze...",
|
20
22
|
"loadingWasm": "Caricamento del modulo WASM...",
|
21
23
|
"migrating": "Esecuzione della migrazione delle tabelle dati...",
|
22
|
-
"ready": "Database pronto"
|
24
|
+
"ready": "Database pronto",
|
25
|
+
"showDetail": "Mostra dettagli"
|
23
26
|
},
|
24
27
|
"autoGenerate": "Generazione automatica",
|
25
28
|
"autoGenerateTooltip": "Completamento automatico basato su suggerimenti",
|
@@ -36,9 +39,10 @@
|
|
36
39
|
"title": "Inizializzazione del database PGlite"
|
37
40
|
},
|
38
41
|
"error": {
|
39
|
-
"desc": "Ci scusiamo, si è verificato un errore durante
|
42
|
+
"desc": "Ci scusiamo, si è verificato un errore durante il processo di inizializzazione del database Pglite. Clicca sul pulsante per riprovare. Se l'errore persiste dopo vari tentativi, per favore <1>invia un problema</1> e noi ci occuperemo di risolverlo il prima possibile",
|
43
|
+
"detail": "Motivo dell'errore: [{{type}}] {{message}}. Dettagli come segue:",
|
40
44
|
"retry": "Riprova",
|
41
|
-
"title": "
|
45
|
+
"title": "Inizializzazione del database fallita"
|
42
46
|
},
|
43
47
|
"initing": {
|
44
48
|
"error": "Si è verificato un errore, si prega di riprovare",
|
@@ -10,7 +10,9 @@
|
|
10
10
|
}
|
11
11
|
},
|
12
12
|
"appLoading": {
|
13
|
+
"appIdle": "起動準備中",
|
13
14
|
"appInitializing": "アプリケーションを起動しています...",
|
15
|
+
"failed": "申し訳ありませんが、アプリの初期化に失敗しました。詳細を確認して問題を調査してください。",
|
14
16
|
"finished": "データベースの初期化が完了しました",
|
15
17
|
"goToChat": "チャットページを読み込んでいます...",
|
16
18
|
"initAuth": "認証サービスを初期化しています...",
|
@@ -19,7 +21,8 @@
|
|
19
21
|
"loadingDependencies": "依存関係を初期化しています...",
|
20
22
|
"loadingWasm": "WASM モジュールを読み込んでいます...",
|
21
23
|
"migrating": "データテーブルの移行を実行しています...",
|
22
|
-
"ready": "データベースは準備完了です"
|
24
|
+
"ready": "データベースは準備完了です",
|
25
|
+
"showDetail": "詳細を見る"
|
23
26
|
},
|
24
27
|
"autoGenerate": "自動生成",
|
25
28
|
"autoGenerateTooltip": "ヒントに基づいてエージェントの説明を自動生成します",
|
@@ -36,9 +39,10 @@
|
|
36
39
|
"title": "PGlite データベースの初期化"
|
37
40
|
},
|
38
41
|
"error": {
|
39
|
-
"desc": "申し訳ありませんが、Pglite
|
42
|
+
"desc": "申し訳ありませんが、Pglite データベースの初期化中にエラーが発生しました。ボタンをクリックして再試行してください。それでも何度もエラーが発生する場合は、<1>問題を報告</1>してください。すぐに調査いたします。",
|
43
|
+
"detail": "エラーの原因:[{{type}}] {{message}}、詳細は以下の通りです:",
|
40
44
|
"retry": "再試行",
|
41
|
-
"title": "
|
45
|
+
"title": "データベースの初期化に失敗しました"
|
42
46
|
},
|
43
47
|
"initing": {
|
44
48
|
"error": "エラーが発生しました。再試行してください。",
|
@@ -10,7 +10,9 @@
|
|
10
10
|
}
|
11
11
|
},
|
12
12
|
"appLoading": {
|
13
|
+
"appIdle": "시작 준비 중",
|
13
14
|
"appInitializing": "앱을 초기화하는 중...",
|
15
|
+
"failed": "죄송합니다. 애플리케이션 초기화에 실패했습니다. 상세 정보를 확인하여 문제를 해결해 주세요.",
|
14
16
|
"finished": "데이터베이스 초기화 완료",
|
15
17
|
"goToChat": "대화 페이지 로딩 중...",
|
16
18
|
"initAuth": "인증 서비스 초기화 중...",
|
@@ -19,7 +21,8 @@
|
|
19
21
|
"loadingDependencies": "의존성 초기화 중...",
|
20
22
|
"loadingWasm": "WASM 모듈 로드 중...",
|
21
23
|
"migrating": "데이터베이스 테이블 마이그레이션 중...",
|
22
|
-
"ready": "데이터베이스 준비 완료"
|
24
|
+
"ready": "데이터베이스 준비 완료",
|
25
|
+
"showDetail": "자세히 보기"
|
23
26
|
},
|
24
27
|
"autoGenerate": "자동 생성",
|
25
28
|
"autoGenerateTooltip": "힌트 단어를 기반으로 에이전트 설명을 자동으로 완성합니다",
|
@@ -36,9 +39,10 @@
|
|
36
39
|
"title": "PGlite 데이터베이스 초기화"
|
37
40
|
},
|
38
41
|
"error": {
|
39
|
-
"desc": "죄송합니다.
|
42
|
+
"desc": "죄송합니다. Pglite 데이터베이스 초기화 과정에서 예외가 발생했습니다. 버튼을 클릭하여 다시 시도해 주십시오. 여러 번 시도한 후에도 여전히 문제가 발생하면 <1>문제를 제출</1>해 주십시오. 저희가 즉시 문제를 해결해 드리겠습니다.",
|
43
|
+
"detail": "오류 원인: [[[{{type}}]]] {{message}},상세 내용은 다음과 같습니다:",
|
40
44
|
"retry": "재시도",
|
41
|
-
"title": "데이터베이스
|
45
|
+
"title": "데이터베이스 초기화 실패"
|
42
46
|
},
|
43
47
|
"initing": {
|
44
48
|
"error": "오류가 발생했습니다. 재시도해 주세요.",
|
@@ -10,7 +10,9 @@
|
|
10
10
|
}
|
11
11
|
},
|
12
12
|
"appLoading": {
|
13
|
+
"appIdle": "Klaar om te starten",
|
13
14
|
"appInitializing": "Applicatie wordt gestart...",
|
15
|
+
"failed": "Het spijt ons, de applicatie-initialisatie is mislukt. Bekijk de details voor hulp bij het oplossen.",
|
14
16
|
"finished": "Database-initialisatie voltooid",
|
15
17
|
"goToChat": "De chatpagina wordt geladen...",
|
16
18
|
"initAuth": "Authenticatiedienst wordt geïnitialiseerd...",
|
@@ -19,7 +21,8 @@
|
|
19
21
|
"loadingDependencies": "Afhankelijkheden worden geïnitialiseerd...",
|
20
22
|
"loadingWasm": "WASM-modules worden geladen...",
|
21
23
|
"migrating": "Gegevens migreren...",
|
22
|
-
"ready": "Database is gereed"
|
24
|
+
"ready": "Database is gereed",
|
25
|
+
"showDetail": "Bekijk details"
|
23
26
|
},
|
24
27
|
"autoGenerate": "Automatisch genereren",
|
25
28
|
"autoGenerateTooltip": "Automatisch assistentbeschrijving genereren op basis van suggesties",
|
@@ -36,9 +39,10 @@
|
|
36
39
|
"title": "Initialiseer de PGlite-database"
|
37
40
|
},
|
38
41
|
"error": {
|
39
|
-
"desc": "
|
42
|
+
"desc": "Onze excuses, er is een fout opgetreden tijdens het initialisatieproces van de Pglite-database. Klik op de knop om het opnieuw te proberen. Als het probleem zich blijft voordoen na meerdere pogingen, gelieve <1>een probleem te melden</1> en we zullen u zo snel mogelijk helpen.",
|
43
|
+
"detail": "Fout reden: [[{{type}}] {{message}}. Details zijn als volgt:",
|
40
44
|
"retry": "Opnieuw proberen",
|
41
|
-
"title": "
|
45
|
+
"title": "Fout bij database-initialisatie"
|
42
46
|
},
|
43
47
|
"initing": {
|
44
48
|
"error": "Er is een fout opgetreden, probeer het opnieuw",
|
@@ -10,7 +10,9 @@
|
|
10
10
|
}
|
11
11
|
},
|
12
12
|
"appLoading": {
|
13
|
+
"appIdle": "Zarządzanie uruchomieniem",
|
13
14
|
"appInitializing": "Aplikacja się uruchamia...",
|
15
|
+
"failed": "Przykro nam, inicjalizacja aplikacji nie powiodła się, proszę sprawdzić szczegóły, aby znaleźć przyczynę.",
|
14
16
|
"finished": "Inicjalizacja bazy danych zakończona",
|
15
17
|
"goToChat": "Ładowanie strony czatu...",
|
16
18
|
"initAuth": "Inicjalizacja usługi autoryzacji...",
|
@@ -19,7 +21,8 @@
|
|
19
21
|
"loadingDependencies": "Inicjalizacja zależności...",
|
20
22
|
"loadingWasm": "Ładowanie modułu WASM...",
|
21
23
|
"migrating": "Wykonywanie migracji tabeli danych...",
|
22
|
-
"ready": "Baza danych jest gotowa"
|
24
|
+
"ready": "Baza danych jest gotowa",
|
25
|
+
"showDetail": "Zobacz szczegóły"
|
23
26
|
},
|
24
27
|
"autoGenerate": "Automatyczne generowanie",
|
25
28
|
"autoGenerateTooltip": "Automatyczne uzupełnianie opisu asystenta na podstawie sugestii",
|
@@ -36,9 +39,10 @@
|
|
36
39
|
"title": "Inicjalizacja bazy danych PGlite"
|
37
40
|
},
|
38
41
|
"error": {
|
39
|
-
"desc": "
|
42
|
+
"desc": "Przykro nam, wystąpił błąd podczas inicjalizacji bazy danych Pglite. Proszę kliknąć przycisk, aby spróbować ponownie. Jeśli błąd powtarza się po wielokrotnych próbach, proszę <1>zgłosić problem</1>, a my jak najszybciej pomożemy w rozwiązaniu.",
|
43
|
+
"detail": "Powód błędu: [{{type}}] {{message}}. Szczegóły poniżej:",
|
40
44
|
"retry": "Spróbuj ponownie",
|
41
|
-
"title": "
|
45
|
+
"title": "Błąd inicjalizacji bazy danych"
|
42
46
|
},
|
43
47
|
"initing": {
|
44
48
|
"error": "Wystąpił błąd, proszę spróbować ponownie",
|
@@ -10,7 +10,9 @@
|
|
10
10
|
}
|
11
11
|
},
|
12
12
|
"appLoading": {
|
13
|
+
"appIdle": "Preparando para iniciar",
|
13
14
|
"appInitializing": "Iniciando o aplicativo...",
|
15
|
+
"failed": "Desculpe, a inicialização do aplicativo falhou. Por favor, verifique os detalhes para solucionar o problema.",
|
14
16
|
"finished": "Inicialização do banco de dados concluída",
|
15
17
|
"goToChat": "Carregando página de conversa...",
|
16
18
|
"initAuth": "Inicializando serviço de autenticação...",
|
@@ -19,7 +21,8 @@
|
|
19
21
|
"loadingDependencies": "Inicializando dependências...",
|
20
22
|
"loadingWasm": "Carregando módulo WASM...",
|
21
23
|
"migrating": "Executando migração de tabelas de dados...",
|
22
|
-
"ready": "Banco de dados pronto"
|
24
|
+
"ready": "Banco de dados pronto",
|
25
|
+
"showDetail": "Ver detalhes"
|
23
26
|
},
|
24
27
|
"autoGenerate": "Auto completar",
|
25
28
|
"autoGenerateTooltip": "Auto completar descrição do assistente com base em sugestões",
|
@@ -36,9 +39,10 @@
|
|
36
39
|
"title": "Inicializando o banco de dados PGlite"
|
37
40
|
},
|
38
41
|
"error": {
|
39
|
-
"desc": "
|
42
|
+
"desc": "Lamentamos, ocorreu uma exceção durante o processo de inicialização do banco de dados Pglite. Por favor, clique no botão para tentar novamente. Se o erro persistir após várias tentativas, por favor <1>envie um problema</1> e nós iremos ajudá-lo a resolver o quanto antes",
|
43
|
+
"detail": "Causa do erro: [{{type}}] {{message}}. Detalhes abaixo:",
|
40
44
|
"retry": "Tentar Novamente",
|
41
|
-
"title": "Falha na
|
45
|
+
"title": "Falha na inicialização do banco de dados"
|
42
46
|
},
|
43
47
|
"initing": {
|
44
48
|
"error": "Ocorreu um erro, por favor tente novamente",
|
@@ -10,7 +10,9 @@
|
|
10
10
|
}
|
11
11
|
},
|
12
12
|
"appLoading": {
|
13
|
+
"appIdle": "Подготовка к запуску",
|
13
14
|
"appInitializing": "Инициализация приложения...",
|
15
|
+
"failed": "К сожалению, инициализация приложения не удалась, пожалуйста, посмотрите подробности для устранения проблемы",
|
14
16
|
"finished": "Инициализация базы данных завершена",
|
15
17
|
"goToChat": "Загрузка страницы чата...",
|
16
18
|
"initAuth": "Инициализация службы аутентификации...",
|
@@ -19,7 +21,8 @@
|
|
19
21
|
"loadingDependencies": "Инициализация зависимостей...",
|
20
22
|
"loadingWasm": "Загрузка модуля WASM...",
|
21
23
|
"migrating": "Выполнение миграции таблиц данных...",
|
22
|
-
"ready": "База данных готова"
|
24
|
+
"ready": "База данных готова",
|
25
|
+
"showDetail": "Посмотреть детали"
|
23
26
|
},
|
24
27
|
"autoGenerate": "Автозаполнение",
|
25
28
|
"autoGenerateTooltip": "Автоматическое дополнение описания агента на основе подсказок",
|
@@ -36,9 +39,10 @@
|
|
36
39
|
"title": "Инициализация базы данных PGlite"
|
37
40
|
},
|
38
41
|
"error": {
|
39
|
-
"desc": "К сожалению, произошла ошибка
|
42
|
+
"desc": "К сожалению, произошла ошибка при инициализации базы данных Pglite. Пожалуйста, нажмите кнопку, чтобы попробовать снова. Если после нескольких попыток ошибка сохраняется, пожалуйста, <1>отправьте запрос</1>, и мы постараемся помочь вам в кратчайшие сроки.",
|
43
|
+
"detail": "Причина ошибки: [{{type}}] {{message}}. Подробности ниже:",
|
40
44
|
"retry": "Повторить",
|
41
|
-
"title": "
|
45
|
+
"title": "Не удалось инициализировать базу данных"
|
42
46
|
},
|
43
47
|
"initing": {
|
44
48
|
"error": "Произошла ошибка, пожалуйста, повторите попытку",
|
@@ -10,7 +10,9 @@
|
|
10
10
|
}
|
11
11
|
},
|
12
12
|
"appLoading": {
|
13
|
+
"appIdle": "Başlatılıyor",
|
13
14
|
"appInitializing": "Uygulama başlatılıyor...",
|
15
|
+
"failed": "Üzgünüz, uygulama başlatılırken bir hata oluştu, lütfen ayrıntıları kontrol edin ve sorunu giderin.",
|
14
16
|
"finished": "Veritabanı başlatma tamamlandı",
|
15
17
|
"goToChat": "Sohbet sayfası yükleniyor...",
|
16
18
|
"initAuth": "Kimlik doğrulama servisi başlatılıyor...",
|
@@ -19,7 +21,8 @@
|
|
19
21
|
"loadingDependencies": "Bağımlılıklar yükleniyor...",
|
20
22
|
"loadingWasm": "WASM modülü yükleniyor...",
|
21
23
|
"migrating": "Veri tablosu taşınıyor...",
|
22
|
-
"ready": "Veritabanı hazır"
|
24
|
+
"ready": "Veritabanı hazır",
|
25
|
+
"showDetail": "Detayları Görüntüle"
|
23
26
|
},
|
24
27
|
"autoGenerate": "Otomatik Oluştur",
|
25
28
|
"autoGenerateTooltip": "Auto-generate agent description based on prompts",
|
@@ -36,9 +39,10 @@
|
|
36
39
|
"title": "PGlite veritabanı başlatılıyor"
|
37
40
|
},
|
38
41
|
"error": {
|
39
|
-
"desc": "Üzgünüz,
|
42
|
+
"desc": "Üzgünüz, Pglite veritabanı başlatma sırasında bir hata oluştu. Lütfen düğmeye tıklayarak tekrar deneyin. Eğer birden fazla denemeden sonra hala hata alıyorsanız, lütfen <1>bir sorun bildirin</1>, size en kısa sürede yardımcı olacağız.",
|
43
|
+
"detail": "Hata Nedeni: [{{type}}] {{message}}. Ayrıntılar aşağıda:",
|
40
44
|
"retry": "Tekrar Dene",
|
41
|
-
"title": "Veritabanı
|
45
|
+
"title": "Veritabanı başlatma hatası"
|
42
46
|
},
|
43
47
|
"initing": {
|
44
48
|
"error": "Hata oluştu, lütfen tekrar deneyin",
|
@@ -10,7 +10,9 @@
|
|
10
10
|
}
|
11
11
|
},
|
12
12
|
"appLoading": {
|
13
|
+
"appIdle": "Sẵn sàng khởi động",
|
13
14
|
"appInitializing": "Đang khởi động ứng dụng...",
|
15
|
+
"failed": "Rất tiếc, ứng dụng không khởi tạo được, vui lòng xem chi tiết để kiểm tra.",
|
14
16
|
"finished": "Khởi tạo cơ sở dữ liệu hoàn tất",
|
15
17
|
"goToChat": "Đang tải trang trò chuyện...",
|
16
18
|
"initAuth": "Đang khởi tạo dịch vụ xác thực...",
|
@@ -19,7 +21,8 @@
|
|
19
21
|
"loadingDependencies": "Đang khởi tạo phụ thuộc...",
|
20
22
|
"loadingWasm": "Đang tải mô-đun WASM...",
|
21
23
|
"migrating": "Đang thực hiện di chuyển bảng dữ liệu...",
|
22
|
-
"ready": "Cơ sở dữ liệu đã sẵn sàng"
|
24
|
+
"ready": "Cơ sở dữ liệu đã sẵn sàng",
|
25
|
+
"showDetail": "Xem chi tiết"
|
23
26
|
},
|
24
27
|
"autoGenerate": "Tự động tạo",
|
25
28
|
"autoGenerateTooltip": "Tự động hoàn thành mô tả trợ lý dựa trên từ gợi ý",
|
@@ -36,9 +39,10 @@
|
|
36
39
|
"title": "Khởi tạo cơ sở dữ liệu PGlite"
|
37
40
|
},
|
38
41
|
"error": {
|
39
|
-
"desc": "
|
42
|
+
"desc": "Xin lỗi, đã xảy ra sự cố trong quá trình khởi tạo cơ sở dữ liệu Pglite. Vui lòng nhấn nút để thử lại. Nếu vẫn gặp lỗi sau nhiều lần thử, vui lòng <1>gửi vấn đề</1>, chúng tôi sẽ hỗ trợ bạn kiểm tra ngay lập tức.",
|
43
|
+
"detail": "Lý do lỗi: [{{type}}] {{message}},Chi tiết như sau:",
|
40
44
|
"retry": "Thử lại",
|
41
|
-
"title": "
|
45
|
+
"title": "Khởi tạo cơ sở dữ liệu thất bại"
|
42
46
|
},
|
43
47
|
"initing": {
|
44
48
|
"error": "Đã xảy ra lỗi, vui lòng thử lại",
|
@@ -10,7 +10,9 @@
|
|
10
10
|
}
|
11
11
|
},
|
12
12
|
"appLoading": {
|
13
|
+
"appIdle": "准备启动",
|
13
14
|
"appInitializing": "应用启动中...",
|
15
|
+
"failed": "很抱歉,应用初始化失败,请查看详情进行排查",
|
14
16
|
"finished": "数据库初始化完成",
|
15
17
|
"goToChat": "对话页面加载中...",
|
16
18
|
"initAuth": "鉴权服务初始化...",
|
@@ -19,7 +21,8 @@
|
|
19
21
|
"loadingDependencies": "初始化依赖...",
|
20
22
|
"loadingWasm": "加载 WASM 模块...",
|
21
23
|
"migrating": "执行数据表迁移...",
|
22
|
-
"ready": "数据库已就绪"
|
24
|
+
"ready": "数据库已就绪",
|
25
|
+
"showDetail": "查看详情"
|
23
26
|
},
|
24
27
|
"autoGenerate": "自动补全",
|
25
28
|
"autoGenerateTooltip": "基于提示词自动补全助手描述",
|
@@ -36,12 +39,13 @@
|
|
36
39
|
"title": "初始化 PGlite 数据库"
|
37
40
|
},
|
38
41
|
"error": {
|
39
|
-
"desc": "非常抱歉,Pglite
|
42
|
+
"desc": "非常抱歉,Pglite 数据库初始化过程发生异常。请点击按钮重试。如多次重试后仍重复出错,请 <1>提交问题</1> ,我们将会第一时间帮你排查",
|
43
|
+
"detail": "错误原因:[{{type}}] {{message}},明细如下:",
|
40
44
|
"retry": "重试",
|
41
|
-
"title": "
|
45
|
+
"title": "数据库初始化失败"
|
42
46
|
},
|
43
47
|
"initing": {
|
44
|
-
"error": "
|
48
|
+
"error": "数据库初始化出错,点击查看详情",
|
45
49
|
"idle": "等待初始化...",
|
46
50
|
"initializing": "正在初始化...",
|
47
51
|
"loadingDependencies": "加载依赖中...",
|
@@ -10,7 +10,9 @@
|
|
10
10
|
}
|
11
11
|
},
|
12
12
|
"appLoading": {
|
13
|
+
"appIdle": "準備啟動",
|
13
14
|
"appInitializing": "應用啟動中...",
|
15
|
+
"failed": "很抱歉,應用初始化失敗,請查看詳情進行排查",
|
14
16
|
"finished": "資料庫初始化完成",
|
15
17
|
"goToChat": "對話頁面加載中...",
|
16
18
|
"initAuth": "鑑權服務初始化...",
|
@@ -19,7 +21,8 @@
|
|
19
21
|
"loadingDependencies": "初始化依賴...",
|
20
22
|
"loadingWasm": "加載 WASM 模組...",
|
21
23
|
"migrating": "執行資料表遷移...",
|
22
|
-
"ready": "資料庫已就緒"
|
24
|
+
"ready": "資料庫已就緒",
|
25
|
+
"showDetail": "查看詳情"
|
23
26
|
},
|
24
27
|
"autoGenerate": "自動生成",
|
25
28
|
"autoGenerateTooltip": "基於提示詞自動生成助手描述",
|
@@ -36,9 +39,10 @@
|
|
36
39
|
"title": "初始化 PGlite 數據庫"
|
37
40
|
},
|
38
41
|
"error": {
|
39
|
-
"desc": "非常抱歉,Pglite
|
42
|
+
"desc": "非常抱歉,Pglite 資料庫初始化過程發生異常。請點擊按鈕重試。如多次重試後仍重複出錯,請 <1>提交問題</1> ,我們將會第一時間幫你排查",
|
43
|
+
"detail": "錯誤原因:[{{type}}] {{message}},明細如下:",
|
40
44
|
"retry": "重試",
|
41
|
-
"title": "
|
45
|
+
"title": "資料庫初始化失敗"
|
42
46
|
},
|
43
47
|
"initing": {
|
44
48
|
"error": "發生錯誤,請重試",
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@lobehub/chat",
|
3
|
-
"version": "1.36.
|
3
|
+
"version": "1.36.40",
|
4
4
|
"description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
|
5
5
|
"keywords": [
|
6
6
|
"framework",
|
@@ -162,7 +162,6 @@
|
|
162
162
|
"i18next-resources-to-backend": "^1.2.1",
|
163
163
|
"idb-keyval": "^6.2.1",
|
164
164
|
"immer": "^10.1.1",
|
165
|
-
"ip": "^2.0.1",
|
166
165
|
"jose": "^5.9.4",
|
167
166
|
"js-sha256": "^0.11.0",
|
168
167
|
"jsonl-parse-stringify": "^1.0.3",
|
@@ -46,6 +46,7 @@ export const userSettings = pgTable('user_settings', {
|
|
46
46
|
defaultAgent: jsonb('default_agent'),
|
47
47
|
tool: jsonb('tool'),
|
48
48
|
});
|
49
|
+
export type UserSettingsItem = typeof userSettings.$inferSelect;
|
49
50
|
|
50
51
|
export const installedPlugins = pgTable(
|
51
52
|
'user_installed_plugins',
|
@@ -7,7 +7,7 @@ import { KeyVaultsGateKeeper } from '@/server/modules/KeyVaultsEncrypt';
|
|
7
7
|
import { UserGuide, UserPreference } from '@/types/user';
|
8
8
|
import { UserSettings } from '@/types/user/settings';
|
9
9
|
|
10
|
-
import { userSettings, users } from '../../../schemas';
|
10
|
+
import { UserSettingsItem, userSettings, users } from '../../../schemas';
|
11
11
|
import { SessionModel } from '../session';
|
12
12
|
import { UserModel } from '../user';
|
13
13
|
|
@@ -101,7 +101,7 @@ describe('UserModel', () => {
|
|
101
101
|
keyVaults: encryptedKeyVaults,
|
102
102
|
});
|
103
103
|
|
104
|
-
const state = await userModel.getUserState();
|
104
|
+
const state = await userModel.getUserState(KeyVaultsGateKeeper.getUserKeyVaults);
|
105
105
|
|
106
106
|
expect(state.userId).toBe(userId);
|
107
107
|
expect(state.preference).toEqual(preference);
|
@@ -111,7 +111,9 @@ describe('UserModel', () => {
|
|
111
111
|
it('should throw an error if user not found', async () => {
|
112
112
|
const userModel = new UserModel(serverDB, 'invalid-user-id');
|
113
113
|
|
114
|
-
await expect(userModel.getUserState()).rejects.toThrow(
|
114
|
+
await expect(userModel.getUserState(KeyVaultsGateKeeper.getUserKeyVaults)).rejects.toThrow(
|
115
|
+
'user not found',
|
116
|
+
);
|
115
117
|
});
|
116
118
|
});
|
117
119
|
|
@@ -144,11 +146,10 @@ describe('UserModel', () => {
|
|
144
146
|
});
|
145
147
|
|
146
148
|
describe('updateSetting', () => {
|
147
|
-
it('should update user settings with
|
149
|
+
it('should update user settings with new item', async () => {
|
148
150
|
const settings = {
|
149
151
|
general: { language: 'en-US' },
|
150
|
-
|
151
|
-
} as UserSettings;
|
152
|
+
} as UserSettingsItem;
|
152
153
|
await serverDB.insert(users).values({ id: userId });
|
153
154
|
|
154
155
|
await userModel.updateSetting(settings);
|
@@ -157,23 +158,18 @@ describe('UserModel', () => {
|
|
157
158
|
where: eq(users.id, userId),
|
158
159
|
});
|
159
160
|
expect(updatedSettings?.general).toEqual(settings.general);
|
160
|
-
expect(updatedSettings?.keyVaults).not.toBe(JSON.stringify(settings.keyVaults));
|
161
|
-
|
162
|
-
const gateKeeper = await KeyVaultsGateKeeper.initWithEnvKey();
|
163
|
-
const { plaintext } = await gateKeeper.decrypt(updatedSettings!.keyVaults!);
|
164
|
-
expect(JSON.parse(plaintext)).toEqual(settings.keyVaults);
|
165
161
|
});
|
166
162
|
|
167
|
-
it('should update user settings with
|
163
|
+
it('should update user settings with exist item', async () => {
|
168
164
|
const settings = {
|
169
165
|
general: { language: 'en-US' },
|
170
|
-
} as
|
166
|
+
} as UserSettingsItem;
|
171
167
|
await serverDB.insert(users).values({ id: userId });
|
172
168
|
await serverDB.insert(userSettings).values({ ...settings, keyVaults: '', id: userId });
|
173
169
|
|
174
170
|
const newSettings = {
|
175
171
|
general: { fontSize: 16, language: 'zh-CN', themeMode: 'dark' },
|
176
|
-
} as
|
172
|
+
} as UserSettingsItem;
|
177
173
|
await userModel.updateSetting(newSettings);
|
178
174
|
|
179
175
|
const updatedSettings = await serverDB.query.userSettings.findFirst({
|
@@ -229,14 +225,18 @@ describe('UserModel', () => {
|
|
229
225
|
keyVaults: encryptedKeyVaults,
|
230
226
|
});
|
231
227
|
|
232
|
-
const result = await UserModel.getUserApiKeys(
|
228
|
+
const result = await UserModel.getUserApiKeys(
|
229
|
+
serverDB,
|
230
|
+
userId,
|
231
|
+
KeyVaultsGateKeeper.getUserKeyVaults,
|
232
|
+
);
|
233
233
|
expect(result).toEqual(keyVaults);
|
234
234
|
});
|
235
235
|
|
236
236
|
it('should throw error when user not found', async () => {
|
237
|
-
await expect(
|
238
|
-
|
239
|
-
);
|
237
|
+
await expect(
|
238
|
+
UserModel.getUserApiKeys(serverDB, 'non-existent-id', KeyVaultsGateKeeper.getUserKeyVaults),
|
239
|
+
).rejects.toThrow('user not found');
|
240
240
|
});
|
241
241
|
|
242
242
|
it('should handle decrypt failure and return empty object', async () => {
|
@@ -249,7 +249,11 @@ describe('UserModel', () => {
|
|
249
249
|
keyVaults: invalidEncryptedData,
|
250
250
|
});
|
251
251
|
|
252
|
-
const result = await UserModel.getUserApiKeys(
|
252
|
+
const result = await UserModel.getUserApiKeys(
|
253
|
+
serverDB,
|
254
|
+
userId,
|
255
|
+
KeyVaultsGateKeeper.getUserKeyVaults,
|
256
|
+
);
|
253
257
|
expect(result).toEqual({});
|
254
258
|
});
|
255
259
|
});
|
@@ -301,7 +301,9 @@ export class SessionModel {
|
|
301
301
|
try {
|
302
302
|
// @ts-expect-error
|
303
303
|
return results.map((item) => item.agentsToSessions[0].session);
|
304
|
-
} catch {
|
304
|
+
} catch (e) {
|
305
|
+
console.error('findSessionsByKeywords error:', e);
|
306
|
+
}
|
305
307
|
return [];
|
306
308
|
};
|
307
309
|
}
|
@@ -3,14 +3,18 @@ import { eq } from 'drizzle-orm/expressions';
|
|
3
3
|
import { DeepPartial } from 'utility-types';
|
4
4
|
|
5
5
|
import { LobeChatDatabase } from '@/database/type';
|
6
|
-
import { KeyVaultsGateKeeper } from '@/server/modules/KeyVaultsEncrypt';
|
7
6
|
import { UserGuide, UserPreference } from '@/types/user';
|
8
7
|
import { UserKeyVaults, UserSettings } from '@/types/user/settings';
|
9
8
|
import { merge } from '@/utils/merge';
|
10
9
|
|
11
|
-
import { NewUser, UserItem, userSettings, users } from '../../schemas';
|
10
|
+
import { NewUser, UserItem, UserSettingsItem, userSettings, users } from '../../schemas';
|
12
11
|
import { SessionModel } from './session';
|
13
12
|
|
13
|
+
type DecryptUserKeyVaults = (
|
14
|
+
encryptKeyVaultsStr: string | null,
|
15
|
+
userId?: string,
|
16
|
+
) => Promise<UserKeyVaults>;
|
17
|
+
|
14
18
|
export class UserNotFoundError extends TRPCError {
|
15
19
|
constructor() {
|
16
20
|
super({ code: 'UNAUTHORIZED', message: 'user not found' });
|
@@ -26,7 +30,7 @@ export class UserModel {
|
|
26
30
|
this.db = db;
|
27
31
|
}
|
28
32
|
|
29
|
-
getUserState = async () => {
|
33
|
+
getUserState = async (decryptor: DecryptUserKeyVaults) => {
|
30
34
|
const result = await this.db
|
31
35
|
.select({
|
32
36
|
isOnboarded: users.isOnboarded,
|
@@ -51,19 +55,7 @@ export class UserModel {
|
|
51
55
|
const state = result[0];
|
52
56
|
|
53
57
|
// Decrypt keyVaults
|
54
|
-
|
55
|
-
if (state.settingsKeyVaults) {
|
56
|
-
const gateKeeper = await KeyVaultsGateKeeper.initWithEnvKey();
|
57
|
-
const { wasAuthentic, plaintext } = await gateKeeper.decrypt(state.settingsKeyVaults);
|
58
|
-
|
59
|
-
if (wasAuthentic) {
|
60
|
-
try {
|
61
|
-
decryptKeyVaults = JSON.parse(plaintext);
|
62
|
-
} catch (e) {
|
63
|
-
console.error(`Failed to parse keyVaults ,userId: ${this.userId}. Error:`, e);
|
64
|
-
}
|
65
|
-
}
|
66
|
-
}
|
58
|
+
const decryptKeyVaults = await decryptor(state.settingsKeyVaults, this.userId);
|
67
59
|
|
68
60
|
const settings: DeepPartial<UserSettings> = {
|
69
61
|
defaultAgent: state.settingsDefaultAgent || {},
|
@@ -94,32 +86,17 @@ export class UserModel {
|
|
94
86
|
return this.db.delete(userSettings).where(eq(userSettings.id, this.userId));
|
95
87
|
};
|
96
88
|
|
97
|
-
updateSetting = async (value: Partial<
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
encryptedKeyVaults = await gateKeeper.encrypt(data);
|
109
|
-
}
|
110
|
-
|
111
|
-
const newValue = { ...res, keyVaults: encryptedKeyVaults };
|
112
|
-
|
113
|
-
// update or create user settings
|
114
|
-
const settings = await this.db.query.userSettings.findFirst({
|
115
|
-
where: eq(users.id, this.userId),
|
116
|
-
});
|
117
|
-
if (!settings) {
|
118
|
-
await this.db.insert(userSettings).values({ id: this.userId, ...newValue });
|
119
|
-
return;
|
120
|
-
}
|
121
|
-
|
122
|
-
return this.db.update(userSettings).set(newValue).where(eq(userSettings.id, this.userId));
|
89
|
+
updateSetting = async (value: Partial<UserSettingsItem>) => {
|
90
|
+
return this.db
|
91
|
+
.insert(userSettings)
|
92
|
+
.values({
|
93
|
+
id: this.userId,
|
94
|
+
...value,
|
95
|
+
})
|
96
|
+
.onConflictDoUpdate({
|
97
|
+
set: value,
|
98
|
+
target: userSettings.id,
|
99
|
+
});
|
123
100
|
};
|
124
101
|
|
125
102
|
updatePreference = async (value: Partial<UserPreference>) => {
|
@@ -175,7 +152,11 @@ export class UserModel {
|
|
175
152
|
return db.query.users.findFirst({ where: eq(users.email, email) });
|
176
153
|
};
|
177
154
|
|
178
|
-
static getUserApiKeys = async (
|
155
|
+
static getUserApiKeys = async (
|
156
|
+
db: LobeChatDatabase,
|
157
|
+
id: string,
|
158
|
+
decryptor: DecryptUserKeyVaults,
|
159
|
+
) => {
|
179
160
|
const result = await db
|
180
161
|
.select({
|
181
162
|
settingsKeyVaults: userSettings.keyVaults,
|
@@ -190,20 +171,6 @@ export class UserModel {
|
|
190
171
|
const state = result[0];
|
191
172
|
|
192
173
|
// Decrypt keyVaults
|
193
|
-
|
194
|
-
if (state.settingsKeyVaults) {
|
195
|
-
const gateKeeper = await KeyVaultsGateKeeper.initWithEnvKey();
|
196
|
-
const { wasAuthentic, plaintext } = await gateKeeper.decrypt(state.settingsKeyVaults);
|
197
|
-
|
198
|
-
if (wasAuthentic) {
|
199
|
-
try {
|
200
|
-
decryptKeyVaults = JSON.parse(plaintext);
|
201
|
-
} catch (e) {
|
202
|
-
console.error(`Failed to parse keyVaults ,userId: ${id}. Error:`, e);
|
203
|
-
}
|
204
|
-
}
|
205
|
-
}
|
206
|
-
|
207
|
-
return decryptKeyVaults as UserKeyVaults;
|
174
|
+
return await decryptor(state.settingsKeyVaults, id);
|
208
175
|
};
|
209
176
|
}
|
@@ -13,6 +13,7 @@ export default {
|
|
13
13
|
appLoading: {
|
14
14
|
appIdle: '准备启动',
|
15
15
|
appInitializing: '应用启动中...',
|
16
|
+
failed: '很抱歉,应用初始化失败,请查看详情进行排查',
|
16
17
|
finished: '数据库初始化完成',
|
17
18
|
goToChat: '对话页面加载中...',
|
18
19
|
initAuth: '鉴权服务初始化...',
|
@@ -22,6 +23,7 @@ export default {
|
|
22
23
|
loadingWasm: '加载 WASM 模块...',
|
23
24
|
migrating: '执行数据表迁移...',
|
24
25
|
ready: '数据库已就绪',
|
26
|
+
showDetail: '查看详情',
|
25
27
|
},
|
26
28
|
autoGenerate: '自动补全',
|
27
29
|
autoGenerateTooltip: '基于提示词自动补全助手描述',
|
@@ -39,12 +41,13 @@ export default {
|
|
39
41
|
title: '初始化 PGlite 数据库',
|
40
42
|
},
|
41
43
|
error: {
|
42
|
-
desc: '非常抱歉,Pglite
|
44
|
+
desc: '非常抱歉,Pglite 数据库初始化过程发生异常。请点击按钮重试。如多次重试后仍重复出错,请 <1>提交问题</1> ,我们将会第一时间帮你排查',
|
45
|
+
detail: '错误原因:[{{type}}] {{message}},明细如下:',
|
43
46
|
retry: '重试',
|
44
|
-
title: '
|
47
|
+
title: '数据库初始化失败',
|
45
48
|
},
|
46
49
|
initing: {
|
47
|
-
error: '
|
50
|
+
error: '数据库初始化出错,点击查看详情',
|
48
51
|
idle: '等待初始化...',
|
49
52
|
initializing: '正在初始化...',
|
50
53
|
loadingDependencies: '加载依赖中...',
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import { getServerDBConfig } from '@/config/db';
|
2
|
+
import { UserKeyVaults } from '@/types/user/settings';
|
2
3
|
|
3
4
|
interface DecryptionResult {
|
4
5
|
plaintext: string;
|
@@ -90,4 +91,26 @@ If you don't have it, please run \`openssl rand -base64 32\` to create one.
|
|
90
91
|
};
|
91
92
|
}
|
92
93
|
};
|
94
|
+
|
95
|
+
static getUserKeyVaults = async (
|
96
|
+
encryptedKeyVaults: string | null,
|
97
|
+
userId?: string,
|
98
|
+
): Promise<UserKeyVaults> => {
|
99
|
+
if (!encryptedKeyVaults) return {};
|
100
|
+
// Decrypt keyVaults
|
101
|
+
let decryptKeyVaults = {};
|
102
|
+
|
103
|
+
const gateKeeper = await KeyVaultsGateKeeper.initWithEnvKey();
|
104
|
+
const { wasAuthentic, plaintext } = await gateKeeper.decrypt(encryptedKeyVaults);
|
105
|
+
|
106
|
+
if (wasAuthentic) {
|
107
|
+
try {
|
108
|
+
decryptKeyVaults = JSON.parse(plaintext);
|
109
|
+
} catch (e) {
|
110
|
+
console.error(`Failed to parse keyVaults, userId: ${userId}. Error:`, e);
|
111
|
+
}
|
112
|
+
}
|
113
|
+
|
114
|
+
return decryptKeyVaults as UserKeyVaults;
|
115
|
+
};
|
93
116
|
}
|
@@ -8,8 +8,10 @@ import { MessageModel } from '@/database/server/models/message';
|
|
8
8
|
import { SessionModel } from '@/database/server/models/session';
|
9
9
|
import { UserModel, UserNotFoundError } from '@/database/server/models/user';
|
10
10
|
import { authedProcedure, router } from '@/libs/trpc';
|
11
|
+
import { KeyVaultsGateKeeper } from '@/server/modules/KeyVaultsEncrypt';
|
11
12
|
import { UserService } from '@/server/services/user';
|
12
13
|
import { UserGuideSchema, UserInitializationState, UserPreference } from '@/types/user';
|
14
|
+
import { UserSettings } from '@/types/user/settings';
|
13
15
|
|
14
16
|
const userProcedure = authedProcedure.use(async (opts) => {
|
15
17
|
return opts.next({
|
@@ -24,7 +26,7 @@ export const userRouter = router({
|
|
24
26
|
// get or create first-time user
|
25
27
|
while (!state) {
|
26
28
|
try {
|
27
|
-
state = await ctx.userModel.getUserState();
|
29
|
+
state = await ctx.userModel.getUserState(KeyVaultsGateKeeper.getUserKeyVaults);
|
28
30
|
} catch (error) {
|
29
31
|
if (enableClerk && error instanceof UserNotFoundError) {
|
30
32
|
const user = await currentUser();
|
@@ -97,7 +99,22 @@ export const userRouter = router({
|
|
97
99
|
updateSettings: userProcedure
|
98
100
|
.input(z.object({}).passthrough())
|
99
101
|
.mutation(async ({ ctx, input }) => {
|
100
|
-
|
102
|
+
const { keyVaults, ...res } = input as Partial<UserSettings>;
|
103
|
+
|
104
|
+
// Encrypt keyVaults
|
105
|
+
let encryptedKeyVaults: string | null = null;
|
106
|
+
|
107
|
+
if (keyVaults) {
|
108
|
+
// TODO: better to add a validation
|
109
|
+
const data = JSON.stringify(keyVaults);
|
110
|
+
const gateKeeper = await KeyVaultsGateKeeper.initWithEnvKey();
|
111
|
+
|
112
|
+
encryptedKeyVaults = await gateKeeper.encrypt(data);
|
113
|
+
}
|
114
|
+
|
115
|
+
const nextValue = { ...res, keyVaults: encryptedKeyVaults };
|
116
|
+
|
117
|
+
return ctx.userModel.updateSetting(nextValue);
|
101
118
|
}),
|
102
119
|
});
|
103
120
|
|
@@ -3,6 +3,7 @@ import { UserJSON } from '@clerk/backend';
|
|
3
3
|
import { serverDB } from '@/database/server';
|
4
4
|
import { UserModel } from '@/database/server/models/user';
|
5
5
|
import { pino } from '@/libs/logger';
|
6
|
+
import { KeyVaultsGateKeeper } from '@/server/modules/KeyVaultsEncrypt';
|
6
7
|
|
7
8
|
export class UserService {
|
8
9
|
createUser = async (id: string, params: UserJSON) => {
|
@@ -84,4 +85,8 @@ export class UserService {
|
|
84
85
|
|
85
86
|
return { message: 'user updated', success: true };
|
86
87
|
};
|
88
|
+
|
89
|
+
getUserApiKeys = async (id: string) => {
|
90
|
+
return UserModel.getUserApiKeys(serverDB, id, KeyVaultsGateKeeper.getUserKeyVaults);
|
91
|
+
};
|
87
92
|
}
|