From 1fd4c4b7b3b6d217a8d19af33aed625aa5c4b189 Mon Sep 17 00:00:00 2001 From: biast12 <53872542+biast12@users.noreply.github.com> Date: Tue, 8 Sep 2026 20:19:54 +0200 Subject: [PATCH 1/2] Add guild ticket limit input and cap checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Expose `ticket_limit` in the guild settings UI with a 0–10 number input and add the field to `GuildSettings` typing. On the backend, enforce the same upper bound in settings validation, fix the panel validation error text to match the actual max (10), and clarify that a panel ticket limit of `0` means no panel-specific limit. The local `database` module replace directive was also enabled in `go.mod`. --- backend/app/http/endpoints/api/panel/panelcreate.go | 2 +- backend/app/http/endpoints/api/panel/panelupdate.go | 2 +- backend/app/http/endpoints/api/panel/validation.go | 2 +- .../app/http/endpoints/api/settings/updatesettings.go | 4 ++++ backend/go.mod | 2 +- frontend/src/pages/manage/GuildSettings.tsx | 10 ++++++++++ frontend/src/types.d.ts | 1 + 7 files changed, 19 insertions(+), 4 deletions(-) diff --git a/backend/app/http/endpoints/api/panel/panelcreate.go b/backend/app/http/endpoints/api/panel/panelcreate.go index 79959ca9..13feb02d 100644 --- a/backend/app/http/endpoints/api/panel/panelcreate.go +++ b/backend/app/http/endpoints/api/panel/panelcreate.go @@ -272,7 +272,7 @@ func CreatePanel(c *gin.Context) { welcomeMessageEmbed = &id } - // If ticket limit is 0, treat it as use global setting + // If ticket limit is 0, this panel has no limit of its own if data.TicketLimit != nil && *data.TicketLimit == 0 { data.TicketLimit = nil } diff --git a/backend/app/http/endpoints/api/panel/panelupdate.go b/backend/app/http/endpoints/api/panel/panelupdate.go index d21e5c4a..4cf93bb9 100644 --- a/backend/app/http/endpoints/api/panel/panelupdate.go +++ b/backend/app/http/endpoints/api/panel/panelupdate.go @@ -260,7 +260,7 @@ func UpdatePanel(c *gin.Context) { } } - // If ticket limit is 0, treat it as use global setting + // If ticket limit is 0, this panel has no limit of its own if data.TicketLimit != nil && *data.TicketLimit == 0 { data.TicketLimit = nil } diff --git a/backend/app/http/endpoints/api/panel/validation.go b/backend/app/http/endpoints/api/panel/validation.go index 8086046e..1ede8be4 100644 --- a/backend/app/http/endpoints/api/panel/validation.go +++ b/backend/app/http/endpoints/api/panel/validation.go @@ -532,7 +532,7 @@ func validateTicketLimit(ctx PanelValidationContext) validation.ValidationFunc { } if *ctx.Data.TicketLimit > 10 { - return validation.NewInvalidInputError("Ticket limit must be at most 11") + return validation.NewInvalidInputError("Ticket limit must be at most 10") } return nil diff --git a/backend/app/http/endpoints/api/settings/updatesettings.go b/backend/app/http/endpoints/api/settings/updatesettings.go index 66c43281..ed13cce8 100644 --- a/backend/app/http/endpoints/api/settings/updatesettings.go +++ b/backend/app/http/endpoints/api/settings/updatesettings.go @@ -106,6 +106,10 @@ func (s *Settings) Validate(ctx context.Context, guildId uint64, premiumTier pre } } + if s.TicketLimit > 10 { + return errors.New("Ticket limit must be between 0 and 10") + } + // Validate colours if len(s.Colours) > len(activeColours) { return errors.New("Invalid colour") diff --git a/backend/go.mod b/backend/go.mod index f95e4759..eae40286 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -2,7 +2,7 @@ module github.com/ticketsbot-cloud/dashboard/backend go 1.26.0 -// replace github.com/TicketsBot-cloud/database => ../../database +replace github.com/TicketsBot-cloud/database => ../../database // replace github.com/TicketsBot-cloud/common => ../../common diff --git a/frontend/src/pages/manage/GuildSettings.tsx b/frontend/src/pages/manage/GuildSettings.tsx index a3bb455a..e7992be1 100644 --- a/frontend/src/pages/manage/GuildSettings.tsx +++ b/frontend/src/pages/manage/GuildSettings.tsx @@ -9,6 +9,7 @@ import Collapsible from "@/components/Collapsible"; import Button from "@/components/Button"; import Select from "@/components/Select"; import Slider from "@/components/Slider"; +import NumberInput from "@/components/NumberInput"; import { useGuildStore } from "@/stores/guild"; import { getGuildById } from "@/stores/auth"; import ColourSelect from "@/components/ColourSelect"; @@ -83,6 +84,7 @@ const GuildSettings: FC = () => { const initialForm: GuildSettings = { language: "en", + ticket_limit: 10, anonymise_dashboard_responses: false, context_menu_permission_level: "0", context_menu_add_sender: false, @@ -190,6 +192,14 @@ const GuildSettings: FC = () => { onChange={(v) => updateField("anonymise_dashboard_responses", v)} label="Anonymise Dashboard Responses" /> + + updateField("ticket_limit", v)} + /> diff --git a/frontend/src/types.d.ts b/frontend/src/types.d.ts index 99fa5d8d..dac7130f 100644 --- a/frontend/src/types.d.ts +++ b/frontend/src/types.d.ts @@ -97,6 +97,7 @@ export interface GuildChannel { } export interface GuildSettings { + ticket_limit: number; context_menu_permission_level: string; context_menu_add_sender: boolean; context_menu_panel?: number; From 5f5bc3042eb04cf9aaacf82ec8b21430cea4186e Mon Sep 17 00:00:00 2001 From: biast12 <53872542+biast12@users.noreply.github.com> Date: Wed, 9 Sep 2026 20:37:05 +0200 Subject: [PATCH 2/2] Bump database Updates the backend to newer TicketsBot common and database module versions and refreshes the transitive Go dependency checksums in go.mod and go.sum. This also disables the local database replace directive so the build uses the published module version, and bumps related x/* packages such as x/sync, x/net, x/sys, x/term, and x/text to compatible releases. --- backend/go.mod | 18 +++++++++--------- backend/go.sum | 32 ++++++++++++++++---------------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/backend/go.mod b/backend/go.mod index eae40286..ceaae53d 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -2,7 +2,7 @@ module github.com/ticketsbot-cloud/dashboard/backend go 1.26.0 -replace github.com/TicketsBot-cloud/database => ../../database +// replace github.com/TicketsBot-cloud/database => ../../database // replace github.com/TicketsBot-cloud/common => ../../common @@ -13,8 +13,8 @@ replace github.com/go-playground/validator/v10 => github.com/go-playground/valid require ( github.com/BurntSushi/toml v1.2.1 github.com/TicketsBot-cloud/archiverclient v0.0.0-20251015181023-f0b66a074704 - github.com/TicketsBot-cloud/common v0.0.0-20260827064609-69131fc7bd3e - github.com/TicketsBot-cloud/database v0.0.0-20260827064551-53077b598c5f + github.com/TicketsBot-cloud/common v0.0.0-20260905165836-38e4090764a4 + github.com/TicketsBot-cloud/database v0.0.0-20260909063631-6804baaaa52b github.com/TicketsBot-cloud/gdl v0.0.0-20260612070331-a3947b410d3e github.com/TicketsBot-cloud/logarchiver v0.0.0-20251018211319-7a7df5cacbdc github.com/TicketsBot-cloud/worker v0.0.0-20260827073646-455b39e53841 @@ -44,7 +44,7 @@ require ( github.com/stretchr/testify v1.12.1 github.com/weppos/publicsuffix-go v0.20.0 go.uber.org/zap v1.28.0 - golang.org/x/sync v0.22.0 + golang.org/x/sync v0.23.0 ) require ( @@ -122,12 +122,12 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v3 v3.0.5 // indirect golang.org/x/arch v0.17.0 // indirect - golang.org/x/crypto v0.55.0 // indirect + golang.org/x/crypto v0.57.0 // indirect golang.org/x/exp v0.0.0-20260824195058-e88cd73687aa // indirect - golang.org/x/net v0.57.0 // indirect - golang.org/x/sys v0.47.0 // indirect - golang.org/x/term v0.45.0 // indirect - golang.org/x/text v0.41.0 // indirect + golang.org/x/net v0.58.0 // indirect + golang.org/x/sys v0.48.0 // indirect + golang.org/x/term v0.46.0 // indirect + golang.org/x/text v0.42.0 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/alexcesaro/statsd.v2 v2.0.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/backend/go.sum b/backend/go.sum index 84457514..b88965db 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -39,10 +39,10 @@ github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0 github.com/ReneKroon/ttlcache v1.6.0/go.mod h1:DG6nbhXKUQhrExfwwLuZUdH7UnRDDRA1IW+nBuCssvs= github.com/TicketsBot-cloud/archiverclient v0.0.0-20251015181023-f0b66a074704 h1:liLfvCrzoJ89DXFHzsd1iK3cyP8s4i0CnZPRFEj53zg= github.com/TicketsBot-cloud/archiverclient v0.0.0-20251015181023-f0b66a074704/go.mod h1:Mux1bEPpOHwRw1wo6Fa6qJLJH9Erk9qv1yAIfLi1Wmw= -github.com/TicketsBot-cloud/common v0.0.0-20260827064609-69131fc7bd3e h1:66mDH3lvotbWSgQXNVbssCvUgy6Yg1mqKl7RmEdr6y4= -github.com/TicketsBot-cloud/common v0.0.0-20260827064609-69131fc7bd3e/go.mod h1:yL+VPSYNVK5gxUkA+fbb0WdTjGfWXnr7ScfL0rwk29g= -github.com/TicketsBot-cloud/database v0.0.0-20260827064551-53077b598c5f h1:5dcXYEUJKRvB+csN5mbTycftijY9NAIhmV4EtuYoNok= -github.com/TicketsBot-cloud/database v0.0.0-20260827064551-53077b598c5f/go.mod h1:HQXAgmNSm7/FmBYwcsa6qpZqMrDhbLoEl+AyqFQ+RwY= +github.com/TicketsBot-cloud/common v0.0.0-20260905165836-38e4090764a4 h1:zcPcJ+03xW9qalqzqllM6j0ZPdhuL+mrtGw8woLrAMo= +github.com/TicketsBot-cloud/common v0.0.0-20260905165836-38e4090764a4/go.mod h1:yL+VPSYNVK5gxUkA+fbb0WdTjGfWXnr7ScfL0rwk29g= +github.com/TicketsBot-cloud/database v0.0.0-20260909063631-6804baaaa52b h1:I7gkfG8EKX9DnfpWrSUlNHBsD1H3EDWpvpL6Yr4OanY= +github.com/TicketsBot-cloud/database v0.0.0-20260909063631-6804baaaa52b/go.mod h1:0fKn7nPX6KeljYNQtGQiuZ5aJ/TczgXvBhnbz+4GEc8= github.com/TicketsBot-cloud/gdl v0.0.0-20260612070331-a3947b410d3e h1:qCibZQmO2rrBFrvn6+oAchPEQ7k/0Izr3ruL5P9aVZU= github.com/TicketsBot-cloud/gdl v0.0.0-20260612070331-a3947b410d3e/go.mod h1:CdwBR2egPtxUXjD2CgC9ZwfuB8dz9HPePM8nuG6dt7Y= github.com/TicketsBot-cloud/logarchiver v0.0.0-20251018211319-7a7df5cacbdc h1:qTLNpCvIqM7UwZ6MdWQ9EztcDsIJfHh+VJdG+ULLEaA= @@ -587,8 +587,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ= -golang.org/x/crypto v0.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M= -golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis= +golang.org/x/crypto v0.57.0 h1:3ZVCjf8Ggz7zneR/EHRVx68Ctf+2pmIMP2UFhh9cC6M= +golang.org/x/crypto v0.57.0/go.mod h1:Fdz0i5U6CoizGwLda9DttjSk6qlZo25zYNtR+ycvuZA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -662,8 +662,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE= -golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU= +golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To= +golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -681,8 +681,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek= -golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sync v0.23.0 h1:KameEIfc1IkluZyXWLn39Wd4tURc6GbCiISGiZm2bQk= +golang.org/x/sync v0.23.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -737,8 +737,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= -golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/sys v0.48.0 h1:bbX/i/6MgT9BVLM9RT1thmxL04yeTAhbEz4SyadbXoo= +golang.org/x/sys v0.48.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -746,8 +746,8 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0= -golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w= +golang.org/x/term v0.46.0 h1:3+OXuTbaKDgwk8jTi3aSLHRlmWqHEUDUtxnbFigO4YE= +golang.org/x/term v0.46.0/go.mod h1:+K02xbkittuwc0Am4abfA3Fc+XRGXkvBXNO88NCXPoc= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -761,8 +761,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8= -golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M= +golang.org/x/text v0.42.0 h1:JbOZXgfeCPU9gacVtYliJqOhD+zhrEqK4LfdpmlUZqI= +golang.org/x/text v0.42.0/go.mod h1:ojzP1Z+2QtioaF8DTtO8K5q7JWVVYwZKenzujK0Zd0E= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=