Add host check
This commit is contained in:
parent
dbb440eadf
commit
651073f69f
@ -2,11 +2,13 @@ package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
dbclient "github.com/TicketsBot/GoPanel/database"
|
||||
"github.com/TicketsBot/GoPanel/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type activateIntegrationBody struct {
|
||||
@ -77,6 +79,7 @@ func ActivateIntegrationHandler(ctx *gin.Context) {
|
||||
|
||||
// Since we've checked the length, we can just iterate over the secrets and they're guaranteed to be correct
|
||||
secretMap := make(map[int]string)
|
||||
secretValues := make(map[string]string)
|
||||
for secretName, value := range data.Secrets {
|
||||
if len(value) == 0 || len(value) > 255 {
|
||||
ctx.JSON(400, utils.ErrorStr("Secret values must be between 1 and 255 characters"))
|
||||
@ -90,6 +93,7 @@ func ActivateIntegrationHandler(ctx *gin.Context) {
|
||||
if secret.Name == secretName {
|
||||
found = true
|
||||
secretMap[secret.Id] = value
|
||||
secretValues[secret.Name] = value
|
||||
break inner
|
||||
}
|
||||
}
|
||||
@ -102,7 +106,23 @@ func ActivateIntegrationHandler(ctx *gin.Context) {
|
||||
|
||||
// Validate secrets
|
||||
if integration.Public && integration.Approved && integration.ValidationUrl != nil {
|
||||
res, statusCode, err := utils.SecureProxyClient.DoRequest(http.MethodPost, *integration.ValidationUrl, nil, data.Secrets)
|
||||
integrationHeaders, err := dbclient.Client.CustomIntegrationHeaders.GetByIntegration(integrationId)
|
||||
if err != nil {
|
||||
ctx.JSON(500, utils.ErrorJson(err))
|
||||
return
|
||||
}
|
||||
|
||||
headers := make(map[string]string)
|
||||
for _, header := range integrationHeaders {
|
||||
value := header.Value
|
||||
for key, secret := range secretValues {
|
||||
value = strings.ReplaceAll(value, fmt.Sprintf("%%%s%%", key), secret)
|
||||
}
|
||||
|
||||
headers[header.Name] = value
|
||||
}
|
||||
|
||||
res, statusCode, err := utils.SecureProxyClient.DoRequest(http.MethodPost, *integration.ValidationUrl, headers, secretValues)
|
||||
if err != nil {
|
||||
if statusCode == http.StatusRequestTimeout {
|
||||
ctx.JSON(400, utils.ErrorStr("Secret validation server did not respond in time (contact the integration author)"))
|
||||
|
@ -1,11 +1,13 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"errors"
|
||||
dbclient "github.com/TicketsBot/GoPanel/database"
|
||||
"github.com/TicketsBot/GoPanel/utils"
|
||||
"github.com/TicketsBot/database"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-playground/validator/v10"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type integrationCreateBody struct {
|
||||
@ -68,6 +70,19 @@ func CreateIntegrationHandler(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if data.ValidationUrl != nil {
|
||||
sameHost, err := isSameValidationUrlHost(data.WebhookUrl, *data.ValidationUrl)
|
||||
if err != nil {
|
||||
ctx.JSON(500, utils.ErrorJson(err))
|
||||
return
|
||||
}
|
||||
|
||||
if !sameHost {
|
||||
ctx.JSON(400, utils.ErrorStr("Validation URL must be on the same host as the webhook URL"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
integration, err := dbclient.Client.CustomIntegrations.Create(userId, data.WebhookUrl, data.ValidationUrl, data.Method, data.Name, data.Description, data.ImageUrl, data.PrivacyPolicyUrl)
|
||||
if err != nil {
|
||||
ctx.JSON(500, utils.ErrorJson(err))
|
||||
@ -124,3 +139,14 @@ func CreateIntegrationHandler(ctx *gin.Context) {
|
||||
|
||||
ctx.JSON(200, integration)
|
||||
}
|
||||
|
||||
func isSameValidationUrlHost(webhookUrl, validationUrl string) (bool, error) {
|
||||
webhookStripped := utils.GetUrlHost(strings.ReplaceAll(webhookUrl, "%", ""))
|
||||
validationStripped := utils.GetUrlHost(strings.ReplaceAll(validationUrl, "%", ""))
|
||||
|
||||
if webhookStripped == "Invalid URL" || validationStripped == "Invalid URL" {
|
||||
return false, errors.New("invalid webhook or validation URL")
|
||||
}
|
||||
|
||||
return strings.ToLower(utils.SecondLevelDomain(webhookStripped)) == strings.ToLower(utils.SecondLevelDomain(validationStripped)), nil
|
||||
}
|
@ -88,6 +88,19 @@ func UpdateIntegrationHandler(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if data.ValidationUrl != nil {
|
||||
sameHost, err := isSameValidationUrlHost(data.WebhookUrl, *data.ValidationUrl)
|
||||
if err != nil {
|
||||
ctx.JSON(500, utils.ErrorJson(err))
|
||||
return
|
||||
}
|
||||
|
||||
if !sameHost {
|
||||
ctx.JSON(400, utils.ErrorStr("Validation URL must be on the same host as the webhook URL"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Update integration metadata
|
||||
err = dbclient.Client.CustomIntegrations.Update(database.CustomIntegration{
|
||||
Id: integration.Id,
|
||||
|
@ -79,7 +79,11 @@
|
||||
|
||||
let res = await axios.post(`${API_URL}/api/${guildId}/integrations/${integrationId}`, data);
|
||||
if (res.status !== 204) {
|
||||
notifyError(res.data.error);
|
||||
if (res.data.client_error) {
|
||||
notifyError(`${res.data.error}: ${res.data.client_error}`);
|
||||
} else {
|
||||
notifyError(res.data.error);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user