package middlewares import ( "aunefyren/wrapperr/files" "aunefyren/wrapperr/models" "aunefyren/wrapperr/modules" "encoding/base64" "errors" "log" "net/http" "strings" "time" "github.com/gin-gonic/gin" "github.com/google/uuid" ) func AuthMiddleware(admin bool) gin.HandlerFunc { return func(context *gin.Context) { authorizationHeader := context.GetHeader("Authorization") if authorizationHeader == "" { context.JSON(401, gin.H{"error": "Request does not contain an access token"}) context.Abort() return } config, err := files.GetConfig() if err != nil { log.Println("Failed to load Wrapperr settings. Error: " + err.Error()) context.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to load Wrapperr settings."}) context.Abort() return } adminConfig, err := files.GetAdminConfig() if err != nil { log.Println("Failed to load Wrapperr admin settings. Error: " + err.Error()) context.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to load Wrapperr admin settings."}) context.Abort() return } payload, httpStatus, err := AuthGetPayloadFromAuthorization(authorizationHeader, config, adminConfig) if err != nil { log.Println("Failed to get payload from Authorization token. Error: " + err.Error()) context.JSON(httpStatus, gin.H{"error": err.Error()}) context.Abort() return } if admin { adminState, err := files.GetAdminState() if err != nil { log.Println("Failed to load admin state. Error: " + err.Error()) context.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to load admin state."}) context.Abort() return } if !adminState { log.Println("Trying to verify admin session, but admin is not configured.") context.JSON(http.StatusBadRequest, gin.H{"error": "Trying to verify admin session, but admin is not configured."}) context.Abort() return } if !payload.Admin { context.JSON(http.StatusUnauthorized, gin.H{"error": "Session is not an admin session."}) context.Abort() return } } else { if !config.PlexAuth { context.JSON(http.StatusBadRequest, gin.H{"error": "Plex Auth is not enabled in the Wrapperr configuration."}) context.Abort() return } if payload.Admin { context.JSON(http.StatusUnauthorized, gin.H{"error": "Session is an admin session."}) context.Abort() return } if payload.AuthToken == "" { context.JSON(http.StatusUnauthorized, gin.H{"error": "Session does not have a Plex Auth Token."}) context.Abort() return } } context.Next() } } func AuthGetPayloadFromAuthorization(authorizationHeader string, config models.WrapperrConfig, adminConfig models.AdminConfig) (payload models.Payload, httpStatus int, err error) { httpStatus = 200 err = nil payload = models.Payload{} if strings.HasPrefix(strings.ToLower(authorizationHeader), "bearer") { token, found := strings.CutPrefix(authorizationHeader, "Bearer ") if !found { return payload, http.StatusBadRequest, errors.New("'Bearer' part of header not found.") } payloadTwo, err := modules.ParseToken(token, config.PrivateKey) if err != nil { log.Println("Session token not accepted. Error: " + err.Error()) return payload, http.StatusUnauthorized, errors.New("Session token not accepted. Please relog.") } payload = *payloadTwo } else if strings.HasPrefix(strings.ToLower(authorizationHeader), "basic") { token, found := strings.CutPrefix(authorizationHeader, "Basic ") if !found { return payload, http.StatusBadRequest, errors.New("'Basic' part of header not found.") } rawDecodedtoken, err := base64.StdEncoding.DecodeString(token) if err != nil { return payload, http.StatusInternalServerError, errors.New("Failed to decode Base64.") } authParts := strings.Split(string(rawDecodedtoken), ":") if len(authParts) < 2 { log.Println("Failed to parse basic auth header. Error: " + err.Error()) return payload, http.StatusBadRequest, errors.New("Failed to parse basic auth header.") } err = modules.ValidateBasicAuth(authParts[0], authParts[1]) if err != nil { log.Println("Failed to validate basic auth header. Error: " + err.Error()) return payload, http.StatusUnauthorized, errors.New("Failed to validate basic auth header.") } _, payloadTwo, err := modules.CreateTokenTwo(config.PrivateKey, adminConfig.AdminUsername, true, "", time.Now()) if err != nil { log.Println("Failed to create token. Error: " + err.Error()) return payload, http.StatusInternalServerError, errors.New("Failed to create token.") } payload = payloadTwo } return } func GetUserIDFromAuthorizationHeader(authorizationHeader string) (userID uuid.UUID, err error) { err = nil userID = uuid.UUID{} config, err := files.GetConfig() if err != nil { log.Println("Failed to load Wrapperr settings. Error: " + err.Error()) return userID, errors.New("Failed to load Wrapperr settings.") } adminConfig, err := files.GetAdminConfig() if err != nil { log.Println("Failed to load Wrapperr admin settings. Error: " + err.Error()) return userID, errors.New("Failed to load Wrapperr admin settings.") } payload, _, err := AuthGetPayloadFromAuthorization(authorizationHeader, config, adminConfig) if err != nil { log.Println("Failed to get payload from Authorization token. Error: " + err.Error()) return userID, errors.New("Failed to get payload from Authorization token.") } return payload.ID, err }