Fix live room iframe CSP blocking and add open-in-new-tab fallback.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
f9ab758926
commit
5d741df77b
@ -13,7 +13,8 @@ from app.data import mock_data
|
||||
from app.data import community_data
|
||||
from app.services.recommendations import recommend_destinations
|
||||
from app.services.meetup_live import (
|
||||
build_lounge_chat_url, build_mirotalk_join_url, can_access_meetup, create_mirotalk_room_slug,
|
||||
build_lounge_chat_url, build_mirotalk_join_url, can_access_meetup,
|
||||
create_lounge_channel, create_mirotalk_room_slug,
|
||||
)
|
||||
from app.services.auth import get_user_by_token
|
||||
from app.services import community_store, social_store
|
||||
@ -368,17 +369,23 @@ async def meetup_session(meetup_id: str, authorization: str | None = Header(None
|
||||
mode = meetup.get("mode", "offline")
|
||||
display = (user or {}).get("name", "访客")
|
||||
|
||||
if mode not in ("online", "hybrid"):
|
||||
can_join = False
|
||||
lock = lock or "offline"
|
||||
|
||||
session = MeetupSession(
|
||||
canJoin=can_join and mode in ("online", "hybrid"),
|
||||
canJoin=can_join,
|
||||
lockReason=lock if not can_join else "",
|
||||
displayName=display,
|
||||
mode=mode,
|
||||
mirotalkRoom=meetup.get("mirotalkRoom") or create_mirotalk_room_slug(meetup),
|
||||
loungeChannel=meetup.get("loungeChannel", ""),
|
||||
loungeChannel=meetup.get("loungeChannel") or "",
|
||||
)
|
||||
if session.canJoin:
|
||||
session.videoUrl = build_mirotalk_join_url(meetup, display)
|
||||
session.chatUrl = build_lounge_chat_url(meetup)
|
||||
if not session.loungeChannel:
|
||||
session.loungeChannel = create_lounge_channel(meetup)
|
||||
return session
|
||||
|
||||
|
||||
|
||||
@ -2,11 +2,14 @@ lounge.nomadro.com {
|
||||
encode gzip
|
||||
reverse_proxy https://lounge.nomadro.cn {
|
||||
header_up Host lounge.nomadro.cn
|
||||
header_down -Content-Security-Policy
|
||||
header_down -X-Frame-Options
|
||||
transport http {
|
||||
tls_insecure_skip_verify
|
||||
}
|
||||
}
|
||||
header {
|
||||
Content-Security-Policy "frame-ancestors 'self' https://nomadweb.nomadro.com https://nomadro.cn https://www.nomadro.cn http://localhost:3001 http://127.0.0.1:3001"
|
||||
-X-Frame-Options
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,11 +2,15 @@ mirotalk.nomadro.com {
|
||||
encode gzip
|
||||
reverse_proxy https://mirotalk.nomadro.cn {
|
||||
header_up Host mirotalk.nomadro.cn
|
||||
# Upstream CSP omits nomadweb.nomadro.com; strip so our frame-ancestors win.
|
||||
header_down -Content-Security-Policy
|
||||
header_down -X-Frame-Options
|
||||
transport http {
|
||||
tls_insecure_skip_verify
|
||||
}
|
||||
}
|
||||
header {
|
||||
Content-Security-Policy "frame-ancestors 'self' https://nomadweb.nomadro.com https://nomadro.cn https://www.nomadro.cn http://localhost:3001 http://127.0.0.1:3001"
|
||||
-X-Frame-Options
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,6 +8,13 @@ export const metadata: Metadata = {
|
||||
};
|
||||
|
||||
const LOGS = [
|
||||
{
|
||||
date: "2026-09-04",
|
||||
tag: "直播 iframe 修复",
|
||||
items: [
|
||||
"修复 MiroTalk/Lounge 被上游 CSP 拦截导致直播页空白;可新窗口打开视频/聊天",
|
||||
],
|
||||
},
|
||||
{
|
||||
date: "2026-09-04",
|
||||
tag: "匹配资料 · 报名日历",
|
||||
|
||||
@ -11044,10 +11044,23 @@ a.weather-card:hover {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.live-layout-btns { margin-left: auto; display: flex; gap: 6px; }
|
||||
.live-external-links {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 10px 20px;
|
||||
background: var(--bg-card);
|
||||
border-bottom: var(--border-glass);
|
||||
}
|
||||
.live-iframe-hint {
|
||||
font-size: 0.8rem;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
.live-stage {
|
||||
flex: 1;
|
||||
display: grid;
|
||||
min-height: calc(100vh - 52px);
|
||||
min-height: calc(100vh - 110px);
|
||||
}
|
||||
.live-stage.layout-split { grid-template-columns: 1fr 380px; }
|
||||
.live-stage.layout-video { grid-template-columns: 1fr; }
|
||||
|
||||
@ -112,17 +112,37 @@ export default function MeetupLiveClient({ meetupId, title }: { meetupId: string
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="live-external-links">
|
||||
{session.videoUrl && (
|
||||
<a href={session.videoUrl} target="_blank" rel="noopener noreferrer" className="btn btn-sm btn-primary">
|
||||
{t.live.openVideo}
|
||||
</a>
|
||||
)}
|
||||
{session.chatUrl && (
|
||||
<a href={session.chatUrl} target="_blank" rel="noopener noreferrer" className="btn btn-sm">
|
||||
{t.live.openChat}
|
||||
</a>
|
||||
)}
|
||||
<span className="live-iframe-hint">{t.live.iframeHint}</span>
|
||||
</div>
|
||||
<div className={`live-stage layout-${layout}`}>
|
||||
{(layout === "split" || layout === "video") && session.videoUrl && (
|
||||
<iframe
|
||||
title="video"
|
||||
src={session.videoUrl}
|
||||
className="live-iframe live-video"
|
||||
allow="camera; microphone; display-capture"
|
||||
allow="camera; microphone; display-capture; autoplay; fullscreen"
|
||||
referrerPolicy="no-referrer-when-downgrade"
|
||||
/>
|
||||
)}
|
||||
{(layout === "split" || layout === "chat") && session.chatUrl && (
|
||||
<iframe title="chat" src={session.chatUrl} className="live-iframe live-chat" />
|
||||
<iframe
|
||||
title="chat"
|
||||
src={session.chatUrl}
|
||||
className="live-iframe live-chat"
|
||||
allow="clipboard-write"
|
||||
referrerPolicy="no-referrer-when-downgrade"
|
||||
/>
|
||||
)}
|
||||
{!session.videoUrl && !session.chatUrl && (
|
||||
<div className="notif-empty">
|
||||
|
||||
@ -520,6 +520,9 @@ export const zh = {
|
||||
layoutVideo: "视频",
|
||||
layoutChat: "聊天",
|
||||
linksMissing: "直播链接尚未配置",
|
||||
openVideo: "新窗口打开视频",
|
||||
openChat: "新窗口打开聊天",
|
||||
iframeHint: "若画面空白,请用上方按钮在新窗口打开",
|
||||
},
|
||||
digital: {
|
||||
tag: "🎓 ACADEMY",
|
||||
@ -1795,6 +1798,9 @@ export const en: { [K in keyof typeof zh]: typeof zh[K] extends string ? string
|
||||
layoutVideo: "Video",
|
||||
layoutChat: "Chat",
|
||||
linksMissing: "Live links are not configured yet",
|
||||
openVideo: "Open video in new tab",
|
||||
openChat: "Open chat in new tab",
|
||||
iframeHint: "If the embed is blank, open the rooms in a new tab above",
|
||||
},
|
||||
digital: {
|
||||
tag: "🎓 ACADEMY",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user