hermes/backend/api/controllers/v1/backends/lookup.go
2024-12-23 16:47:35 -05:00

148 lines
3.7 KiB
Go

package backends
import (
"encoding/base64"
"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 BackendLookupRequest struct {
Token string `validate:"required"`
BackendID *uint `json:"id"`
Name *string
Description *string
Backend *string
}
type SanitizedBackend struct {
Name string `json:"name"`
BackendID uint `json:"id"`
OwnerID uint `json:"ownerID"`
Description *string `json:"description"`
Backend string `json:"backend"`
BackendParameters *string `json:"connectionDetails"`
}
type LookupResponse struct {
Success bool `json:"success"`
Data []*SanitizedBackend `json:"data"`
}
func LookupBackend(c *gin.Context) {
var req BackendLookupRequest
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, "backends.visible") {
c.JSON(http.StatusForbidden, gin.H{
"error": "Missing permissions",
})
return
}
backends := []dbcore.Backend{}
queryString := []string{}
queryParameters := []interface{}{}
if req.BackendID != nil {
queryString = append(queryString, "id = ?")
queryParameters = append(queryParameters, req.BackendID)
}
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.Backend != nil {
queryString = append(queryString, "isbot = ?")
queryParameters = append(queryParameters, req.Backend)
}
if err := dbcore.DB.Where(strings.Join(queryString, " AND "), queryParameters...).Find(&backends).Error; err != nil {
log.Warnf("Failed to get backends: %s", err.Error())
c.JSON(http.StatusInternalServerError, gin.H{
"error": "Failed to get backends",
})
return
}
sanitizedBackends := make([]*SanitizedBackend, len(backends))
hasSecretVisibility := permissions.UserHasPermission(user, "backends.secretVis")
for backendIndex, backend := range backends {
sanitizedBackends[backendIndex] = &SanitizedBackend{
BackendID: backend.ID,
OwnerID: backend.UserID,
Name: backend.Name,
Description: backend.Description,
Backend: backend.Backend,
}
if backend.UserID == user.ID || hasSecretVisibility {
backendParametersBytes, err := base64.StdEncoding.DecodeString(backend.BackendParameters)
if err != nil {
log.Warnf("Failed to decode base64 backend parameters: %s", err.Error())
}
backendParameters := string(backendParametersBytes)
sanitizedBackends[backendIndex].BackendParameters = &backendParameters
}
}
c.JSON(http.StatusOK, &LookupResponse{
Success: true,
Data: sanitizedBackends,
})
}