110 lines
3.9 KiB
Go
110 lines
3.9 KiB
Go
package http
|
|
|
|
import (
|
|
"log"
|
|
"net/http"
|
|
"time"
|
|
|
|
roomv1 "hyapp.local/api/proto/room/v1"
|
|
"hyapp/pkg/appcode"
|
|
"hyapp/pkg/roomid"
|
|
"hyapp/pkg/tencentrtc"
|
|
"hyapp/pkg/xerr"
|
|
"hyapp/services/gateway-service/internal/auth"
|
|
)
|
|
|
|
// issueTencentRTCToken signs Tencent RTC credentials only after room-service confirms presence.
|
|
func (h *Handler) issueTencentRTCToken(writer http.ResponseWriter, request *http.Request) {
|
|
var body struct {
|
|
RoomID string `json:"room_id"`
|
|
}
|
|
|
|
if !decode(writer, request, &body) {
|
|
return
|
|
}
|
|
if !roomid.ValidStringID(body.RoomID) {
|
|
// Token signing repeats room_id validation to fail closed on historical or dirty rooms.
|
|
writeError(writer, request, http.StatusBadRequest, codeInvalidArgument, "invalid argument")
|
|
return
|
|
}
|
|
|
|
userID := auth.UserIDFromContext(request.Context())
|
|
if userID <= 0 {
|
|
// Auth middleware normally blocks this; the handler keeps a defensive guard before signing.
|
|
writeError(writer, request, http.StatusUnauthorized, codeUnauthorized, "unauthorized")
|
|
return
|
|
}
|
|
|
|
rtcConfig := tencentrtc.TokenConfig{
|
|
Enabled: h.tencentRTC.Enabled,
|
|
SDKAppID: h.tencentRTC.SDKAppID,
|
|
SecretKey: h.tencentRTC.SecretKey,
|
|
TTL: h.tencentRTC.UserSigTTL,
|
|
RoomIDType: h.tencentRTC.RoomIDType,
|
|
AppScene: h.tencentRTC.AppScene,
|
|
}
|
|
if err := tencentrtc.ValidateConfig(rtcConfig); err != nil {
|
|
log.Printf("gateway_rtc_token result=config_error request_id=%s user_id=%d room_id=%s reason=%q", requestIDFromContext(request.Context()), userID, body.RoomID, err.Error())
|
|
writeError(writer, request, http.StatusInternalServerError, codeInternalError, "internal error")
|
|
return
|
|
}
|
|
|
|
if h.roomGuardClient == nil {
|
|
// Without room-service presence, gateway cannot safely decide RTC room entry.
|
|
writeError(writer, request, http.StatusBadGateway, codeUpstreamError, "upstream service error")
|
|
return
|
|
}
|
|
|
|
guardResp, err := h.roomGuardClient.VerifyRoomPresence(request.Context(), &roomv1.VerifyRoomPresenceRequest{
|
|
RoomId: body.RoomID,
|
|
UserId: userID,
|
|
RequestId: requestIDFromContext(request.Context()),
|
|
AppCode: appcode.FromContext(request.Context()),
|
|
})
|
|
if err != nil {
|
|
writeRPCError(writer, request, err)
|
|
return
|
|
}
|
|
if guardResp == nil || !guardResp.GetPresent() {
|
|
h.writeRTCPresenceDenied(writer, request, body.RoomID, userID, guardResp)
|
|
return
|
|
}
|
|
|
|
token, err := tencentrtc.GenerateToken(rtcConfig, userID, body.RoomID, timeNow())
|
|
if err != nil {
|
|
log.Printf("gateway_rtc_token result=config_error request_id=%s user_id=%d room_id=%s reason=%q", requestIDFromContext(request.Context()), userID, body.RoomID, err.Error())
|
|
writeError(writer, request, http.StatusInternalServerError, codeInternalError, "internal error")
|
|
return
|
|
}
|
|
|
|
log.Printf("gateway_rtc_token result=issued request_id=%s user_id=%d rtc_user_id=%s room_id=%s str_room_id=%s room_version=%d", requestIDFromContext(request.Context()), userID, token.RTCUserID, body.RoomID, token.StrRoomID, guardResp.GetRoomVersion())
|
|
writeOK(writer, request, token)
|
|
}
|
|
|
|
func (h *Handler) writeRTCPresenceDenied(writer http.ResponseWriter, request *http.Request, targetRoomID string, userID int64, guardResp *roomv1.VerifyRoomPresenceResponse) {
|
|
reason := "not_in_room"
|
|
roomVersion := int64(0)
|
|
if guardResp != nil {
|
|
reason = guardResp.GetReason()
|
|
roomVersion = guardResp.GetRoomVersion()
|
|
}
|
|
|
|
log.Printf("gateway_rtc_token result=denied request_id=%s user_id=%d room_id=%s room_version=%d reason=%q", requestIDFromContext(request.Context()), userID, targetRoomID, roomVersion, reason)
|
|
if reason == "room_not_found" {
|
|
writeError(writer, request, http.StatusNotFound, codeNotFound, "not found")
|
|
return
|
|
}
|
|
if reason == "room_closed" {
|
|
writeError(writer, request, http.StatusConflict, string(xerr.RoomClosed), "room closed")
|
|
return
|
|
}
|
|
|
|
writeError(writer, request, http.StatusForbidden, codePermissionDenied, "permission denied")
|
|
}
|
|
|
|
var timeNow = defaultTimeNow
|
|
|
|
func defaultTimeNow() time.Time {
|
|
return time.Now()
|
|
}
|