98 lines
3.4 KiB
Go
98 lines
3.4 KiB
Go
package service
|
||
|
||
import (
|
||
"hyapp/pkg/xerr"
|
||
"hyapp/services/room-service/internal/room/state"
|
||
)
|
||
|
||
// roomRole 是权限矩阵内部使用的收敛角色,不直接信任客户端 JoinRoom.role。
|
||
type roomRole string
|
||
|
||
const (
|
||
// roleOwner 来自 RoomState.OwnerUserID,拥有房间内最高管理权限。
|
||
roleOwner roomRole = "owner"
|
||
// roleAdmin 来自 RoomState.AdminUsers,权限低于 owner。
|
||
roleAdmin roomRole = "admin"
|
||
// roleAudience 是默认兜底角色,包含未登录、未在房间和普通观众。
|
||
roleAudience roomRole = "audience"
|
||
)
|
||
|
||
func actorRole(current *state.RoomState, actorUserID int64) roomRole {
|
||
// 角色权威顺序按当前房间状态固定:owner > admin > audience,不能只看 RoomUser.role 展示字段。
|
||
switch {
|
||
case current == nil || actorUserID <= 0:
|
||
return roleAudience
|
||
case actorUserID == current.OwnerUserID:
|
||
return roleOwner
|
||
case current.AdminUsers[actorUserID]:
|
||
return roleAdmin
|
||
default:
|
||
return roleAudience
|
||
}
|
||
}
|
||
|
||
func requireActiveRoom(current *state.RoomState) error {
|
||
// 当前只有 active 房间可执行管理和麦位命令;CloseRoom 语义后续单独扩展。
|
||
if current == nil || current.Status != state.RoomStatusActive {
|
||
return xerr.New(xerr.Conflict, "room is not active")
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func requireActorPresent(current *state.RoomState, actorUserID int64) error {
|
||
// 管理动作必须来自房间业务 presence;离房后的 admin 不能远程管理房间。
|
||
if _, exists := current.OnlineUsers[actorUserID]; !exists {
|
||
return xerr.New(xerr.PermissionDenied, "permission denied")
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func requireManagerPresent(current *state.RoomState, actorUserID int64) error {
|
||
// 先校验 presence,再校验角色,避免房间外用户凭持久 admin 身份直接操作。
|
||
if err := requireActorPresent(current, actorUserID); err != nil {
|
||
return err
|
||
}
|
||
if !isManagerRole(actorRole(current, actorUserID)) {
|
||
return xerr.New(xerr.PermissionDenied, "permission denied")
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func isManagerRole(role roomRole) bool {
|
||
// 管理角色集合只包含 owner/admin,普通观众只能做自助动作。
|
||
return role == roleOwner || role == roleAdmin
|
||
}
|
||
|
||
func canManageTarget(current *state.RoomState, actorUserID int64, targetUserID int64) error {
|
||
// 目标用户同样按权威状态判定角色,防止客户端伪造 role 绕过管理层级。
|
||
actor := actorRole(current, actorUserID)
|
||
target := actorRole(current, targetUserID)
|
||
if !isManagerRole(actor) {
|
||
return xerr.New(xerr.PermissionDenied, "permission denied")
|
||
}
|
||
if target == roleOwner && actor != roleOwner {
|
||
// admin 不能管理 owner,owner 自操作由具体命令的 self check 再收紧。
|
||
return xerr.New(xerr.PermissionDenied, "permission denied")
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func canSelfOrManageTarget(current *state.RoomState, actorUserID int64, targetUserID int64) error {
|
||
// 自助动作例如自己下麦允许 audience 执行,代操作才进入管理权限矩阵。
|
||
if actorUserID == targetUserID {
|
||
return nil
|
||
}
|
||
return canManageTarget(current, actorUserID, targetUserID)
|
||
}
|
||
|
||
func requireOwnerPresent(current *state.RoomState, actorUserID int64) error {
|
||
// owner 专属命令仍要求 owner 当前在房间业务 presence 内。
|
||
if err := requireActorPresent(current, actorUserID); err != nil {
|
||
return err
|
||
}
|
||
if actorRole(current, actorUserID) != roleOwner {
|
||
return xerr.New(xerr.PermissionDenied, "permission denied")
|
||
}
|
||
return nil
|
||
}
|