From 82601a3e8f0dc6d284d581cf6911650e23acedb3 Mon Sep 17 00:00:00 2001 From: Simon Larsen Date: Mon, 1 Jul 2024 14:41:25 +0100 Subject: [PATCH] chore: Disable editing and deleting of probes in ProbePage component This commit disables the editing and deleting functionality for probes in the ProbePage component. The isEditable and isDeleteable props are set to false, preventing users from modifying or removing probes. This change ensures that probes cannot be accidentally modified or deleted, improving the data integrity of the application. --- Dashboard/src/Pages/Settings/ProbeView.tsx | 388 ++++++++++++++++++ Dashboard/src/Pages/Settings/Probes.tsx | 5 +- Dashboard/src/Routes/SettingsRoutes.tsx | 18 + .../Utils/Breadcrumbs/SettingsBreadcrumbs.ts | 6 + Dashboard/src/Utils/PageMap.ts | 3 + Dashboard/src/Utils/RouteMap.ts | 7 + Model/Models/Probe.ts | 7 +- 7 files changed, 431 insertions(+), 3 deletions(-) create mode 100644 Dashboard/src/Pages/Settings/ProbeView.tsx diff --git a/Dashboard/src/Pages/Settings/ProbeView.tsx b/Dashboard/src/Pages/Settings/ProbeView.tsx new file mode 100644 index 0000000000..181a07a8b4 --- /dev/null +++ b/Dashboard/src/Pages/Settings/ProbeView.tsx @@ -0,0 +1,388 @@ +import LabelsElement from "../../Components/Label/Labels"; +import UserElement from "../../Components/User/User"; +import DashboardNavigation from "../../Utils/Navigation"; +import PageMap from "../../Utils/PageMap"; +import ProjectUser from "../../Utils/ProjectUser"; +import RouteMap from "../../Utils/RouteMap"; +import PageComponentProps from "../PageComponentProps"; +import Route from "Common/Types/API/Route"; +import BadDataException from "Common/Types/Exception/BadDataException"; +import ObjectID from "Common/Types/ObjectID"; +import FormFieldSchemaType from "CommonUI/src/Components/Forms/Types/FormFieldSchemaType"; +import ModelDelete from "CommonUI/src/Components/ModelDelete/ModelDelete"; +import CardModelDetail from "CommonUI/src/Components/ModelDetail/CardModelDetail"; +import ModelTable from "CommonUI/src/Components/ModelTable/ModelTable"; +import FieldType from "CommonUI/src/Components/Types/FieldType"; +import Navigation from "CommonUI/src/Utils/Navigation"; +import Label from "Model/Models/Label"; +import Probe from "Model/Models/Probe"; +import ProbeOwnerTeam from "Model/Models/ProbeOwnerTeam"; +import ProbeOwnerUser from "Model/Models/ProbeOwnerUser"; +import User from "Model/Models/User"; +import React, { Fragment, FunctionComponent, ReactElement } from "react"; +import TeamElement from "../../Components/Team/Team"; +import Team from "Model/Models/Team"; +import ResetObjectID from "CommonUI/src/Components/ResetObjectID/ResetObjectID"; + +export enum PermissionType { + AllowPermissions = "AllowPermissions", + BlockPermissions = "BlockPermissions", +} + +const TeamView: FunctionComponent = ( + _props: PageComponentProps, +): ReactElement => { + const modelId: ObjectID = Navigation.getLastParamAsObjectID(); + + return ( + + {/* API Key View */} + + name="Probe Details" + cardProps={{ + title: "Probe Details", + description: "Here are more details for this probe.", + }} + isEditable={true} + formSteps={[ + { + title: "Basic Info", + id: "basic-info", + }, + { + title: "More", + id: "more", + }, + ]} + formFields={[ + { + field: { + name: true, + }, + stepId: "basic-info", + title: "Name", + fieldType: FormFieldSchemaType.Text, + required: true, + placeholder: "internal-probe", + validation: { + minLength: 2, + }, + }, + + { + field: { + description: true, + }, + title: "Description", + stepId: "basic-info", + fieldType: FormFieldSchemaType.LongText, + required: true, + placeholder: "This probe is to monitor all the internal services.", + }, + + { + field: { + iconFile: true, + }, + title: "Probe Logo", + stepId: "basic-info", + fieldType: FormFieldSchemaType.ImageFile, + required: false, + placeholder: "Upload logo", + }, + { + field: { + shouldAutoEnableProbeOnNewMonitors: true, + }, + stepId: "more", + title: "Enable monitoring automatically on new monitors", + fieldType: FormFieldSchemaType.Toggle, + required: false, + }, + { + field: { + labels: true, + }, + + title: "Labels ", + stepId: "more", + description: + "Team members with access to these labels will only be able to access this resource. This is optional and an advanced feature.", + fieldType: FormFieldSchemaType.MultiSelectDropdown, + dropdownModal: { + type: Label, + labelField: "name", + valueField: "_id", + }, + required: false, + placeholder: "Labels", + }, + ]} + modelDetailProps={{ + modelType: Probe, + id: "model-detail-team", + fields: [ + { + field: { + _id: true, + }, + title: "Probe ID", + }, + { + field: { + name: true, + }, + title: "Name", + }, + { + field: { + description: true, + }, + title: "Description", + }, + { + field: { + key: true, + }, + title: "Probe Key", + fieldType: FieldType.HiddenText, + }, + { + field: { + labels: { + name: true, + color: true, + }, + }, + title: "Labels", + fieldType: FieldType.Element, + getElement: (item: Probe): ReactElement => { + return ; + }, + }, + ], + modelId: Navigation.getLastParamAsObjectID(), + }} + /> + + + modelType={ProbeOwnerTeam} + id="table-monitor-owner-team" + name="Probe > Owner Team" + singularName="Team" + isDeleteable={true} + createVerb={"Add"} + isCreateable={true} + isViewable={false} + showViewIdButton={true} + query={{ + probeId: modelId, + projectId: DashboardNavigation.getProjectId()?.toString(), + }} + onBeforeCreate={(item: ProbeOwnerTeam): Promise => { + item.probeId = modelId; + item.projectId = DashboardNavigation.getProjectId()!; + return Promise.resolve(item); + }} + cardProps={{ + title: "Owners (Teams)", + description: + "Here is list of teams that own this probe. They will be alerted when this probe status changes.", + }} + noItemsMessage={"No teams associated with this probe so far."} + formFields={[ + { + field: { + team: true, + }, + title: "Team", + fieldType: FormFieldSchemaType.Dropdown, + required: true, + placeholder: "Select Team", + dropdownModal: { + type: Team, + labelField: "name", + valueField: "_id", + }, + }, + ]} + showRefreshButton={true} + viewPageRoute={Navigation.getCurrentRoute()} + filters={[ + { + field: { + team: true, + }, + type: FieldType.Entity, + title: "Team", + filterEntityType: Team, + filterQuery: { + projectId: DashboardNavigation.getProjectId()?.toString(), + }, + filterDropdownField: { + label: "name", + value: "_id", + }, + }, + { + field: { + createdAt: true, + }, + title: "Owner since", + type: FieldType.Date, + }, + ]} + columns={[ + { + field: { + team: { + name: true, + }, + }, + title: "Team", + type: FieldType.Entity, + getElement: (item: ProbeOwnerTeam): ReactElement => { + if (!item["team"]) { + throw new BadDataException("Team not found"); + } + + return ; + }, + }, + { + field: { + createdAt: true, + }, + title: "Owner since", + type: FieldType.DateTime, + }, + ]} + /> + + + modelType={ProbeOwnerUser} + id="table-monitor-owner-team" + name="Probe > Owner Team" + isDeleteable={true} + singularName="User" + isCreateable={true} + isViewable={false} + showViewIdButton={true} + createVerb={"Add"} + query={{ + probeId: modelId, + projectId: DashboardNavigation.getProjectId()?.toString(), + }} + onBeforeCreate={(item: ProbeOwnerUser): Promise => { + item.probeId = modelId; + item.projectId = DashboardNavigation.getProjectId()!; + return Promise.resolve(item); + }} + cardProps={{ + title: "Owners (Users)", + description: + "Here is list of users that own this probe. They will be alerted when this probe status changes.", + }} + noItemsMessage={"No users associated with this probe so far."} + formFields={[ + { + field: { + user: true, + }, + title: "User", + fieldType: FormFieldSchemaType.Dropdown, + required: true, + placeholder: "Select User", + fetchDropdownOptions: async () => { + return await ProjectUser.fetchProjectUsersAsDropdownOptions( + DashboardNavigation.getProjectId()!, + ); + }, + }, + ]} + showRefreshButton={true} + viewPageRoute={Navigation.getCurrentRoute()} + filters={[ + { + field: { + user: true, + }, + title: "User", + type: FieldType.Entity, + filterEntityType: User, + fetchFilterDropdownOptions: async () => { + return await ProjectUser.fetchProjectUsersAsDropdownOptions( + DashboardNavigation.getProjectId()!, + ); + }, + filterDropdownField: { + label: "name", + value: "_id", + }, + }, + { + field: { + createdAt: true, + }, + title: "Owner since", + type: FieldType.Date, + }, + ]} + columns={[ + { + field: { + user: { + name: true, + email: true, + profilePictureId: true, + }, + }, + title: "User", + type: FieldType.Entity, + getElement: (item: ProbeOwnerUser): ReactElement => { + if (!item["user"]) { + throw new BadDataException("User not found"); + } + + return ; + }, + }, + { + field: { + createdAt: true, + }, + title: "Owner since", + type: FieldType.DateTime, + }, + ]} + /> + + + modelType={Probe} + onUpdateComplete={async () => { + Navigation.reload(); + }} + fieldName={"key"} + title={"Reset Probe Key"} + description={ +

+ Resetting the secret key will generate a new key. Secret is + used to authenticate probe requests. +

+ } + modelId={modelId} + /> + + {/* Delete Probe */} + { + Navigation.navigate(RouteMap[PageMap.SETTINGS_PROBES] as Route); + }} + /> +
+ ); +}; + +export default TeamView; diff --git a/Dashboard/src/Pages/Settings/Probes.tsx b/Dashboard/src/Pages/Settings/Probes.tsx index 6380a67db2..3121bd1e44 100644 --- a/Dashboard/src/Pages/Settings/Probes.tsx +++ b/Dashboard/src/Pages/Settings/Probes.tsx @@ -116,8 +116,9 @@ const ProbePage: FunctionComponent = (): ReactElement => { }} id="probes-table" name="Settings > Probes" - isDeleteable={true} - isEditable={true} + isDeleteable={false} + isEditable={false} + isViewable={true} isCreateable={true} cardProps={{ title: "Custom Probes", diff --git a/Dashboard/src/Routes/SettingsRoutes.tsx b/Dashboard/src/Routes/SettingsRoutes.tsx index ccda1e8fef..5b5b978996 100644 --- a/Dashboard/src/Routes/SettingsRoutes.tsx +++ b/Dashboard/src/Routes/SettingsRoutes.tsx @@ -49,6 +49,12 @@ const SettingsTeamView: LazyExoticComponent> = lazy(() => { return import("../Pages/Settings/TeamView"); }); + +const SettingsProbeView: LazyExoticComponent< + FunctionComponent +> = lazy(() => { + return import("../Pages/Settings/ProbeView"); +}); const SettingsMonitors: LazyExoticComponent> = lazy(() => { return import("../Pages/Settings/MonitorStatus"); @@ -644,6 +650,18 @@ const SettingsRoutes: FunctionComponent = ( } /> + + + + + } + /> ); diff --git a/Dashboard/src/Utils/Breadcrumbs/SettingsBreadcrumbs.ts b/Dashboard/src/Utils/Breadcrumbs/SettingsBreadcrumbs.ts index 67877250c9..657e8d0d86 100644 --- a/Dashboard/src/Utils/Breadcrumbs/SettingsBreadcrumbs.ts +++ b/Dashboard/src/Utils/Breadcrumbs/SettingsBreadcrumbs.ts @@ -129,6 +129,12 @@ export function getSettingsBreadcrumbs(path: string): Array | undefined { "Settings", "Probes", ]), + ...BuildBreadcrumbLinksByTitles(PageMap.SETTINGS_PROBE_VIEW, [ + "Project", + "Settings", + "Probes", + "View Probe", + ]), ...BuildBreadcrumbLinksByTitles(PageMap.SETTINGS_DOMAINS, [ "Project", "Settings", diff --git a/Dashboard/src/Utils/PageMap.ts b/Dashboard/src/Utils/PageMap.ts index bc588cd7e4..5cb089ca4d 100644 --- a/Dashboard/src/Utils/PageMap.ts +++ b/Dashboard/src/Utils/PageMap.ts @@ -170,6 +170,9 @@ enum PageMap { SETTINGS_TEAMS = "SETTINGS_TEAMS", SETTINGS_TEAM_VIEW = "SETTINGS_TEAM_VIEW", + // Probe + SETTINGS_PROBE_VIEW = "SETTINGS_PROBE_VIEW", + // Resource settings. SETTINGS_INCIDENTS_STATE = "SETTINGS_INCIDENTS_STATE", SETTINGS_INCIDENTS_SEVERITY = "SETTINGS_INCIDENTS_SEVERITY", diff --git a/Dashboard/src/Utils/RouteMap.ts b/Dashboard/src/Utils/RouteMap.ts index 58f2b3ebff..aacbeab71c 100644 --- a/Dashboard/src/Utils/RouteMap.ts +++ b/Dashboard/src/Utils/RouteMap.ts @@ -145,6 +145,7 @@ export const SettingsRoutePath: Dictionary = { [PageMap.SETTINGS_BILLING_INVOICES]: "invoices", [PageMap.SETTINGS_USAGE_HISTORY]: "usage-history", [PageMap.SETTINGS_TEAM_VIEW]: `teams/${RouteParams.ModelID}`, + [PageMap.SETTINGS_PROBE_VIEW]: `probes/${RouteParams.ModelID}`, [PageMap.SETTINGS_LABELS]: "labels", [PageMap.SETTINGS_PROBES]: "probes", }; @@ -1016,6 +1017,12 @@ const RouteMap: Dictionary = { }`, ), + [PageMap.SETTINGS_PROBE_VIEW]: new Route( + `/dashboard/${RouteParams.ProjectID}/settings/${ + SettingsRoutePath[PageMap.SETTINGS_PROBE_VIEW] + }`, + ), + // labels. [PageMap.SETTINGS_LABELS]: new Route( `/dashboard/${RouteParams.ProjectID}/settings/${ diff --git a/Model/Models/Probe.ts b/Model/Models/Probe.ts index 3f6f93b3a2..25618de700 100755 --- a/Model/Models/Probe.ts +++ b/Model/Models/Probe.ts @@ -88,7 +88,12 @@ export default class Probe extends BaseModel { Permission.CreateProjectProbe, ], read: [Permission.ProjectOwner, Permission.ProjectAdmin], - update: [], + update: [ + Permission.ProjectOwner, + Permission.ProjectAdmin, + Permission.ProjectMember, + Permission.EditProjectProbe, + ], }) @TableColumn({ required: true,