mirror of
https://github.com/langgenius/dify.git
synced 2026-05-27 04:16:16 +08:00
Replace the single mutable-context Pipeline with a two-phase, condition-driven system dispatched by token type. New architecture: - TokenType(StrEnum) replaces source: str on AuthContext / TokenKind - AuthPipeline: pure prepare→auth step runner; no guard() - PipelineRoute: binds AuthPipeline to an optional required_edition gate - PipelineRouter: single guard() entry point; runs edition/license/token-type pre-gates then dispatches to the registered pipeline for the token type - Cond / When: composable predicates for conditional step dispatch - AuthData: frozen Pydantic model produced by the prepare phase; carries token_id so endpoints don't need to call get_auth_ctx() for identity fields - Edition enum + current_edition(): CE / EE / SAAS discriminator Two pipelines in composition.py: - account_pipeline — OAUTH_ACCOUNT tokens - external_sso_pipeline — OAUTH_EXTERNAL_SSO tokens (EE enforced at route level) All /openapi/v1 endpoints migrated to auth_router.guard(). Old context.py, steps.py, strategies.py, surface_gate.py deleted. WORKSPACE_READ scope added; cached_verdicts renamed to membership_cache.
81 lines
2.8 KiB
Python
81 lines
2.8 KiB
Python
from controllers.openapi.auth.composition import account_pipeline, auth_router, external_sso_pipeline
|
|
from controllers.openapi.auth.flow import When
|
|
from controllers.openapi.auth.pipeline import AuthPipeline, PipelineRoute, PipelineRouter
|
|
from libs.oauth_bearer import TokenType
|
|
|
|
|
|
def test_account_pipeline_is_auth_pipeline():
|
|
assert isinstance(account_pipeline, AuthPipeline)
|
|
|
|
|
|
def test_external_sso_pipeline_is_auth_pipeline():
|
|
assert isinstance(external_sso_pipeline, AuthPipeline)
|
|
|
|
|
|
def test_auth_router_is_pipeline_router():
|
|
assert isinstance(auth_router, PipelineRouter)
|
|
|
|
|
|
def test_account_pipeline_prepare_has_four_entries():
|
|
assert len(account_pipeline._prepare) == 4
|
|
|
|
|
|
def test_account_auth_list_has_five_entries():
|
|
assert len(account_pipeline._auth) == 5
|
|
|
|
|
|
def test_external_sso_pipeline_prepare_has_five_entries():
|
|
assert len(external_sso_pipeline._prepare) == 5
|
|
|
|
|
|
def test_external_sso_auth_list_has_three_entries():
|
|
# check_scope (unconditional) + 2 When entries
|
|
assert len(external_sso_pipeline._auth) == 3
|
|
|
|
|
|
def test_account_pipeline_has_unconditional_load_account():
|
|
# load_account is the only bare (non-When) entry in account prepare
|
|
non_when = [s for s in account_pipeline._prepare if not isinstance(s, When)]
|
|
assert len(non_when) == 1
|
|
|
|
|
|
def test_external_sso_pipeline_first_prepare_is_build_external_identity():
|
|
from controllers.openapi.auth.prepare import build_external_identity
|
|
assert external_sso_pipeline._prepare[0] is build_external_identity
|
|
|
|
|
|
def test_external_sso_pipeline_remaining_prepare_entries_are_when():
|
|
assert all(isinstance(s, When) for s in external_sso_pipeline._prepare[1:])
|
|
|
|
|
|
def test_first_auth_entry_is_check_scope_in_both_pipelines():
|
|
# check_scope is unconditional (not a When) and comes first in auth
|
|
assert not isinstance(account_pipeline._auth[0], When)
|
|
assert not isinstance(external_sso_pipeline._auth[0], When)
|
|
|
|
|
|
def test_remaining_auth_entries_are_when_for_account():
|
|
assert all(isinstance(s, When) for s in account_pipeline._auth[1:])
|
|
|
|
|
|
def test_remaining_auth_entries_are_when_for_external_sso():
|
|
assert all(isinstance(s, When) for s in external_sso_pipeline._auth[1:])
|
|
|
|
|
|
def test_router_routes_contain_both_token_types():
|
|
assert TokenType.OAUTH_ACCOUNT in auth_router._routes
|
|
assert TokenType.OAUTH_EXTERNAL_SSO in auth_router._routes
|
|
|
|
|
|
def test_external_sso_route_has_ee_required_edition():
|
|
route = auth_router._routes[TokenType.OAUTH_EXTERNAL_SSO]
|
|
assert isinstance(route, PipelineRoute)
|
|
from controllers.openapi.auth.data import Edition
|
|
assert route.required_edition == frozenset({Edition.EE})
|
|
|
|
|
|
def test_account_route_has_no_required_edition():
|
|
route = auth_router._routes[TokenType.OAUTH_ACCOUNT]
|
|
assert isinstance(route, PipelineRoute)
|
|
assert route.required_edition is None
|