mirror of
https://github.com/khoaliber/khoj.git
synced 2026-03-08 21:29:12 +00:00
[Multi-User Part 4]: Authenticate using API Tokens (#513)
### ✨ New - Use API keys to authenticate from Desktop, Obsidian, Emacs clients - Create API, UI on web app config page to CRUD API Keys - Create user API keys table and functions to CRUD them in Database ### 🧪 Improve - Default to better search model, [gte-small](https://huggingface.co/thenlper/gte-small), to improve search quality - Only load chat model to GPU if enough space, throw error on load failure - Show encoding progress, truncate headings to max chars supported - Add instruction to create db in Django DB setup Readme ### ⚙️ Fix - Fix error handling when configure offline chat via Web UI - Do not warn in anon mode about Google OAuth env vars not being set - Fix path to load static files when server started from project root
This commit is contained in:
@@ -28,6 +28,7 @@ from khoj.utils import state, fs_syncer
|
||||
from khoj.routers.indexer import configure_content
|
||||
from khoj.processor.org_mode.org_to_jsonl import OrgToJsonl
|
||||
from database.models import (
|
||||
KhojApiUser,
|
||||
LocalOrgConfig,
|
||||
LocalMarkdownConfig,
|
||||
LocalPlaintextConfig,
|
||||
@@ -76,13 +77,26 @@ def default_user2():
|
||||
if KhojUser.objects.filter(username="default").exists():
|
||||
return KhojUser.objects.get(username="default")
|
||||
|
||||
return UserFactory(
|
||||
return KhojUser.objects.create(
|
||||
username="default",
|
||||
email="default@example.com",
|
||||
password="default",
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@pytest.fixture
|
||||
def api_user(default_user):
|
||||
if KhojApiUser.objects.filter(user=default_user).exists():
|
||||
return KhojApiUser.objects.get(user=default_user)
|
||||
|
||||
return KhojApiUser.objects.create(
|
||||
user=default_user,
|
||||
name="api-key",
|
||||
token="kk-secret",
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def search_models(search_config: SearchConfig):
|
||||
search_models = SearchModels()
|
||||
@@ -176,7 +190,7 @@ def chat_client(search_config: SearchConfig, default_user2: KhojUser):
|
||||
if os.getenv("OPENAI_API_KEY"):
|
||||
OpenAIProcessorConversationConfigFactory(user=default_user2)
|
||||
|
||||
state.anonymous_mode = True
|
||||
state.anonymous_mode = False
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
@@ -219,7 +233,7 @@ def fastapi_app():
|
||||
def client(
|
||||
content_config: ContentConfig,
|
||||
search_config: SearchConfig,
|
||||
default_user: KhojUser,
|
||||
api_user: KhojApiUser,
|
||||
):
|
||||
state.config.content_type = content_config
|
||||
state.config.search_type = search_config
|
||||
@@ -231,7 +245,7 @@ def client(
|
||||
OrgToJsonl,
|
||||
get_sample_data("org"),
|
||||
regenerate=False,
|
||||
user=default_user,
|
||||
user=api_user.user,
|
||||
)
|
||||
state.content_index.image = image_search.setup(
|
||||
content_config.image, state.search_models.image_search, regenerate=False
|
||||
@@ -240,11 +254,11 @@ def client(
|
||||
PlaintextToJsonl,
|
||||
get_sample_data("plaintext"),
|
||||
regenerate=False,
|
||||
user=default_user,
|
||||
user=api_user.user,
|
||||
)
|
||||
|
||||
ConversationProcessorConfigFactory(user=default_user)
|
||||
state.anonymous_mode = True
|
||||
ConversationProcessorConfigFactory(user=api_user.user)
|
||||
state.anonymous_mode = False
|
||||
|
||||
configure_routes(app)
|
||||
configure_middleware(app)
|
||||
@@ -253,13 +267,8 @@ def client(
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def client_offline_chat(
|
||||
search_config: SearchConfig,
|
||||
content_config: ContentConfig,
|
||||
default_user2: KhojUser,
|
||||
):
|
||||
def client_offline_chat(search_config: SearchConfig, default_user2: KhojUser):
|
||||
# Initialize app state
|
||||
state.config.content_type = md_content_config
|
||||
state.config.search_type = search_config
|
||||
state.SearchType = configure_search_types(state.config)
|
||||
|
||||
@@ -269,9 +278,6 @@ def client_offline_chat(
|
||||
user=default_user2,
|
||||
)
|
||||
|
||||
# Index Markdown Content for Search
|
||||
state.search_models.image_search = image_search.initialize_model(search_config.image)
|
||||
|
||||
all_files = fs_syncer.collect_files(user=default_user2)
|
||||
configure_content(
|
||||
state.content_index, state.config.content_type, all_files, state.search_models, user=default_user2
|
||||
@@ -283,6 +289,8 @@ def client_offline_chat(
|
||||
|
||||
state.anonymous_mode = True
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
configure_routes(app)
|
||||
configure_middleware(app)
|
||||
app.mount("/static", StaticFiles(directory=web_directory), name="static")
|
||||
|
||||
Reference in New Issue
Block a user