mirror of
https://github.com/aunefyren/wrapperr
synced 2025-01-08 15:58:43 +00:00
336 lines
11 KiB
Go
336 lines
11 KiB
Go
package routes
|
|
|
|
import (
|
|
"aunefyren/wrapperr/files"
|
|
"aunefyren/wrapperr/middlewares"
|
|
"aunefyren/wrapperr/models"
|
|
"aunefyren/wrapperr/modules"
|
|
"aunefyren/wrapperr/utilities"
|
|
"log"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// Create shareable link using Plex Auth
|
|
func ApiCreateShareLink(context *gin.Context) {
|
|
configBool, err := files.GetConfigState()
|
|
if err != nil {
|
|
log.Println("Failed to retrieve configuration state. Error: " + err.Error())
|
|
context.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to retrieve configuration state."})
|
|
context.Abort()
|
|
return
|
|
} else if !configBool {
|
|
context.JSON(http.StatusBadRequest, gin.H{"error": "Wrapperr is not configured."})
|
|
context.Abort()
|
|
return
|
|
}
|
|
|
|
config, err := files.GetConfig()
|
|
if err != nil {
|
|
log.Println("Failed to load Wrapperr configuration. Error: " + err.Error())
|
|
context.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to load Wrapperr configuration."})
|
|
context.Abort()
|
|
return
|
|
}
|
|
|
|
if !config.CreateShareLinks {
|
|
log.Panicln("Shareable links are not enabled in the Wrapperr configuration.")
|
|
context.JSON(http.StatusBadRequest, gin.H{"error": "Shareable links are not enabled in the Wrapperr configuration."})
|
|
context.Abort()
|
|
return
|
|
}
|
|
|
|
adminConfig, err := files.GetAdminConfig()
|
|
if err != nil {
|
|
log.Println("Failed to load Wrapperr admin configuration. Error: " + err.Error())
|
|
context.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to load Wrapperr admin configuration."})
|
|
context.Abort()
|
|
return
|
|
}
|
|
|
|
var user_name string
|
|
var user_id int
|
|
|
|
// Try to authorize bearer token from header
|
|
if config.PlexAuth {
|
|
authorizationHeader := context.GetHeader("Authorization")
|
|
payload, httpStatus, err := middlewares.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 err != nil || payload.Admin {
|
|
log.Println("Either error or admin sessions.")
|
|
context.JSON(http.StatusUnauthorized, gin.H{"error": "Failed to authorize request."})
|
|
context.Abort()
|
|
return
|
|
} else {
|
|
plex_object, err := modules.PlexAuthValidateToken(payload.AuthToken, config.ClientKey, config.WrapperrVersion)
|
|
if err != nil {
|
|
log.Println("Could not validate Plex Auth login. Error: " + err.Error())
|
|
context.JSON(http.StatusUnauthorized, gin.H{"error": "Could not validate Plex Auth login."})
|
|
context.Abort()
|
|
return
|
|
}
|
|
|
|
user_name = plex_object.Username
|
|
user_id = plex_object.ID
|
|
}
|
|
}
|
|
|
|
// Read payload from Post input
|
|
var link_payload models.WrapperrShareLinkCreateRequest
|
|
if err := context.ShouldBindJSON(&link_payload); err != nil {
|
|
log.Println("Failed to parse request. Error: " + err.Error())
|
|
context.JSON(http.StatusBadRequest, gin.H{"error": "Failed to parse request."})
|
|
context.Abort()
|
|
return
|
|
}
|
|
|
|
currentTime := time.Now()
|
|
hash_value := uuid.New().String()
|
|
|
|
if !config.PlexAuth {
|
|
user_name = link_payload.Data.User.Name
|
|
user_id = 0
|
|
}
|
|
|
|
link_object := models.WrapperrShareLink{
|
|
Content: link_payload,
|
|
UserID: user_id,
|
|
Hash: hash_value,
|
|
Date: currentTime.Format("2006-01-02"),
|
|
WrapperrVersion: config.WrapperrVersion,
|
|
Expired: false,
|
|
}
|
|
|
|
err = files.SaveLink(&link_object, config.PlexAuth)
|
|
if err != nil {
|
|
log.Println("Failed to save new link. Error: " + err.Error())
|
|
context.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save new link."})
|
|
context.Abort()
|
|
return
|
|
}
|
|
|
|
ipString := utilities.GetOriginIPString(context)
|
|
log.Println("Saved new Wrapperr share link for " + user_name + " (" + strconv.Itoa(user_id) + ")." + ipString)
|
|
|
|
context.JSON(http.StatusCreated, gin.H{"message": "Saved Wrapperr link.", "error": false, "data": strconv.Itoa(user_id) + "-" + hash_value})
|
|
return
|
|
}
|
|
|
|
func ApiWrapperGetStatistics(context *gin.Context) {
|
|
log.Println("New wrap request.")
|
|
|
|
configBool, err := files.GetConfigState()
|
|
if err != nil {
|
|
log.Println("Failed to retrieve configuration state. Error: " + err.Error())
|
|
context.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to retrieve configuration state."})
|
|
context.Abort()
|
|
return
|
|
} else if !configBool {
|
|
context.JSON(http.StatusBadRequest, gin.H{"error": "Wrapperr is not configured."})
|
|
context.Abort()
|
|
return
|
|
}
|
|
|
|
config, err := files.GetConfig()
|
|
if err != nil {
|
|
log.Println("Failed to load Wrapperr configuration. Error: " + err.Error())
|
|
context.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to load Wrapperr configuration."})
|
|
context.Abort()
|
|
return
|
|
}
|
|
|
|
adminConfig, err := files.GetAdminConfig()
|
|
if err != nil {
|
|
log.Println("Failed to load Wrapperr admin configuration. Error: " + err.Error())
|
|
context.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to load Wrapperr admin configuration."})
|
|
context.Abort()
|
|
return
|
|
}
|
|
|
|
// Check connection to every Tautulli server
|
|
err = modules.TautulliTestEveryServer()
|
|
if err != nil {
|
|
log.Println("Failed to test Tautulli server. Error: " + err.Error())
|
|
context.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to test Tautulli server."})
|
|
context.Abort()
|
|
return
|
|
}
|
|
|
|
// Sync users from Tautulli to Wrapperr
|
|
err = modules.TautulliSyncUsersToWrapperr()
|
|
if err != nil {
|
|
log.Println("Failed to sync users from Tautulli. Error: " + err.Error())
|
|
context.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to sync users from Tautulli."})
|
|
context.Abort()
|
|
return
|
|
}
|
|
|
|
var userName string = ""
|
|
var userId int = 0
|
|
var userEmail string = ""
|
|
var userFriendlyName = ""
|
|
var userActive = false
|
|
|
|
// Try to authorize bearer token from header
|
|
authorizationHeader := context.GetHeader("Authorization")
|
|
payload, _, err := middlewares.AuthGetPayloadFromAuthorization(authorizationHeader, config, adminConfig)
|
|
|
|
// If it failed and PlexAuth is enabled, respond with and error
|
|
// If it didn't fail, and PlexAuth is enabled, declare auth as passed
|
|
if err != nil && config.PlexAuth {
|
|
log.Println("Failed to authorize authorization header. Error: " + err.Error())
|
|
context.JSON(http.StatusUnauthorized, gin.H{"error": "Failed to authorize request."})
|
|
context.Abort()
|
|
return
|
|
} else if payload.Admin && config.PlexAuth {
|
|
context.JSON(http.StatusBadRequest, gin.H{"error": "Admin login cannot retrieve statistics."})
|
|
context.Abort()
|
|
return
|
|
}
|
|
|
|
// If the user is not an admin, and PlexAuth is enabled, validate and retrieve details from Plex Token in payload
|
|
if config.PlexAuth {
|
|
plex_object, err := modules.PlexAuthValidateToken(payload.AuthToken, config.ClientKey, config.WrapperrVersion)
|
|
if err != nil {
|
|
log.Println("Could not validate Plex Auth login. Error: " + err.Error())
|
|
context.JSON(http.StatusUnauthorized, gin.H{"error": "Could not validate Plex Auth login."})
|
|
context.Abort()
|
|
return
|
|
}
|
|
|
|
// Set user details from Plex login
|
|
userName = plex_object.Username
|
|
userId = plex_object.ID
|
|
userEmail = plex_object.Email
|
|
|
|
// Check for friendly name using Tautulli
|
|
wrapperrUser, err := modules.UsersGetUser(userId)
|
|
if err != nil {
|
|
log.Println("Failed to find Wrapperr user. Error: " + err.Error())
|
|
context.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to find Wrapperr user."})
|
|
context.Abort()
|
|
return
|
|
}
|
|
|
|
userName = wrapperrUser.User
|
|
userFriendlyName = wrapperrUser.FriendlyName
|
|
userActive = wrapperrUser.Active
|
|
}
|
|
|
|
// Read payload from Post input
|
|
var wrapperr_request models.SearchWrapperrRequest
|
|
if err := context.ShouldBindJSON(&wrapperr_request); err != nil {
|
|
log.Println("Failed to parse request. Error: " + err.Error())
|
|
context.JSON(http.StatusBadRequest, gin.H{"error": "Failed to parse request."})
|
|
context.Abort()
|
|
return
|
|
}
|
|
|
|
// If auth is not passed, caching mode is false, and no PlexIdentity was received, mark it as a bad request
|
|
if wrapperr_request.PlexIdentity == "" && !config.PlexAuth {
|
|
log.Println("Cannot retrieve statistics because search parameter is invalid.")
|
|
context.JSON(http.StatusBadRequest, gin.H{"error": "Invalid search parameter."})
|
|
context.Abort()
|
|
return
|
|
}
|
|
|
|
// If no auth has been passed, caching mode is false, and user is not admin, search for the Plex details using Tautulli and PlexIdentity
|
|
if !config.PlexAuth {
|
|
UserNameFound := false
|
|
|
|
for i := 0; i < len(config.TautulliConfig); i++ {
|
|
new_id, _, _, _, _, err := modules.TautulliGetUserId(config.TautulliConfig[i].TautulliPort, config.TautulliConfig[i].TautulliIP, config.TautulliConfig[i].TautulliHttps, config.TautulliConfig[i].TautulliRoot, config.TautulliConfig[i].TautulliApiKey, strings.TrimSpace(wrapperr_request.PlexIdentity))
|
|
|
|
if err == nil {
|
|
UserNameFound = true
|
|
userId = new_id
|
|
break
|
|
}
|
|
}
|
|
|
|
if !UserNameFound {
|
|
log.Println("Failed to find user in Tautulli.")
|
|
context.JSON(http.StatusInternalServerError, gin.H{"error": "Could not find a matching user."})
|
|
context.Abort()
|
|
return
|
|
}
|
|
|
|
// Check for friendly name using Tautulli
|
|
wrapperrUser, err := modules.UsersGetUser(userId)
|
|
if err != nil {
|
|
log.Println("Failed to find Wrapperr user. Error: " + err.Error())
|
|
context.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to find Wrapperr user."})
|
|
context.Abort()
|
|
return
|
|
}
|
|
|
|
userName = wrapperrUser.User
|
|
userEmail = wrapperrUser.Email
|
|
userFriendlyName = wrapperrUser.FriendlyName
|
|
userActive = wrapperrUser.Active
|
|
}
|
|
|
|
// If no username, email and no user_id has been declared at this point, and Plex Auth is active, something is wrong. Return error.
|
|
if (userName == "" || userEmail == "" || userId == 0) && config.PlexAuth {
|
|
log.Println("At this point the user should have been verified, but username, email or ID is empty.")
|
|
context.JSON(http.StatusInternalServerError, gin.H{"error": "User validation error."})
|
|
context.Abort()
|
|
return
|
|
} else if userName == "" || userEmail == "" {
|
|
log.Println("At this point the user should have been verified, but username or ID is empty.")
|
|
context.JSON(http.StatusInternalServerError, gin.H{"error": "User validation error."})
|
|
context.Abort()
|
|
return
|
|
}
|
|
|
|
if !userActive {
|
|
context.JSON(http.StatusUnauthorized, gin.H{"error": "User is not active."})
|
|
context.Abort()
|
|
return
|
|
}
|
|
|
|
wrapperrReply, _, err := modules.GetWrapperStatistics(userName, userFriendlyName, userId, userEmail, config, adminConfig, false, 0)
|
|
if err != nil {
|
|
log.Println("Failed to get statistics. Error: " + err.Error())
|
|
context.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get statistics."})
|
|
context.Abort()
|
|
return
|
|
}
|
|
|
|
userhistoryEntry := models.WrapperrHistoryEntry{
|
|
Date: time.Now(),
|
|
IP: context.ClientIP(),
|
|
}
|
|
historyEntries := []models.WrapperrHistoryEntry{}
|
|
historyEntries = append(historyEntries, userhistoryEntry)
|
|
|
|
userEntry := models.WrapperrUser{
|
|
User: userName,
|
|
UserID: userId,
|
|
FriendlyName: userFriendlyName,
|
|
Email: userEmail,
|
|
Wrappings: historyEntries,
|
|
}
|
|
|
|
err = modules.UsersSaveUserEntry(userEntry)
|
|
if err != nil {
|
|
log.Println("Failed to save user history entry. Error: " + err.Error())
|
|
context.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save user history entry."})
|
|
context.Abort()
|
|
return
|
|
}
|
|
|
|
context.JSON(http.StatusOK, wrapperrReply)
|
|
return
|
|
}
|