Files
dify/api/tests/unit_tests/controllers/openapi/test_account.py
GareArc b7bd9c19ed feat(api): lift identity + self-revoke to /openapi/v1/account (Phase C.9-10)
GET /v1/me moves to GET /openapi/v1/account. DELETE
/v1/oauth/authorizations/self moves to DELETE
/openapi/v1/account/sessions/self. Both classes (AccountApi,
AccountSessionsSelfApi) are now in controllers/openapi/account.py and
re-registered on service_api_ns at the legacy paths.

service_api/oauth.py is now nothing but legacy re-mount declarations
(20 lines). All in-place handler logic has moved to openapi/. Phase F
will delete the file and the legacy mounts together.

Helper functions (_load_memberships, _pick_default_workspace,
_workspace_payload, _account_payload) move with the AccountApi class.

Plan: docs/superpowers/plans/2026-04-26-openapi-migration.md (in difyctl repo).
2026-04-26 23:50:15 -07:00

74 lines
2.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Phase C steps 910: identity + self-revoke moved to /openapi/v1/account.
Legacy /v1/me + /v1/oauth/authorizations/self stay mounted via
re-registration in service_api/oauth.py.
"""
import builtins
import pytest
from flask import Flask
from flask.views import MethodView
from controllers.openapi import bp as openapi_bp
from controllers.openapi.account import AccountApi, AccountSessionsSelfApi
from controllers.service_api import bp as service_api_bp
if not hasattr(builtins, "MethodView"):
builtins.MethodView = MethodView # type: ignore[attr-defined]
@pytest.fixture
def dual_app() -> Flask:
app = Flask(__name__)
app.config["TESTING"] = True
app.register_blueprint(service_api_bp)
app.register_blueprint(openapi_bp)
return app
def _rule(app: Flask, path: str):
return next(r for r in app.url_map.iter_rules() if r.rule == path)
def test_account_route_registered(dual_app: Flask):
rules = {r.rule for r in dual_app.url_map.iter_rules()}
assert "/openapi/v1/account" in rules
def test_legacy_me_route_registered(dual_app: Flask):
rules = {r.rule for r in dual_app.url_map.iter_rules()}
assert "/v1/me" in rules
def test_account_and_me_dispatch_to_same_class(dual_app: Flask):
new = _rule(dual_app, "/openapi/v1/account")
legacy = _rule(dual_app, "/v1/me")
assert dual_app.view_functions[new.endpoint].view_class is AccountApi
assert dual_app.view_functions[legacy.endpoint].view_class is AccountApi
def test_account_sessions_self_route_registered(dual_app: Flask):
rules = {r.rule for r in dual_app.url_map.iter_rules()}
assert "/openapi/v1/account/sessions/self" in rules
def test_legacy_oauth_authorizations_self_route_registered(dual_app: Flask):
rules = {r.rule for r in dual_app.url_map.iter_rules()}
assert "/v1/oauth/authorizations/self" in rules
def test_sessions_self_paths_dispatch_to_same_class(dual_app: Flask):
new = _rule(dual_app, "/openapi/v1/account/sessions/self")
legacy = _rule(dual_app, "/v1/oauth/authorizations/self")
assert dual_app.view_functions[new.endpoint].view_class is AccountSessionsSelfApi
assert dual_app.view_functions[legacy.endpoint].view_class is AccountSessionsSelfApi
def test_account_methods(dual_app: Flask):
rule = _rule(dual_app, "/openapi/v1/account")
assert "GET" in rule.methods
def test_sessions_self_methods(dual_app: Flask):
rule = _rule(dual_app, "/openapi/v1/account/sessions/self")
assert "DELETE" in rule.methods