feat: 화상회의 단계 2 — 권한 분기(생성자=진행자)
방을 처음 만든 사용자를 진행자로 보고, 역할별로 LiveKit 권한을 차등 부여한다.
백엔드
- meeting_rooms 엔티티/마이그레이션: 방 이름(고유)→진행자(host) 보관
- 토큰 발급 시 역할 결정: 방이 없으면 생성자=진행자, 있으면 생성자 일치로 판정
(동시 생성 경쟁은 name unique 충돌 후 재조회로 처리)
- grant 차등: 진행자 roomAdmin+발행/구독, 일반 발행/구독
- 역할을 토큰 metadata({"role":...})에 실어 다른 참여자도 진행자 식별
- 응답에 role 추가
프론트
- useMeeting: role 반환
- ParticipantTile: metadata 파싱 → 진행자 타일에 "진행자" 배지
- MeetingPage: 본인이 진행자면 헤더에 역할 칩 표시
방 목록/예약/참여 제한 UI 는 단계 4 로 분리.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,18 @@ const videoEl = ref<HTMLVideoElement | null>(null)
|
||||
const audioEl = ref<HTMLAudioElement | null>(null)
|
||||
const hasVideo = ref(false)
|
||||
const micOn = ref(false)
|
||||
// 진행자 여부 — 토큰 metadata({"role":"host"})에서 파생
|
||||
const isHost = ref(false)
|
||||
|
||||
// 참여자 metadata 문자열에서 진행자 여부 파싱
|
||||
function parseHost(metadata: string | undefined): boolean {
|
||||
if (!metadata) return false
|
||||
try {
|
||||
return (JSON.parse(metadata) as { role?: string }).role === 'host'
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 표시 이름 — 토큰에 담은 name, 없으면 식별자
|
||||
const displayName = ref(props.participant.name || props.participant.identity)
|
||||
@@ -19,6 +31,7 @@ function sync() {
|
||||
const p = props.participant
|
||||
displayName.value = p.name || p.identity
|
||||
micOn.value = p.isMicrophoneEnabled
|
||||
isHost.value = parseHost(p.metadata)
|
||||
|
||||
const camPub = p.getTrackPublication(Track.Source.Camera)
|
||||
if (camPub?.track && videoEl.value) {
|
||||
@@ -88,6 +101,11 @@ onBeforeUnmount(() => {
|
||||
:title="micOn ? '마이크 켜짐' : '마이크 꺼짐'"
|
||||
>{{ micOn ? '🎙' : '🔇' }}</span>
|
||||
<span class="name">{{ displayName }}{{ props.isLocal ? ' (나)' : '' }}</span>
|
||||
<span
|
||||
v-if="isHost"
|
||||
class="host-badge"
|
||||
title="진행자"
|
||||
>진행자</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -161,4 +179,14 @@ onBeforeUnmount(() => {
|
||||
.meta .mic.off {
|
||||
opacity: 0.6;
|
||||
}
|
||||
.host-badge {
|
||||
flex-shrink: 0;
|
||||
padding: 0.0625rem 0.375rem;
|
||||
border-radius: 0.25rem;
|
||||
background: var(--accent);
|
||||
color: #fff;
|
||||
font-size: 0.625rem;
|
||||
font-weight: 700;
|
||||
line-height: 1.4;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user