hermes/backend/api/controllers/v1/proxies/lookup.go

174 lines
4.7 KiB
Go

package proxies
import (
"fmt"
"net/http"
"strings"
"git.terah.dev/imterah/hermes/api/dbcore"
"git.terah.dev/imterah/hermes/api/jwtcore"
"git.terah.dev/imterah/hermes/api/permissions"
"github.com/charmbracelet/log"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
)
type ProxyLookupRequest struct {
Token string `validate:"required" json:"token"`
Id *uint `json:"id"`
Name *string `json:"name"`
Description *string `json:"description"`
Protocol *string `json:"protocol"`
SourceIP *string `json:"source_ip"`
SourcePort *uint16 `json:"source_port"`
DestinationPort *uint16 `json:"destination_port"`
ProviderID *uint `json:"provider_id"`
AutoStart *bool `json:"auto_start"`
}
type SanitizedProxy struct {
Id uint `json:"id"`
Name string `json:"name"`
Description *string `json:"description"`
Protcol string `json:"protcol"`
SourceIP string `json:"source_ip"`
SourcePort uint16 `json:"source_port"`
DestinationPort uint16 `json:"destination_port"`
ProviderID uint `json:"provider_id"`
AutoStart bool `json:"auto_start"`
}
type ProxyLookupResponse struct {
Success bool `json:"success"`
Data []*SanitizedProxy `json:"data"`
}
func LookupProxy(c *gin.Context) {
var req ProxyLookupRequest
if err := c.BindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": fmt.Sprintf("Failed to parse body: %s", err.Error()),
})
return
}
if err := validator.New().Struct(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": fmt.Sprintf("Failed to validate body: %s", err.Error()),
})
return
}
user, err := jwtcore.GetUserFromJWT(req.Token)
if err != nil {
if err.Error() == "token is expired" || err.Error() == "user does not exist" {
c.JSON(http.StatusForbidden, gin.H{
"error": err.Error(),
})
return
} else {
log.Warnf("Failed to get user from the provided JWT token: %s", err.Error())
c.JSON(http.StatusInternalServerError, gin.H{
"error": "Failed to parse token",
})
return
}
}
if !permissions.UserHasPermission(user, "routes.visible") {
c.JSON(http.StatusForbidden, gin.H{
"error": "Missing permissions",
})
return
}
if *req.Protcol != "tcp" && *req.Protcol != "udp" {
c.JSON(http.StatusBadRequest, gin.H{
"error": "Protocol specified in body must either be 'tcp' or 'udp'",
})
}
proxies := []dbcore.Proxy{}
queryString := []string{}
queryParameters := []interface{}{}
if req.Id != nil {
queryString = append(queryString, "id = ?")
queryParameters = append(queryParameters, req.Id)
}
if req.Name != nil {
queryString = append(queryString, "name = ?")
queryParameters = append(queryParameters, req.Name)
}
if req.Description != nil {
queryString = append(queryString, "description = ?")
queryParameters = append(queryParameters, req.Description)
}
if req.SourceIP != nil {
queryString = append(queryString, "name = ?")
queryParameters = append(queryParameters, req.Name)
}
if req.SourcePort != nil {
queryString = append(queryString, "sourceport = ?")
queryParameters = append(queryParameters, req.SourcePort)
}
if req.DestinationPort != nil {
queryString = append(queryString, "destinationport = ?")
queryParameters = append(queryParameters, req.DestinationPort)
}
if req.ProviderID != nil {
queryString = append(queryString, "backendid = ?")
queryParameters = append(queryParameters, req.ProviderID)
}
if req.AutoStart != nil {
queryString = append(queryString, "autostart = ?")
queryParameters = append(queryParameters, req.AutoStart)
}
if req.Protocol != nil {
queryString = append(queryString, "protocol = ?")
queryParameters = append(queryParameters, req.Protocol)
}
if err := dbcore.DB.Where(strings.Join(queryString, " AND "), queryParameters...).Find(&proxies).Error; err != nil {
log.Warnf("failed to get proxies: %s", err.Error())
c.JSON(http.StatusInternalServerError, gin.H{
"error": "failed to get forward rules",
})
return
}
sanitizedProxies := make([]*SanitizedProxy, len(proxies))
for proxyIndex, proxy := range proxies {
description := ""
if proxy.Description != nil {
description = *proxy.Description
}
sanitizedProxies[proxyIndex] = &SanitizedProxy{
Id: proxy.ID,
Name: proxy.Name,
Description: &description,
Protcol: proxy.Protocol,
SourceIP: proxy.SourceIP,
SourcePort: proxy.SourcePort,
DestinationPort: proxy.DestinationPort,
ProviderID: proxy.BackendID,
AutoStart: proxy.AutoStart,
}
}
c.JSON(http.StatusOK, &ProxyLookupResponse{
Success: true,
Data: sanitizedProxies,
})
}