diff --git a/app/http/endpoints/api/forms/createinput.go b/app/http/endpoints/api/forms/createinput.go deleted file mode 100644 index 8c6ae1a..0000000 --- a/app/http/endpoints/api/forms/createinput.go +++ /dev/null @@ -1,118 +0,0 @@ -package forms - -import ( - dbclient "github.com/TicketsBot/GoPanel/database" - "github.com/TicketsBot/GoPanel/utils" - "github.com/TicketsBot/database" - "github.com/gin-gonic/gin" - "github.com/rxdn/gdl/objects/interaction/component" - "strconv" -) - -func CreateInput(ctx *gin.Context) { - guildId := ctx.Keys["guildid"].(uint64) - - var data inputCreateBody - if err := ctx.BindJSON(&data); err != nil { - ctx.JSON(400, utils.ErrorJson(err)) - return - } - - // Validate body - if !data.Validate(ctx) { - return - } - - // Parse form ID from URL - formId, err := strconv.Atoi(ctx.Param("form_id")) - if err != nil { - ctx.JSON(400, utils.ErrorStr("Invalid form ID")) - return - } - - // Get form and validate it belongs to the guild - form, ok, err := dbclient.Client.Forms.Get(formId) - if err != nil { - ctx.JSON(500, utils.ErrorJson(err)) - return - } - - if !ok { - ctx.JSON(404, utils.ErrorStr("Form not found")) - return - } - - if form.GuildId != guildId { - ctx.JSON(403, utils.ErrorStr("Form does not belong to this guild")) - return - } - - // Check there are not more than 25 inputs already - // TODO: This is vulnerable to a race condition - inputCount, err := getFormInputCount(formId) - if err != nil { - ctx.JSON(500, utils.ErrorJson(err)) - return - } - - if inputCount >= 5 { - ctx.JSON(400, utils.ErrorStr("A form cannot have more than 5 inputs")) - return - } - - // 2^30 chance of collision - customId, err := utils.RandString(30) - if err != nil { - ctx.JSON(500, utils.ErrorJson(err)) - return - } - - formInputId, err := dbclient.Client.FormInput.Create(formId, customId, uint8(data.Style), data.Label, data.Placeholder, data.Required) - if err != nil { - ctx.JSON(500, utils.ErrorJson(err)) - return - } - - ctx.JSON(200, database.FormInput{ - Id: formInputId, - FormId: formId, - CustomId: customId, - Style: uint8(data.Style), - Label: data.Label, - Placeholder: data.Placeholder, - Required: data.Required, - }) -} - -func (b *inputCreateBody) Validate(ctx *gin.Context) bool { - if b.Style != component.TextStyleShort && b.Style != component.TextStyleParagraph { - ctx.JSON(400, utils.ErrorStr("Invalid style")) - return false - } - - if len(b.Label) == 0 || len(b.Label) > 45 { - ctx.JSON(400, utils.ErrorStr("The input label must be between 1 and 45 characters")) - return false - } - - if b.Placeholder != nil && len(*b.Placeholder) == 0 { - b.Placeholder = nil - } - - if b.Placeholder != nil && len(*b.Placeholder) > 100 { - ctx.JSON(400, utils.ErrorStr("The placeholder cannot be more than 100 characters")) - return false - } - - return true -} - -// TODO: Use select count() -func getFormInputCount(formId int) (int, error) { - inputs, err := dbclient.Client.FormInput.GetInputs(formId) - if err != nil { - return 0, err - } - - return len(inputs), nil -} diff --git a/app/http/endpoints/api/forms/deleteinput.go b/app/http/endpoints/api/forms/deleteinput.go deleted file mode 100644 index c11109d..0000000 --- a/app/http/endpoints/api/forms/deleteinput.go +++ /dev/null @@ -1,63 +0,0 @@ -package forms - -import ( - dbclient "github.com/TicketsBot/GoPanel/database" - "github.com/TicketsBot/GoPanel/utils" - "github.com/gin-gonic/gin" - "strconv" -) - -func DeleteInput(ctx *gin.Context) { - guildId := ctx.Keys["guildid"].(uint64) - - formId, err := strconv.Atoi(ctx.Param("form_id")) - if err != nil { - ctx.JSON(400, utils.ErrorStr("Invalid form ID")) - return - } - - inputId, err := strconv.Atoi(ctx.Param("input_id")) - if err != nil { - ctx.JSON(400, utils.ErrorStr("Invalid form ID")) - return - } - - form, ok, err := dbclient.Client.Forms.Get(formId) - if err != nil { - ctx.JSON(500, utils.ErrorJson(err)) - return - } - - if !ok { - ctx.JSON(404, utils.ErrorStr("Form not found")) - return - } - - if form.GuildId != guildId { - ctx.JSON(403, utils.ErrorStr("Form does not belong to this guild")) - return - } - - input, ok, err := dbclient.Client.FormInput.Get(inputId) - if err != nil { - ctx.JSON(500, utils.ErrorJson(err)) - return - } - - if !ok { - ctx.JSON(404, utils.ErrorStr("Input not found")) - return - } - - if input.FormId != formId { - ctx.JSON(403, utils.ErrorStr("Input does not belong to this form")) - return - } - - if err := dbclient.Client.FormInput.Delete(input.Id, input.FormId); err != nil { - ctx.JSON(500, utils.ErrorJson(err)) - return - } - - ctx.JSON(200, utils.SuccessResponse) -} diff --git a/app/http/endpoints/api/forms/swapinputs.go b/app/http/endpoints/api/forms/swapinputs.go deleted file mode 100644 index 5b37bad..0000000 --- a/app/http/endpoints/api/forms/swapinputs.go +++ /dev/null @@ -1,77 +0,0 @@ -package forms - -import ( - dbclient "github.com/TicketsBot/GoPanel/database" - "github.com/TicketsBot/GoPanel/utils" - "github.com/TicketsBot/database" - "github.com/gin-gonic/gin" - "strconv" -) - -func SwapInput(ctx *gin.Context) { - guildId := ctx.Keys["guildid"].(uint64) - - formId, err := strconv.Atoi(ctx.Param("form_id")) - if err != nil { - ctx.JSON(400, utils.ErrorStr("Invalid form ID")) - return - } - - inputId, err := strconv.Atoi(ctx.Param("input_id")) - if err != nil { - ctx.JSON(400, utils.ErrorStr("Invalid form ID")) - return - } - - form, ok, err := dbclient.Client.Forms.Get(formId) - if err != nil { - ctx.JSON(500, utils.ErrorJson(err)) - return - } - - if !ok { - ctx.JSON(404, utils.ErrorStr("Form not found")) - return - } - - if form.GuildId != guildId { - ctx.JSON(403, utils.ErrorStr("Form does not belong to this guild")) - return - } - - input, ok, err := dbclient.Client.FormInput.Get(inputId) - if err != nil { - ctx.JSON(500, utils.ErrorJson(err)) - return - } - - if !ok { - ctx.JSON(404, utils.ErrorStr("Input not found")) - return - } - - if input.FormId != formId { - ctx.JSON(403, utils.ErrorStr("Input does not belong to this form")) - return - } - - var direction database.InputSwapDirection - { - directionRaw := ctx.Param("direction") - if directionRaw == "up" { - direction = database.SwapDirectionUp - } else if directionRaw == "down" { - direction = database.SwapDirectionDown - } else { - ctx.JSON(400, utils.ErrorStr("Invalid swap direction")) - return - } - } - - if err := dbclient.Client.FormInput.SwapDirection(inputId, formId, direction); err != nil { - ctx.JSON(500, utils.ErrorJson(err)) - return - } - - ctx.JSON(200, utils.SuccessResponse) -} diff --git a/app/http/endpoints/api/forms/updateinput.go b/app/http/endpoints/api/forms/updateinput.go deleted file mode 100644 index 7d2ff9c..0000000 --- a/app/http/endpoints/api/forms/updateinput.go +++ /dev/null @@ -1,84 +0,0 @@ -package forms - -import ( - dbclient "github.com/TicketsBot/GoPanel/database" - "github.com/TicketsBot/GoPanel/utils" - "github.com/TicketsBot/database" - "github.com/gin-gonic/gin" - "strconv" -) - -func UpdateInput(ctx *gin.Context) { - guildId := ctx.Keys["guildid"].(uint64) - - var data inputCreateBody - if err := ctx.BindJSON(&data); err != nil { - ctx.JSON(400, utils.ErrorJson(err)) - return - } - - if !data.Validate(ctx) { - return - } - - formId, err := strconv.Atoi(ctx.Param("form_id")) - if err != nil { - ctx.JSON(400, utils.ErrorStr("Invalid form ID")) - return - } - - inputId, err := strconv.Atoi(ctx.Param("input_id")) - if err != nil { - ctx.JSON(400, utils.ErrorStr("Invalid form ID")) - return - } - - form, ok, err := dbclient.Client.Forms.Get(formId) - if err != nil { - ctx.JSON(500, utils.ErrorJson(err)) - return - } - - if !ok { - ctx.JSON(404, utils.ErrorStr("Form not found")) - return - } - - if form.GuildId != guildId { - ctx.JSON(403, utils.ErrorStr("Form does not belong to this guild")) - return - } - - input, ok, err := dbclient.Client.FormInput.Get(inputId) - if err != nil { - ctx.JSON(500, utils.ErrorJson(err)) - return - } - - if !ok { - ctx.JSON(404, utils.ErrorStr("Input not found")) - return - } - - if input.FormId != formId { - ctx.JSON(403, utils.ErrorStr("Input does not belong to this form")) - return - } - - newInput := database.FormInput{ - Id: inputId, - FormId: formId, - CustomId: input.CustomId, - Style: uint8(data.Style), - Label: data.Label, - Placeholder: data.Placeholder, - Required: data.Required, - } - - if err := dbclient.Client.FormInput.Update(newInput); err != nil { - ctx.JSON(500, utils.ErrorJson(err)) - return - } - - ctx.JSON(200, newInput) -} diff --git a/app/http/endpoints/api/forms/updateinputs.go b/app/http/endpoints/api/forms/updateinputs.go index 58b8dbd..47faf09 100644 --- a/app/http/endpoints/api/forms/updateinputs.go +++ b/app/http/endpoints/api/forms/updateinputs.go @@ -26,6 +26,8 @@ type ( Position int `json:"position" validate:"required,min=1,max=5"` Style component.TextStyleTypes `json:"style" validate:"required,min=1,max=2"` Required bool `json:"required"` + MinLength uint16 `json:"min_length" validate:"min=0,max=1024"` // validator interprets 0 as not set + MaxLength uint16 `json:"max_length" validate:"min=0,max=1024"` } inputUpdateBody struct { @@ -212,6 +214,8 @@ func saveInputs(formId int, data updateInputsBody, existingInputs []database.For Label: input.Label, Placeholder: input.Placeholder, Required: input.Required, + MinLength: &input.MinLength, + MaxLength: &input.MaxLength, } if err := dbclient.Client.FormInput.UpdateTx(tx, wrapped); err != nil { @@ -234,6 +238,8 @@ func saveInputs(formId int, data updateInputsBody, existingInputs []database.For input.Label, input.Placeholder, input.Required, + &input.MinLength, + &input.MaxLength, ); err != nil { return err } diff --git a/app/http/server.go b/app/http/server.go index a754a98..35cf1ea 100644 --- a/app/http/server.go +++ b/app/http/server.go @@ -132,11 +132,7 @@ func StartServer(sm *livechat.SocketManager) { guildAuthApiAdmin.POST("/forms", rl(middleware.RateLimitTypeGuild, 30, time.Hour), api_forms.CreateForm) guildAuthApiAdmin.PATCH("/forms/:form_id", rl(middleware.RateLimitTypeGuild, 30, time.Hour), api_forms.UpdateForm) guildAuthApiAdmin.DELETE("/forms/:form_id", api_forms.DeleteForm) - guildAuthApiAdmin.POST("/forms/:form_id", api_forms.CreateInput) guildAuthApiAdmin.PATCH("/forms/:form_id/inputs", api_forms.UpdateInputs) - guildAuthApiAdmin.PATCH("/forms/:form_id/:input_id", api_forms.UpdateInput) - guildAuthApiAdmin.PATCH("/forms/:form_id/:input_id/:direction", api_forms.SwapInput) - guildAuthApiAdmin.DELETE("/forms/:form_id/:input_id", api_forms.DeleteInput) // Should be a GET, but easier to take a body for development purposes guildAuthApiSupport.POST("/transcripts", diff --git a/frontend/src/components/manage/FormInputRow.svelte b/frontend/src/components/manage/FormInputRow.svelte index 38fd356..f91b6af 100644 --- a/frontend/src/components/manage/FormInputRow.svelte +++ b/frontend/src/components/manage/FormInputRow.svelte @@ -26,17 +26,18 @@
-