mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-09-20 04:37:09 +02:00
@@ -42,6 +42,10 @@ class UserCreate(schemas.BaseUserCreate):
|
|||||||
tenant_id: str | None = None
|
tenant_id: str | None = None
|
||||||
|
|
||||||
|
|
||||||
|
class UserUpdateWithRole(schemas.BaseUserUpdate):
|
||||||
|
role: UserRole
|
||||||
|
|
||||||
|
|
||||||
class UserUpdate(schemas.BaseUserUpdate):
|
class UserUpdate(schemas.BaseUserUpdate):
|
||||||
"""
|
"""
|
||||||
Role updates are not allowed through the user update endpoint for security reasons
|
Role updates are not allowed through the user update endpoint for security reasons
|
||||||
|
@@ -57,7 +57,7 @@ from onyx.auth.invited_users import get_invited_users
|
|||||||
from onyx.auth.schemas import AuthBackend
|
from onyx.auth.schemas import AuthBackend
|
||||||
from onyx.auth.schemas import UserCreate
|
from onyx.auth.schemas import UserCreate
|
||||||
from onyx.auth.schemas import UserRole
|
from onyx.auth.schemas import UserRole
|
||||||
from onyx.auth.schemas import UserUpdate
|
from onyx.auth.schemas import UserUpdateWithRole
|
||||||
from onyx.configs.app_configs import AUTH_BACKEND
|
from onyx.configs.app_configs import AUTH_BACKEND
|
||||||
from onyx.configs.app_configs import AUTH_COOKIE_EXPIRE_TIME_SECONDS
|
from onyx.configs.app_configs import AUTH_COOKIE_EXPIRE_TIME_SECONDS
|
||||||
from onyx.configs.app_configs import AUTH_TYPE
|
from onyx.configs.app_configs import AUTH_TYPE
|
||||||
@@ -216,7 +216,6 @@ class UserManager(UUIDIDMixin, BaseUserManager[User, uuid.UUID]):
|
|||||||
reset_password_token_secret = USER_AUTH_SECRET
|
reset_password_token_secret = USER_AUTH_SECRET
|
||||||
verification_token_secret = USER_AUTH_SECRET
|
verification_token_secret = USER_AUTH_SECRET
|
||||||
verification_token_lifetime_seconds = AUTH_COOKIE_EXPIRE_TIME_SECONDS
|
verification_token_lifetime_seconds = AUTH_COOKIE_EXPIRE_TIME_SECONDS
|
||||||
|
|
||||||
user_db: SQLAlchemyUserDatabase[User, uuid.UUID]
|
user_db: SQLAlchemyUserDatabase[User, uuid.UUID]
|
||||||
|
|
||||||
async def create(
|
async def create(
|
||||||
@@ -246,10 +245,8 @@ class UserManager(UUIDIDMixin, BaseUserManager[User, uuid.UUID]):
|
|||||||
referral_source=referral_source,
|
referral_source=referral_source,
|
||||||
request=request,
|
request=request,
|
||||||
)
|
)
|
||||||
|
|
||||||
async with get_async_session_with_tenant(tenant_id) as db_session:
|
async with get_async_session_with_tenant(tenant_id) as db_session:
|
||||||
token = CURRENT_TENANT_ID_CONTEXTVAR.set(tenant_id)
|
token = CURRENT_TENANT_ID_CONTEXTVAR.set(tenant_id)
|
||||||
|
|
||||||
verify_email_is_invited(user_create.email)
|
verify_email_is_invited(user_create.email)
|
||||||
verify_email_domain(user_create.email)
|
verify_email_domain(user_create.email)
|
||||||
if MULTI_TENANT:
|
if MULTI_TENANT:
|
||||||
@@ -268,16 +265,16 @@ class UserManager(UUIDIDMixin, BaseUserManager[User, uuid.UUID]):
|
|||||||
user_create.role = UserRole.ADMIN
|
user_create.role = UserRole.ADMIN
|
||||||
else:
|
else:
|
||||||
user_create.role = UserRole.BASIC
|
user_create.role = UserRole.BASIC
|
||||||
|
|
||||||
try:
|
try:
|
||||||
user = await super().create(user_create, safe=safe, request=request) # type: ignore
|
user = await super().create(user_create, safe=safe, request=request) # type: ignore
|
||||||
except exceptions.UserAlreadyExists:
|
except exceptions.UserAlreadyExists:
|
||||||
user = await self.get_by_email(user_create.email)
|
user = await self.get_by_email(user_create.email)
|
||||||
# Handle case where user has used product outside of web and is now creating an account through web
|
# Handle case where user has used product outside of web and is now creating an account through web
|
||||||
if not user.role.is_web_login() and user_create.role.is_web_login():
|
if not user.role.is_web_login() and user_create.role.is_web_login():
|
||||||
user_update = UserUpdate(
|
user_update = UserUpdateWithRole(
|
||||||
password=user_create.password,
|
password=user_create.password,
|
||||||
is_verified=user_create.is_verified,
|
is_verified=user_create.is_verified,
|
||||||
|
role=user_create.role,
|
||||||
)
|
)
|
||||||
user = await self.update(user_update, user)
|
user = await self.update(user_update, user)
|
||||||
else:
|
else:
|
||||||
@@ -285,7 +282,6 @@ class UserManager(UUIDIDMixin, BaseUserManager[User, uuid.UUID]):
|
|||||||
|
|
||||||
finally:
|
finally:
|
||||||
CURRENT_TENANT_ID_CONTEXTVAR.reset(token)
|
CURRENT_TENANT_ID_CONTEXTVAR.reset(token)
|
||||||
|
|
||||||
return user
|
return user
|
||||||
|
|
||||||
async def validate_password(self, password: str, _: schemas.UC | models.UP) -> None:
|
async def validate_password(self, password: str, _: schemas.UC | models.UP) -> None:
|
||||||
|
@@ -534,7 +534,7 @@ export function ChatInputBar({
|
|||||||
filterManager.selectedDocumentSets.length > 0 ||
|
filterManager.selectedDocumentSets.length > 0 ||
|
||||||
filterManager.selectedTags.length > 0 ||
|
filterManager.selectedTags.length > 0 ||
|
||||||
filterManager.selectedSources.length > 0) && (
|
filterManager.selectedSources.length > 0) && (
|
||||||
<div className="flex gap-x-.5 px-2">
|
<div className="flex bg-background gap-x-.5 px-2">
|
||||||
<div className="flex gap-x-1 px-2 overflow-visible overflow-x-scroll items-end miniscroll">
|
<div className="flex gap-x-1 px-2 overflow-visible overflow-x-scroll items-end miniscroll">
|
||||||
{filterManager.selectedTags &&
|
{filterManager.selectedTags &&
|
||||||
filterManager.selectedTags.map((tag, index) => (
|
filterManager.selectedTags.map((tag, index) => (
|
||||||
|
@@ -21,8 +21,12 @@ export const AddMemberForm: React.FC<AddMemberFormProps> = ({
|
|||||||
const [selectedUserIds, setSelectedUserIds] = useState<string[]>([]);
|
const [selectedUserIds, setSelectedUserIds] = useState<string[]>([]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal title="Add New User" onOutsideClick={() => onClose()}>
|
<Modal
|
||||||
<div className="px-6 pt-4 pb-12">
|
className="max-w-xl"
|
||||||
|
title="Add New User"
|
||||||
|
onOutsideClick={() => onClose()}
|
||||||
|
>
|
||||||
|
<div className="flex flex-col">
|
||||||
<UserEditor
|
<UserEditor
|
||||||
selectedUserIds={selectedUserIds}
|
selectedUserIds={selectedUserIds}
|
||||||
setSelectedUserIds={setSelectedUserIds}
|
setSelectedUserIds={setSelectedUserIds}
|
||||||
|
@@ -120,9 +120,7 @@ export function Modal({
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-grow overflow-y-auto overflow-x-hidden">
|
{children}
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@@ -160,7 +160,7 @@ export function UserDropdown({
|
|||||||
{user && user.email ? user.email[0].toUpperCase() : "A"}
|
{user && user.email ? user.email[0].toUpperCase() : "A"}
|
||||||
</div>
|
</div>
|
||||||
{notifications && notifications.length > 0 && (
|
{notifications && notifications.length > 0 && (
|
||||||
<div className="absolute right-0 top-0 w-3 h-3 bg-red-500 rounded-full"></div>
|
<div className="absolute -right-0.5 -top-0.5 w-3 h-3 bg-red-500 rounded-full"></div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
@@ -11,6 +11,8 @@ import {
|
|||||||
import { ChatSession, InputPrompt } from "@/app/chat/interfaces";
|
import { ChatSession, InputPrompt } from "@/app/chat/interfaces";
|
||||||
import { LLMProviderDescriptor } from "@/app/admin/configuration/llm/interfaces";
|
import { LLMProviderDescriptor } from "@/app/admin/configuration/llm/interfaces";
|
||||||
import { Folder } from "@/app/chat/folders/interfaces";
|
import { Folder } from "@/app/chat/folders/interfaces";
|
||||||
|
import { useSearchParams } from "next/navigation";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
|
||||||
interface ChatContextProps {
|
interface ChatContextProps {
|
||||||
chatSessions: ChatSession[];
|
chatSessions: ChatSession[];
|
||||||
@@ -49,6 +51,8 @@ export const ChatProvider: React.FC<{
|
|||||||
>;
|
>;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}> = ({ value, children }) => {
|
}> = ({ value, children }) => {
|
||||||
|
const router = useRouter();
|
||||||
|
const searchParams = useSearchParams();
|
||||||
const [inputPrompts, setInputPrompts] = useState(value?.inputPrompts || []);
|
const [inputPrompts, setInputPrompts] = useState(value?.inputPrompts || []);
|
||||||
const [chatSessions, setChatSessions] = useState(value?.chatSessions || []);
|
const [chatSessions, setChatSessions] = useState(value?.chatSessions || []);
|
||||||
const [folders, setFolders] = useState(value?.folders || []);
|
const [folders, setFolders] = useState(value?.folders || []);
|
||||||
@@ -70,6 +74,16 @@ export const ChatProvider: React.FC<{
|
|||||||
if (!response.ok) throw new Error("Failed to fetch chat sessions");
|
if (!response.ok) throw new Error("Failed to fetch chat sessions");
|
||||||
const { sessions } = await response.json();
|
const { sessions } = await response.json();
|
||||||
setChatSessions(sessions);
|
setChatSessions(sessions);
|
||||||
|
|
||||||
|
const currentSessionId = searchParams.get("chatId");
|
||||||
|
if (
|
||||||
|
currentSessionId &&
|
||||||
|
!sessions.some(
|
||||||
|
(session: ChatSession) => session.id === currentSessionId
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
router.replace("/chat");
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error refreshing chat sessions:", error);
|
console.error("Error refreshing chat sessions:", error);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user