From 2fe510eb6fed8cec72fba83505295f2ca3e5dcef Mon Sep 17 00:00:00 2001 From: Stephanie Hingtgen Date: Tue, 21 Jan 2025 07:50:24 -0700 Subject: [PATCH] Dashboards: set max length of message to 500 (#99229) --- pkg/services/dashboards/errors.go | 4 ++++ .../dashboards/service/dashboard_service.go | 4 ++++ .../service/dashboard_service_test.go | 16 +++++++++++++++ .../saving/SaveDashboardForm.tsx | 20 +++++++++++++++++++ public/locales/en-US/grafana.json | 4 ++++ public/locales/pseudo-LOCALE/grafana.json | 4 ++++ 6 files changed, 52 insertions(+) diff --git a/pkg/services/dashboards/errors.go b/pkg/services/dashboards/errors.go index af11c84f652..93f6b1152e0 100644 --- a/pkg/services/dashboards/errors.go +++ b/pkg/services/dashboards/errors.go @@ -70,6 +70,10 @@ var ( Reason: "uid too long, max 40 characters", StatusCode: 400, } + ErrDashboardMessageTooLong = DashboardErr{ + Reason: "message too long, max 500 characters", + StatusCode: 400, + } ErrDashboardCannotSaveProvisionedDashboard = DashboardErr{ Reason: "Cannot save provisioned dashboard", StatusCode: 400, diff --git a/pkg/services/dashboards/service/dashboard_service.go b/pkg/services/dashboards/service/dashboard_service.go index 77df8b33da7..037cf3b53d0 100644 --- a/pkg/services/dashboards/service/dashboard_service.go +++ b/pkg/services/dashboards/service/dashboard_service.go @@ -353,6 +353,10 @@ func (dr *DashboardServiceImpl) BuildSaveDashboardCommand(ctx context.Context, d return nil, dashboards.ErrDashboardTitleEmpty } + if len(dto.Message) > 500 { + return nil, dashboards.ErrDashboardMessageTooLong + } + metrics.MFolderIDsServiceCount.WithLabelValues(metrics.Dashboard).Inc() // nolint:staticcheck if dash.IsFolder && dash.FolderID > 0 { diff --git a/pkg/services/dashboards/service/dashboard_service_test.go b/pkg/services/dashboards/service/dashboard_service_test.go index cada629f1d5..eff505300b6 100644 --- a/pkg/services/dashboards/service/dashboard_service_test.go +++ b/pkg/services/dashboards/service/dashboard_service_test.go @@ -67,6 +67,22 @@ func TestDashboardService(t *testing.T) { } }) + t.Run("Should return validation error if message is too long", func(t *testing.T) { + dto.Dashboard = dashboards.NewDashboard("Dash") + dto.Message = `Here we go, 500+ characters for testing. I'm sorry that you're + having to read this. I spent too long trying to come up with something clever + to say or a funny joke. Unforuntately, nothing came to mind. So instead, I'm + will share this with you, as a form of payment for having to read this: + https://youtu.be/dQw4w9WgXcQ?si=KeoTIpn9tUtQnOBk! Enjoy :) Now lets see if + this test passes or if the result is more exciting than these 500 characters + I wrote. Best of luck to the both of us!` + _, err := service.SaveDashboard(context.Background(), dto, false) + require.Equal(t, err, dashboards.ErrDashboardMessageTooLong) + + // set to a shorter message for the rest of the tests + dto.Message = `message` + }) + t.Run("Should return validation error if folder is named General", func(t *testing.T) { dto.Dashboard = dashboards.NewDashboardFolder("General") _, err := service.SaveDashboard(context.Background(), dto, false) diff --git a/public/app/features/dashboard-scene/saving/SaveDashboardForm.tsx b/public/app/features/dashboard-scene/saving/SaveDashboardForm.tsx index 39933216aa8..7845c4b8ee8 100644 --- a/public/app/features/dashboard-scene/saving/SaveDashboardForm.tsx +++ b/public/app/features/dashboard-scene/saving/SaveDashboardForm.tsx @@ -2,6 +2,7 @@ import { useState } from 'react'; import { selectors } from '@grafana/e2e-selectors'; import { Button, Checkbox, TextArea, Stack, Alert, Box, Field } from '@grafana/ui'; +import { Trans, t } from 'app/core/internationalization'; import { SaveDashboardOptions } from 'app/features/dashboard/components/SaveDashboard/types'; import { DashboardScene } from '../scene/DashboardScene'; @@ -49,7 +50,26 @@ export function SaveDashboardForm({ dashboard, drawer, changeInfo }: Props) { ); + const isMessageTooLongError = (message?: string) => { + return message && message.length > 500; + }; + function renderFooter(error?: Error) { + if (isMessageTooLongError(options.message)) { + const messageLength = options.message?.length ?? 0; + + return ( + +

+ + The message is {{ messageLength }} characters, which exceeds the maximum length of 500 characters. Please + shorten it before saving. + +

+
+ ); + } + if (isVersionMismatchError(error)) { return ( diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index f68a771ff6b..536293a7b70 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -2886,6 +2886,10 @@ "title": "Unable to find application file" }, "save-dashboards": { + "message-length": { + "info": "The message is {{messageLength}} characters, which exceeds the maximum length of 500 characters. Please shorten it before saving.", + "title": "Message too long" + }, "name-exists": { "message-info": "A dashboard with the same name in the selected folder already exists, including recently deleted dashboards.", "message-suggestion": "Please choose a different name or folder.", diff --git a/public/locales/pseudo-LOCALE/grafana.json b/public/locales/pseudo-LOCALE/grafana.json index 88ca996b76a..e016299a6c3 100644 --- a/public/locales/pseudo-LOCALE/grafana.json +++ b/public/locales/pseudo-LOCALE/grafana.json @@ -2886,6 +2886,10 @@ "title": "Ůʼnäþľę ŧő ƒįʼnđ äppľįčäŧįőʼn ƒįľę" }, "save-dashboards": { + "message-length": { + "info": "Ŧĥę męşşäģę įş {{messageLength}} čĥäřäčŧęřş, ŵĥįčĥ ęχčęęđş ŧĥę mäχįmūm ľęʼnģŧĥ őƒ 500 čĥäřäčŧęřş. Pľęäşę şĥőřŧęʼn įŧ þęƒőřę şävįʼnģ.", + "title": "Męşşäģę ŧőő ľőʼnģ" + }, "name-exists": { "message-info": "Å đäşĥþőäřđ ŵįŧĥ ŧĥę şämę ʼnämę įʼn ŧĥę şęľęčŧęđ ƒőľđęř äľřęäđy ęχįşŧş, įʼnčľūđįʼnģ řęčęʼnŧľy đęľęŧęđ đäşĥþőäřđş.", "message-suggestion": "Pľęäşę čĥőőşę ä đįƒƒęřęʼnŧ ʼnämę őř ƒőľđęř.",