1
0
forked from github/onyx

Compare commits

...

7 Commits

Author SHA1 Message Date
pablonyx
a72e67ef74 k 2025-02-26 20:12:06 -08:00
pablonyx
9881e88eaa k 2025-02-26 20:11:34 -08:00
pablodanswer
b6efd784a1 k 2025-02-26 20:11:34 -08:00
pablodanswer
0ae951daa9 fix typing 2025-02-26 20:11:34 -08:00
pablodanswer
51d93659d7 add test 2025-02-26 20:11:34 -08:00
pablodanswer
4512711b7a fix code path 2025-02-26 20:11:34 -08:00
pablodanswer
a864150379 fix code path 2025-02-26 20:11:34 -08:00
4 changed files with 77 additions and 1 deletions

View File

@@ -4,6 +4,7 @@ import secrets
import string
import uuid
from collections.abc import AsyncGenerator
from collections.abc import Awaitable
from datetime import datetime
from datetime import timezone
from typing import cast
@@ -292,6 +293,7 @@ class UserManager(UUIDIDMixin, BaseUserManager[User, uuid.UUID]):
token = CURRENT_TENANT_ID_CONTEXTVAR.set(tenant_id)
verify_email_is_invited(user_create.email)
verify_email_domain(user_create.email)
if MULTI_TENANT:
tenant_user_db = SQLAlchemyUserAdminDB[User, uuid.UUID](
db_session, User, OAuthAccount
@@ -311,7 +313,10 @@ class UserManager(UUIDIDMixin, BaseUserManager[User, uuid.UUID]):
try:
user = await super().create(user_create, safe=safe, request=request) # type: ignore
except exceptions.UserAlreadyExists:
user = await self.get_by_email(user_create.email)
user = await cast(
Awaitable[User], self.user_db.get_by_email(user_create.email)
)
# 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():
user_update = UserUpdateWithRole(

View File

@@ -93,6 +93,32 @@ class UserManager:
test_user.cookies = {"fastapiusersauth": session_cookie}
return test_user
@staticmethod
def invite_users(
user_performing_action: DATestUser,
emails: list[str],
) -> int:
response = requests.put(
url=f"{API_SERVER_URL}/manage/admin/users",
json={"emails": emails},
headers=user_performing_action.headers,
)
response.raise_for_status()
return response.json()
@staticmethod
def remove_invited_user(
user_performing_action: DATestUser,
user_email: str,
) -> int:
response = requests.patch(
url=f"{API_SERVER_URL}/manage/admin/remove-invited-user",
json={"user_email": user_email},
headers=user_performing_action.headers,
)
response.raise_for_status()
return response.json()
@staticmethod
def is_role(
user_to_verify: DATestUser,

View File

@@ -0,0 +1,44 @@
import pytest
from requests import HTTPError
from onyx.auth.schemas import UserRole
from tests.integration.common_utils.managers.user import UserManager
from tests.integration.common_utils.test_models import DATestUser
def test_inviting_users_flow(reset: None) -> None:
"""
Test that verifies the functionality around inviting users:
1. Creating an admin user
2. Admin inviting a new user
3. Invited user successfully signing in
4. Non-invited user attempting to sign in (should result in an error)
"""
# 1) Create an admin user (the first user created is automatically admin)
admin_user: DATestUser = UserManager.create(name="admin_user")
assert admin_user is not None
assert UserManager.is_role(
admin_user, UserRole.ADMIN
), "Admin user should have ADMIN role"
# 2) Admin invites a new user
invited_email = "invited_user@test.com"
invite_response = UserManager.invite_users(admin_user, [invited_email])
assert (
invite_response == 1
), "Invite operation should return count=1 for a single invited user"
# 3) The invited user successfully registers/logs in
invited_user: DATestUser = UserManager.create(
name="invited_user", email=invited_email
)
assert invited_user is not None, "Invited user should be able to register"
assert invited_user.email == invited_email, "Invited user email mismatch"
assert UserManager.is_role(
invited_user, UserRole.BASIC
), "Newly created user should have BASIC role by default"
# 4) A non-invited user attempts to sign in/register (should fail)
with pytest.raises(HTTPError):
UserManager.create(name="uninvited_user", email="uninvited_user@test.com")

View File

@@ -383,6 +383,7 @@ export function FilterPopup({
)}
</div>
</div>
<Separator className="mt-0 mb-2" />
<div className="flex justify-between items-center px-4 py-2">
<Button