diff --git a/backend/danswer/auth/noauth_user.py b/backend/danswer/auth/noauth_user.py
index c7e11cd452a..fdb48f34854 100644
--- a/backend/danswer/auth/noauth_user.py
+++ b/backend/danswer/auth/noauth_user.py
@@ -28,13 +28,16 @@ def load_no_auth_user_preferences(store: KeyValueStore) -> UserPreferences:
)
-def fetch_no_auth_user(store: KeyValueStore) -> UserInfo:
+def fetch_no_auth_user(
+ store: KeyValueStore, *, anonymous_user_enabled: bool | None = None
+) -> UserInfo:
return UserInfo(
id="__no_auth_user__",
email="anonymous@danswer.ai",
is_active=True,
is_superuser=False,
is_verified=True,
- role=UserRole.ADMIN,
+ role=UserRole.ADMIN if anonymous_user_enabled else UserRole.BASIC,
preferences=load_no_auth_user_preferences(store),
+ is_anonymous_user=anonymous_user_enabled,
)
diff --git a/backend/danswer/server/manage/llm/api.py b/backend/danswer/server/manage/llm/api.py
index f52877d919a..56f3bbbf56f 100644
--- a/backend/danswer/server/manage/llm/api.py
+++ b/backend/danswer/server/manage/llm/api.py
@@ -7,7 +7,7 @@
from sqlalchemy.orm import Session
from danswer.auth.users import current_admin_user
-from danswer.auth.users import current_user
+from danswer.auth.users import current_second_level_limited_user
from danswer.db.engine import get_session
from danswer.db.llm import fetch_existing_llm_providers
from danswer.db.llm import fetch_provider
@@ -190,7 +190,7 @@ def set_provider_as_default(
@basic_router.get("/provider")
def list_llm_provider_basics(
- user: User | None = Depends(current_user),
+ user: User | None = Depends(current_second_level_limited_user),
db_session: Session = Depends(get_session),
) -> list[LLMProviderDescriptor]:
return [
diff --git a/backend/danswer/server/manage/users.py b/backend/danswer/server/manage/users.py
index 33162b93430..1633279b647 100644
--- a/backend/danswer/server/manage/users.py
+++ b/backend/danswer/server/manage/users.py
@@ -26,6 +26,7 @@
from danswer.auth.noauth_user import set_no_auth_user_preferences
from danswer.auth.schemas import UserRole
from danswer.auth.schemas import UserStatus
+from danswer.auth.users import anonymous_user_enabled
from danswer.auth.users import current_admin_user
from danswer.auth.users import current_curator_or_admin_user
from danswer.auth.users import current_user
@@ -489,13 +490,15 @@ def verify_user_logged_in(
# NOTE: this does not use `current_user` / `current_admin_user` because we don't want
# to enforce user verification here - the frontend always wants to get the info about
# the current user regardless of if they are currently verified
-
if user is None:
# if auth type is disabled, return a dummy user with preferences from
# the key-value store
if AUTH_TYPE == AuthType.DISABLED:
store = get_kv_store()
return fetch_no_auth_user(store)
+ if anonymous_user_enabled():
+ store = get_kv_store()
+ return fetch_no_auth_user(store, anonymous_user_enabled=True)
raise BasicAuthenticationError(detail="User Not Authenticated")
if user.oidc_expiry and user.oidc_expiry < datetime.now(timezone.utc):
diff --git a/backend/danswer/server/query_and_chat/chat_backend.py b/backend/danswer/server/query_and_chat/chat_backend.py
index 00c9da319aa..52498fa35d0 100644
--- a/backend/danswer/server/query_and_chat/chat_backend.py
+++ b/backend/danswer/server/query_and_chat/chat_backend.py
@@ -139,7 +139,7 @@ def update_chat_session_model(
def get_chat_session(
session_id: UUID,
is_shared: bool = False,
- user: User | None = Depends(current_user),
+ user: User | None = Depends(current_second_level_limited_user),
db_session: Session = Depends(get_session),
) -> ChatSessionDetailResponse:
user_id = user.id if user is not None else None
@@ -313,7 +313,7 @@ def is_connected_sync() -> bool:
def handle_new_chat_message(
chat_message_req: CreateChatMessageRequest,
request: Request,
- user: User | None = Depends(current_limited_user),
+ user: User | None = Depends(current_second_level_limited_user),
_: None = Depends(check_token_rate_limits),
is_connected_func: Callable[[], bool] = Depends(is_connected),
) -> StreamingResponse:
diff --git a/web/src/app/chat/ChatPage.tsx b/web/src/app/chat/ChatPage.tsx
index f9fb554a3ba..de5b8cea481 100644
--- a/web/src/app/chat/ChatPage.tsx
+++ b/web/src/app/chat/ChatPage.tsx
@@ -2198,6 +2198,7 @@ export function ChatPage({
currentChatSession={selectedChatSession}
documentSidebarToggled={documentSidebarToggled}
llmOverrideManager={llmOverrideManager}
+ hideUserDropdown={user?.is_anonymous_user}
/>
)}
diff --git a/web/src/components/chat_search/Header.tsx b/web/src/components/chat_search/Header.tsx
index de0f4699f8b..ec4f04d447d 100644
--- a/web/src/components/chat_search/Header.tsx
+++ b/web/src/components/chat_search/Header.tsx
@@ -26,6 +26,7 @@ export default function FunctionalHeader({
llmOverrideManager,
documentSidebarToggled,
toggleUserSettings,
+ hideUserDropdown,
}: {
reset?: () => void;
page: pageType;
@@ -38,6 +39,7 @@ export default function FunctionalHeader({
onAssistantChange?: (assistant: Persona) => void;
llmOverrideManager?: LlmOverrideManager;
toggleUserSettings?: () => void;
+ hideUserDropdown?: boolean;
}) {
useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
@@ -119,9 +121,14 @@ export default function FunctionalHeader({