1
This commit is contained in:
parent
ce7a203f3d
commit
ca021d541e
@ -11,6 +11,7 @@ from app.web.shared import (
|
||||
SendCodeRequest,
|
||||
VerifyEmailRequest,
|
||||
auth_error,
|
||||
has_active_subscription,
|
||||
require_user,
|
||||
)
|
||||
|
||||
@ -108,6 +109,8 @@ async def api_auth_login(req: LoginRequest, request: Request = None):
|
||||
async def api_auth_me(altcoin_session: str = Cookie(default="")):
|
||||
user = require_user(altcoin_session)
|
||||
sub = auth_db.get_current_subscription(user["id"])
|
||||
if not user.get("local_debug") and not has_active_subscription(user):
|
||||
raise HTTPException(status_code=402, detail="订阅已过期或未开通,请先开通订阅")
|
||||
return {"ok": True, "user": user, "subscription": sub, "subscription_active": bool(sub)}
|
||||
|
||||
|
||||
|
||||
@ -148,10 +148,10 @@ def subscription_redirect():
|
||||
|
||||
|
||||
def has_active_subscription(user) -> bool:
|
||||
if is_local_request():
|
||||
return True
|
||||
if not user:
|
||||
return False
|
||||
if user.get("local_debug"):
|
||||
return True
|
||||
try:
|
||||
if auth_db.is_user_admin(user["id"]):
|
||||
return True
|
||||
|
||||
@ -266,7 +266,6 @@ a { color: inherit; text-decoration: none; }
|
||||
<a class="sidebar-link {% if active_nav == 'subscription' %}active{% endif %}" href="/subscription"><svg class="link-icon"><use href="#svg-subscribe"/></svg>订阅</a>
|
||||
<a class="sidebar-link {% if active_nav == 'referral' %}active{% endif %}" href="/referral"><svg class="link-icon"><use href="#svg-referral"/></svg>邀请</a>
|
||||
<div class="sidebar-section-label admin-link" style="display:none">管理员菜单</div>
|
||||
<a class="sidebar-link admin-link {% if active_nav == 'operations' %}active{% endif %}" href="/operations" target="_blank" rel="noopener" style="display:none"><svg class="link-icon"><use href="#svg-operations"/></svg>运行大屏</a>
|
||||
<a class="sidebar-link admin-link {% if active_nav == 'paper_trading' %}active{% endif %}" href="/paper-trading" style="display:none"><svg class="link-icon"><use href="#svg-paper"/></svg>策略交易</a>
|
||||
<a class="sidebar-link admin-link {% if active_nav == 'live_trading' %}active{% endif %}" href="/live-trading" style="display:none"><svg class="link-icon"><use href="#svg-shield"/></svg>实盘控制台</a>
|
||||
<a class="sidebar-link admin-link {% if active_nav == 'review_center' %}active{% endif %}" href="/review-center" style="display:none"><svg class="link-icon"><use href="#svg-iterate"/></svg>复盘中心</a>
|
||||
@ -328,6 +327,8 @@ window.addEventListener('orientationchange', function(){ setTimeout(setAppViewpo
|
||||
async function loadUser() {
|
||||
try {
|
||||
var resp = await fetch(API + '/api/auth/me');
|
||||
if (resp.status === 401) { window.location.href = '/auth?tab=login'; return; }
|
||||
if (resp.status === 402) { window.location.href = '/subscription?expired=1'; return; }
|
||||
if (!resp.ok) return;
|
||||
var data = await resp.json();
|
||||
currentUser = data.user;
|
||||
|
||||
@ -342,6 +342,7 @@ def test_sidebar_keeps_engineering_pages_in_admin_menu(temp_db):
|
||||
html = resp.text
|
||||
assert "机会中心" in html
|
||||
assert "诊断中心" in html
|
||||
assert 'href="/operations"' not in html
|
||||
assert 'href="/llm-insights"' not in html
|
||||
assert 'href="/data-export"' not in html
|
||||
assert 'href="/strategy"' not in html
|
||||
|
||||
@ -223,12 +223,11 @@ def test_auth_page_hides_internal_requirements_and_has_modern_member_copy(temp_a
|
||||
assert forbidden not in html
|
||||
|
||||
for expected in [
|
||||
"提前发现机会,别在强信号后追高",
|
||||
"登录或开启免费体验",
|
||||
"创建账号",
|
||||
"会员登录",
|
||||
"前往订阅中心",
|
||||
"AlphaX Agent | Crypto",
|
||||
"邮箱验证码",
|
||||
"发送验证码",
|
||||
"AlphaX Agent",
|
||||
]:
|
||||
assert expected in html
|
||||
|
||||
@ -251,17 +250,35 @@ def test_subscription_page_owns_trial_and_plan_flow(temp_auth_db):
|
||||
assert "USDT 订阅已预留表结构" not in html
|
||||
|
||||
|
||||
def test_app_shell_returns_200_for_all_users(temp_auth_db):
|
||||
"""v2: /app 是纯壳页,不校验登录/订阅(鉴权由 JS 调用 /api/auth/me 完成)"""
|
||||
def test_app_shell_requires_active_subscription_for_real_users(temp_auth_db):
|
||||
client = TestClient(web_server.app)
|
||||
# 未登录也能拿到壳页(JS自己判断跳转)
|
||||
assert client.get("/app").status_code == 200
|
||||
assert "AlphaX Agent | Crypto" in client.get("/app").text
|
||||
|
||||
# 登录用户也一样
|
||||
reg = auth_db.register_user("alice@example.com", "StrongPass123")
|
||||
auth_db.verify_email("alice@example.com", reg["verification_code"])
|
||||
login = auth_db.login_user("alice@example.com", "StrongPass123")
|
||||
token = login["token"]
|
||||
client.cookies.set("altcoin_session", token)
|
||||
|
||||
expired_at = (datetime.now() - timedelta(days=1)).isoformat(timespec="seconds")
|
||||
conn = auth_db.get_conn()
|
||||
conn.execute(
|
||||
"""
|
||||
INSERT INTO user_subscription (user_id, plan_code, start_at, end_at, status, source, order_id, created_at, updated_at)
|
||||
VALUES (%s, 'free_trial_1m', %s, %s, 'active', 'test', 0, %s, %s)
|
||||
""",
|
||||
(login["user"]["id"], (datetime.now() - timedelta(days=31)).isoformat(timespec="seconds"), expired_at, expired_at, expired_at),
|
||||
)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
page = client.get("/app", follow_redirects=False)
|
||||
me = client.get("/api/auth/me")
|
||||
|
||||
assert page.status_code == 302
|
||||
assert page.headers["location"] == "/subscription?expired=1"
|
||||
assert me.status_code == 402
|
||||
|
||||
sub = auth_db.claim_free_trial(login["user"]["id"])
|
||||
assert sub["status"] == "active"
|
||||
assert client.get("/app").status_code == 200
|
||||
assert client.get("/api/auth/me").status_code == 200
|
||||
|
||||
Loading…
Reference in New Issue
Block a user