Skip to content

Commit

Permalink
♻️ refactor: Update LiveClassController with enhanced comments and cl…
Browse files Browse the repository at this point in the history
…eanup

Updated the LiveClassController to enhance readability and maintainability. Improved documentation comments across all methods and structures to align with Clean Code principles, ensuring each function's purpose and usage are clearly described. This update facilitates easier future modifications and better code comprehension.

Related issue: YJU-OKURA#80
  • Loading branch information
yuminn-k committed Apr 17, 2024
1 parent 44219f4 commit 233c0ff
Showing 1 changed file with 45 additions and 36 deletions.
81 changes: 45 additions & 36 deletions controllers/live_class_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,46 @@ package controllers

import (
"fmt"
"github.com/YJU-OKURA/project_minori-gin-deployment-repo/constants"
"github.com/YJU-OKURA/project_minori-gin-deployment-repo/services"
"github.com/dgrijalva/jwt-go"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
"log"
"net/http"
"os"
"strings"
)

// LiveClassController implements the interface
// LiveClassController handles all web socket operations for live classroom interactions
// including creating a room, starting and stopping screen sharing
type LiveClassController struct {
liveClassService services.LiveClassService
upgrader websocket.Upgrader
}

// RoomResponse encapsulates the response structure for room creation.
type RoomResponse struct {
RoomID string `json:"roomID"`
}

// ScreenShareResponse contains the SDP information necessary for establishing
// a WebRTC connection for screen sharing.
type ScreenShareResponse struct {
SDP string `json:"sdp"`
}

// StandardResponse provides a generic response structure for simple messages.
type StandardResponse struct {
Message string `json:"message"`
}

// ErrorResponse provides a structured error message for API responses.
type ErrorResponse struct {
Error string `json:"error"`
Details string `json:"details,omitempty"`
}

// NewLiveClassController creates a new controller instance with the necessary dependencies.
func NewLiveClassController(service services.LiveClassService) *LiveClassController {
return &LiveClassController{
liveClassService: service,
Expand All @@ -40,10 +64,10 @@ func (c *LiveClassController) CreateRoomHandler() gin.HandlerFunc {
return func(ctx *gin.Context) {
roomID, err := c.liveClassService.CreateRoom()
if err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create room"})
respondWithError(ctx, constants.StatusInternalServerError, "Failed to create room"+err.Error())
return
}
ctx.JSON(http.StatusOK, gin.H{"roomID": roomID})
respondWithSuccess(ctx, constants.StatusOK, RoomResponse{RoomID: roomID})
}
}

Expand All @@ -54,40 +78,40 @@ func (c *LiveClassController) CreateRoomHandler() gin.HandlerFunc {
// @Produce json
// @Param Authorization header string true "Bearer Token"
// @Param roomID path string true "ルームID"
// @Param userID path string true "ユーザーID"
// @Success 200 {object} ScreenShareResponse
// @Failure 400 {object} ErrorResponse
// @Router /live/start-screen-share/{roomID} [get]
func (c *LiveClassController) StartScreenShareHandler() gin.HandlerFunc {
return func(ctx *gin.Context) {
// Retrieve the JWT from the Authorization header
authHeader := ctx.GetHeader("Authorization")

if !authenticateUser(authHeader) {
ctx.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
respondWithError(ctx, constants.StatusUnauthorized, "Unauthorized access")
return
}

roomID := ctx.Param("roomID")
pc, err := c.liveClassService.StartScreenShare(roomID)
userID := ctx.Param("userID")
pc, err := c.liveClassService.StartScreenShare(roomID, userID)
if err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
respondWithError(ctx, constants.StatusInternalServerError, "Screen sharing could not be started: "+err.Error())
return
}

offer, err := pc.CreateOffer(nil)
if err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
pc.Close()
respondWithError(ctx, constants.StatusInternalServerError, "Failed to create offer: "+err.Error())
return
}

err = pc.SetLocalDescription(offer)
if err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
if err := pc.SetLocalDescription(offer); err != nil {
respondWithError(ctx, constants.StatusInternalServerError, "Failed to set local description: "+err.Error())
return
}

ctx.JSON(http.StatusOK, gin.H{"sdp": pc.LocalDescription().SDP})
log.Printf("User %s started screen share in room %s", ctx.MustGet("userID"), roomID)
respondWithSuccess(ctx, constants.StatusOK, ScreenShareResponse{SDP: pc.LocalDescription().SDP})
log.Printf("Screen sharing started by user %s in room %s", userID, roomID)
}
}

Expand All @@ -99,23 +123,25 @@ func (c *LiveClassController) StartScreenShareHandler() gin.HandlerFunc {
// @Produce json
// @Param Authorization header string true "Bearer Token"
// @Param roomID path string true "ルームID"
// @Param userID path string true "ユーザーID"
// @Success 200 {object} StandardResponse
// @Failure 400 {object} ErrorResponse
// @Router /live/stop-screen-share/{roomID} [get]
func (c *LiveClassController) StopScreenShareHandler() gin.HandlerFunc {
return func(ctx *gin.Context) {
roomID := ctx.Param("roomID")
err := c.liveClassService.StopScreenShare(roomID)
userID := ctx.Param("userID")
err := c.liveClassService.StopScreenShare(roomID, userID)
if err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
respondWithError(ctx, constants.StatusInternalServerError, "Screen sharing could not be stopped: "+err.Error())
return
}
ctx.JSON(http.StatusOK, gin.H{"message": "Screen share stopped successfully"})
respondWithSuccess(ctx, constants.StatusOK, StandardResponse{Message: "Screen share stopped successfully"})
}
}

// authenticateUser checks if the provided JWT token is valid and authorized to access the system.
func authenticateUser(tokenString string) bool {
// Assuming the token is in the Authorization header as a Bearer token
tokenString = strings.TrimPrefix(tokenString, "Bearer ")

token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
Expand All @@ -132,20 +158,3 @@ func authenticateUser(tokenString string) bool {

return token.Valid
}

type RoomResponse struct {
RoomID string `json:"roomID"`
}

type ScreenShareResponse struct {
SDP string `json:"sdp"`
}

type StandardResponse struct {
Message string `json:"message"`
}

type ErrorResponse struct {
Error string `json:"error"`
Details string `json:"details,omitempty"`
}

0 comments on commit 233c0ff

Please sign in to comment.