dify/api/tests/test_containers_integration_tests/controllers/openapi/conftest.py

105 lines
3.6 KiB
Python

from __future__ import annotations
import uuid
from collections.abc import Callable
from typing import Literal
from unittest.mock import patch
import pytest
from faker import Faker
from flask import Flask
from sqlalchemy.orm import Session
from controllers.openapi.auth.data import AuthData
from libs.oauth_bearer import Scope, TokenType
from machinery.context import AccountRequestContext
from models import Account, Tenant
from services.account_service import AccountService, TenantService
from tests.test_containers_integration_tests.helpers import generate_valid_password
@pytest.fixture
def app(flask_app_with_containers: Flask) -> Flask:
return flask_app_with_containers
@pytest.fixture
def make_account(db_session_with_containers: Session) -> Callable[..., Account]:
"""Factory that registers a real Account and gives it an owner workspace.
System feature gates are stubbed (registration / workspace creation
allowed) exactly like the AppDslService integration tests, so this stays a
pure account+tenant setup helper.
"""
# Depend on db_session_with_containers so the app context / DB session is
# active for the real AccountService/TenantService calls below.
assert db_session_with_containers is not None
def _make(*, with_owner_tenant: bool = True) -> Account:
fake = Faker()
with patch("services.account_service.SystemFeatureService") as mock_feature_service:
mock_feature_service.is_registration_allowed.return_value = True
account = AccountService.create_account(
email=fake.email(),
name=fake.name(),
interface_language="en-US",
password=generate_valid_password(fake),
session=db_session_with_containers,
)
if with_owner_tenant:
TenantService.create_owner_tenant_if_not_exist(
account, name=fake.company(), session=db_session_with_containers
)
return account
return _make
def add_tenant_for_account(
account: Account, *, session: Session, role: str = "normal", name: str = "Second WS"
) -> Tenant:
"""Create an additional tenant and join ``account`` to it (real service calls)."""
with patch("services.account_service.SystemFeatureService") as mock_feature_service:
mock_feature_service.is_workspace_creation_allowed.return_value = True
tenant = TenantService.create_tenant(name=name, session=session)
TenantService.create_tenant_member(tenant, account, session, role=role)
return tenant
def auth_for(
account: Account,
*,
app_model: object | None = None,
token_id: uuid.UUID | None = None,
caller_kind: Literal["account", "end_user"] | None = None,
) -> AuthData:
"""Build an AuthData for ``account`` (and optionally an app context).
``token_id`` is needed by the self-revoke endpoint, and ``caller_kind`` by
any handler calling ``require_app_context`` (e.g. file upload / task stop).
"""
return AuthData(
token_type=TokenType.OAUTH_ACCOUNT,
account_id=uuid.UUID(str(account.id)),
token_hash="integration-test",
token_id=token_id,
scopes=frozenset({Scope.FULL}),
caller=account,
caller_kind=caller_kind,
app=app_model, # type: ignore[arg-type]
)
def request_context_for(
account: Account,
*,
token_id: uuid.UUID | None = None,
) -> AccountRequestContext:
return AccountRequestContext(
request_id="integration-request",
trace_id="integration-trace",
account_id=str(account.id),
access_token_id=str(token_id) if token_id is not None else None,
)