Move production dependencies to prod python packages group

This will reduce khoj dependencies to install for self-hosting users

- Move auth production dependencies to prod python packages group
  - Only enable authentication API router if not in anonymous mode
  - Improve error with requirements to enable authentication when not in
    anonymous mode
This commit is contained in:
Debanjum Singh Solanky
2024-02-14 15:20:27 +05:30
parent d7dbb715ef
commit cf4a524988
6 changed files with 47 additions and 25 deletions

View File

@@ -73,6 +73,7 @@ class UserAuthenticationBackend(AuthenticationBackend):
Subscription.objects.create(user=default_user, type="standard", renewal_date=renewal_date)
async def authenticate(self, request: HTTPConnection):
# Request from Web client
current_user = request.session.get("user")
if current_user and current_user.get("email"):
user = (
@@ -93,6 +94,8 @@ class UserAuthenticationBackend(AuthenticationBackend):
if subscribed:
return AuthCredentials(["authenticated", "premium"]), AuthenticatedKhojUser(user)
return AuthCredentials(["authenticated"]), AuthenticatedKhojUser(user)
# Request from Desktop, Emacs, Obsidian clients
if len(request.headers.get("Authorization", "").split("Bearer ")) == 2:
# Get bearer token from header
bearer_token = request.headers["Authorization"].split("Bearer ")[1]
@@ -116,7 +119,8 @@ class UserAuthenticationBackend(AuthenticationBackend):
if subscribed:
return AuthCredentials(["authenticated", "premium"]), AuthenticatedKhojUser(user_with_token.user)
return AuthCredentials(["authenticated"]), AuthenticatedKhojUser(user_with_token.user)
# Get query params for client_id and client_secret
# Request from Whatsapp client
client_id = request.query_params.get("client_id")
if client_id:
# Get the client secret, which is passed in the Authorization header
@@ -163,6 +167,8 @@ class UserAuthenticationBackend(AuthenticationBackend):
AuthenticatedKhojUser(user, client_application),
)
return AuthCredentials(["authenticated"]), AuthenticatedKhojUser(user, client_application)
# No auth required if server in anonymous mode
if state.anonymous_mode:
user = await self.khojuser_manager.filter(username="default").prefetch_related("subscription").afirst()
if user:
@@ -258,28 +264,32 @@ def configure_routes(app):
from khoj.routers.api import api
from khoj.routers.api_chat import api_chat
from khoj.routers.api_config import api_config
from khoj.routers.auth import auth_router
from khoj.routers.indexer import indexer
from khoj.routers.web_client import web_client
app.include_router(api, prefix="/api")
app.include_router(api_chat, prefix="/api/chat")
app.include_router(api_config, prefix="/api/config")
app.include_router(indexer, prefix="/api/v1/index")
app.include_router(web_client)
app.include_router(auth_router, prefix="/auth")
app.include_router(api_chat, prefix="/api/chat")
if not state.anonymous_mode:
from khoj.routers.auth import auth_router
app.include_router(auth_router, prefix="/auth")
logger.info("🔑 Enabled Authentication")
if state.billing_enabled:
from khoj.routers.subscription import subscription_router
logger.info("💳 Enabled Billing")
app.include_router(subscription_router, prefix="/api/subscription")
logger.info("💳 Enabled Billing")
if is_twilio_enabled():
logger.info("📞 Enabled Twilio")
from khoj.routers.api_phone import api_phone
app.include_router(api_phone, prefix="/api/config/phone")
logger.info("📞 Enabled Twilio")
def configure_middleware(app):

View File

@@ -2,10 +2,7 @@ import logging
import os
from typing import Optional
from authlib.integrations.starlette_client import OAuth, OAuthError
from fastapi import APIRouter
from google.auth.transport import requests as google_requests
from google.oauth2 import id_token
from starlette.authentication import requires
from starlette.config import Config
from starlette.requests import Request
@@ -17,7 +14,6 @@ from khoj.database.adapters import (
get_khoj_tokens,
get_or_create_user,
)
from khoj.database.models import KhojApiUser
from khoj.routers.helpers import update_telemetry_state
from khoj.utils import state
@@ -25,11 +21,23 @@ logger = logging.getLogger(__name__)
auth_router = APIRouter()
if not state.anonymous_mode and not (os.environ.get("GOOGLE_CLIENT_ID") and os.environ.get("GOOGLE_CLIENT_SECRET")):
logger.warning(
"🚨 Use --anonymous-mode flag to disable Google OAuth or set GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET environment variables to enable it"
)
else:
if not state.anonymous_mode:
missing_requirements = []
from authlib.integrations.starlette_client import OAuth, OAuthError
try:
from google.auth.transport import requests as google_requests
from google.oauth2 import id_token
except ImportError:
missing_requirements += ["Install the Khoj production package with `pip install khoj-assistant[prod]`"]
if not os.environ.get("GOOGLE_CLIENT_ID") or not os.environ.get("GOOGLE_CLIENT_SECRET"):
missing_requirements += ["Set your GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET as environment variables"]
if missing_requirements:
requirements_string = "\n - " + "\n - ".join(missing_requirements)
error_msg = f"🚨 Start Khoj with --anonymous-mode flag or to enable authentication:{requirements_string}"
logger.error(error_msg)
config = Config(environ=os.environ)
oauth = OAuth(config)

View File

@@ -2,16 +2,18 @@ import logging
import os
from datetime import datetime, timezone
import stripe
from asgiref.sync import sync_to_async
from fastapi import APIRouter, Request
from fastapi.responses import Response
from starlette.authentication import requires
from khoj.database import adapters
from khoj.utils import state
# Stripe integration for Khoj Cloud Subscription
stripe.api_key = os.getenv("STRIPE_API_KEY")
if state.billing_enabled:
import stripe
stripe.api_key = os.getenv("STRIPE_API_KEY")
endpoint_secret = os.getenv("STRIPE_SIGNING_SECRET")
logger = logging.getLogger(__name__)
subscription_router = APIRouter()

View File

@@ -1,8 +1,6 @@
import logging
import os
from twilio.rest import Client
from khoj.database.models import KhojUser
logger = logging.getLogger(__name__)
@@ -13,6 +11,8 @@ verification_service_sid = os.getenv("TWILIO_VERIFICATION_SID")
twilio_enabled = account_sid is not None and auth_token is not None and verification_service_sid is not None
if twilio_enabled:
from twilio.rest import Client
client = Client(account_sid, auth_token)