From 0f425cec66ec4d9302ef5c0ad18db7725d05868a Mon Sep 17 00:00:00 2001 From: Tim Wheeler <63284593+TimWheeler-SQUP@users.noreply.github.com> Date: Wed, 1 Apr 2026 21:27:12 +0100 Subject: [PATCH 01/14] New Datto plugin - Alerts+Devices --- .../v1/dataStreams/dattoAllDevices.json | 59 +++++++++++++ .../v1/dataStreams/dattoScopeOpenAlerts.json | 30 +++++++ .../DattoRMM/v1/dataStreams/importSites.json | 82 ++++++++++++++++++ plugins/DattoRMM/v1/icon.png | Bin 0 -> 2437 bytes plugins/DattoRMM/v1/metadata.json | 50 +++++++++++ plugins/DattoRMM/v1/ui.json | 34 ++++++++ 6 files changed, 255 insertions(+) create mode 100644 plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json create mode 100644 plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json create mode 100644 plugins/DattoRMM/v1/dataStreams/importSites.json create mode 100644 plugins/DattoRMM/v1/icon.png create mode 100644 plugins/DattoRMM/v1/metadata.json create mode 100644 plugins/DattoRMM/v1/ui.json diff --git a/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json b/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json new file mode 100644 index 00000000..219920e6 --- /dev/null +++ b/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json @@ -0,0 +1,59 @@ +{ + "name": "dattoAllDevices", + "displayName": "Datto all devices", + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "paging": { + "mode": "nextUrl", + "pageSize": { + "realm": { + "value": "none", + "label": "none" + } + }, + "in": { + "realm": { + "value": "payload", + "label": "payload" + }, + "path": "pageDetails.nextPageUrl" + } + }, + "expandInnerObjects": true, + "endpointPath": "account/devices", + "pathToData": "devices", + "getArgs": [], + "headers": [] + }, + "providesPluginDiagnostics": true, + "timeframes": [ + "last1hour", + "last12hours", + "last24hours", + "last7days", + "last30days", + "thisMonth", + "thisQuarter", + "thisYear", + "lastMonth", + "lastQuarter", + "lastYear", + "none" + ], + "defaultShaping": { + "group": { + "by": [ + [ + "siteName", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + } + } +} \ No newline at end of file diff --git a/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json b/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json new file mode 100644 index 00000000..222e702e --- /dev/null +++ b/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json @@ -0,0 +1,30 @@ +{ + "name": "dattoScopeOpenAlerts", + "displayName": "Datto scope open alerts", + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "paging": { + "mode": "none" + }, + "expandInnerObjects": true, + "endpointPath": "/site/e3e9537b-168c-4ebc-b1ea-f02c7848da21/alerts/open\n", + "pathToData": "alerts", + "getArgs": [], + "headers": [] + }, + "providesPluginDiagnostics": true, + "timeframes": [ + "last1hour", + "last12hours", + "last24hours", + "last7days", + "last30days", + "thisMonth", + "thisQuarter", + "thisYear", + "lastMonth", + "lastQuarter", + "lastYear" + ] +} \ No newline at end of file diff --git a/plugins/DattoRMM/v1/dataStreams/importSites.json b/plugins/DattoRMM/v1/dataStreams/importSites.json new file mode 100644 index 00000000..79ccca44 --- /dev/null +++ b/plugins/DattoRMM/v1/dataStreams/importSites.json @@ -0,0 +1,82 @@ +{ + "name": "importSites", + "displayName": "Import Sites", + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "paging": { + "mode": "nextUrl", + "pageSize": { + "realm": { + "value": "none", + "label": "none" + } + }, + "in": { + "realm": { + "value": "payload", + "label": "payload" + }, + "path": "nextPageUrl" + } + }, + "expandInnerObjects": true, + "endpointPath": "account/sites", + "pathToData": "sites", + "getArgs": [], + "headers": [] + }, + "metadata": [ + { + "shape": [ + "number", + { + "decimalPlaces": 0 + } + ], + "name": "devicesStatus.numberOfDevices" + }, + { + "shape": [ + "number", + { + "decimalPlaces": 0 + } + ], + "name": "devicesStatus.numberOfOfflineDevices" + }, + { + "shape": [ + "number", + { + "decimalPlaces": 0 + } + ], + "name": "devicesStatus.numberOfOnlineDevices" + }, + { + "shape": "string", + "name": "id" + }, + { + "pattern": ".*" + } + ], + "timeframes": [ + "last1hour", + "last12hours", + "last24hours", + "last7days", + "last30days", + "thisMonth", + "thisQuarter", + "thisYear", + "lastMonth", + "lastQuarter", + "lastYear", + "none" + ], + "visibility": { + "type": "hidden" + } +} \ No newline at end of file diff --git a/plugins/DattoRMM/v1/icon.png b/plugins/DattoRMM/v1/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..da4522235a9831e5fa52e5025c8dc6d303da5165 GIT binary patch literal 2437 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 API.", + "validation": { + "required": true, + "pattern": { + "value": "^https?://[^\\s]+$", + "message": "Please enter a valid URL starting with https://" + } + } + }, + { + "type": "text", + "name": "apiKey", + "label": "Client ID", + "placeholder": "Enter your Datto RMM API Client ID", + "validation": { + "required": true + } + }, + { + "type": "password", + "name": "apiSecret", + "label": "Client Secret", + "placeholder": "Enter your Datto RMM API Client Secret", + "validation": { + "required": true + } + } +] From 69e0aebd566df5015f8ba91168733ae1f687eda0 Mon Sep 17 00:00:00 2001 From: Tim Wheeler <63284593+TimWheeler-SQUP@users.noreply.github.com> Date: Thu, 2 Apr 2026 20:44:02 +0100 Subject: [PATCH 02/14] Update metadata --- plugins/DattoRMM/v1/metadata.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/DattoRMM/v1/metadata.json b/plugins/DattoRMM/v1/metadata.json index ecc18b2d..9158ebe2 100644 --- a/plugins/DattoRMM/v1/metadata.json +++ b/plugins/DattoRMM/v1/metadata.json @@ -7,8 +7,8 @@ "type": "community" }, "description": "Datto RMM - Index and search your devices, sites and alerts", - "category": "User Defined", - "type": "hybrid", + "category": "SquaredUp Internal", + "type": "cloud", "schemaVersion": "2.0", "base": { "plugin": "WebAPI", From bbb2265d930129e741e2985574953a1e1bbdea2b Mon Sep 17 00:00:00 2001 From: Tim Wheeler <63284593+TimWheeler-SQUP@users.noreply.github.com> Date: Sun, 5 Apr 2026 13:29:14 +0100 Subject: [PATCH 03/14] Import sites + devices --- plugins/DattoRMM/v1/custom_types.json | 16 ++++++ .../v1/dataStreams/dattoAllDevices.json | 55 +++++++++++++++++++ .../DattoRMM/v1/dataStreams/importSites.json | 27 +++++++-- .../DattoRMM/v1/indexDefinitions/default.json | 43 +++++++++++++++ 4 files changed, 137 insertions(+), 4 deletions(-) create mode 100644 plugins/DattoRMM/v1/custom_types.json create mode 100644 plugins/DattoRMM/v1/indexDefinitions/default.json diff --git a/plugins/DattoRMM/v1/custom_types.json b/plugins/DattoRMM/v1/custom_types.json new file mode 100644 index 00000000..3629a3c3 --- /dev/null +++ b/plugins/DattoRMM/v1/custom_types.json @@ -0,0 +1,16 @@ +[ + { + "icon": "building", + "name": "Datto Site", + "plural": "Sites", + "singular": "Site", + "sourceType": "Datto Site" + }, + { + "icon": "desktop", + "name": "Datto Device", + "plural": "Devices", + "singular": "Device", + "sourceType": "Datto Device" + } +] diff --git a/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json b/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json index 219920e6..d6965d43 100644 --- a/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json +++ b/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json @@ -26,6 +26,61 @@ "getArgs": [], "headers": [] }, + "metadata": [ + { + "shape": "string", + "name": "uid", + "visible": false + }, + { + "displayName": "Hostname", + "shape": "string", + "name": "hostname" + }, + { + "displayName": "Site", + "shape": "string", + "name": "siteName" + }, + { + "displayName": "Device Class", + "shape": "string", + "name": "deviceClass" + }, + { + "displayName": "Operating System", + "shape": "string", + "name": "operatingSystem" + }, + { + "displayName": "Online Status", + "shape": "string", + "name": "onlineStatus" + }, + { + "displayName": "Last Seen", + "shape": "date", + "name": "lastSeen" + }, + { + "displayName": "Internal IP", + "shape": "string", + "name": "intIpAddress" + }, + { + "displayName": "External IP", + "shape": "string", + "name": "extIpAddress" + }, + { + "shape": "string", + "name": "siteUid", + "visible": false + }, + { + "pattern": ".*" + } + ], "providesPluginDiagnostics": true, "timeframes": [ "last1hour", diff --git a/plugins/DattoRMM/v1/dataStreams/importSites.json b/plugins/DattoRMM/v1/dataStreams/importSites.json index 79ccca44..41f24407 100644 --- a/plugins/DattoRMM/v1/dataStreams/importSites.json +++ b/plugins/DattoRMM/v1/dataStreams/importSites.json @@ -28,6 +28,27 @@ }, "metadata": [ { + "shape": "string", + "name": "uid", + "visible": false + }, + { + "displayName": "Name", + "shape": "string", + "name": "name" + }, + { + "displayName": "Description", + "shape": "string", + "name": "description" + }, + { + "displayName": "Notes", + "shape": "string", + "name": "notes" + }, + { + "displayName": "Total Devices", "shape": [ "number", { @@ -37,6 +58,7 @@ "name": "devicesStatus.numberOfDevices" }, { + "displayName": "Offline Devices", "shape": [ "number", { @@ -46,6 +68,7 @@ "name": "devicesStatus.numberOfOfflineDevices" }, { + "displayName": "Online Devices", "shape": [ "number", { @@ -54,10 +77,6 @@ ], "name": "devicesStatus.numberOfOnlineDevices" }, - { - "shape": "string", - "name": "id" - }, { "pattern": ".*" } diff --git a/plugins/DattoRMM/v1/indexDefinitions/default.json b/plugins/DattoRMM/v1/indexDefinitions/default.json new file mode 100644 index 00000000..ffc3b437 --- /dev/null +++ b/plugins/DattoRMM/v1/indexDefinitions/default.json @@ -0,0 +1,43 @@ +{ + "steps": [ + { + "name": "sites", + "dataStream": { "name": "importSites" }, + "timeframe": "none", + "objectMapping": { + "id": "uid", + "name": "name", + "type": { "value": "Datto Site" }, + "properties": [ + "description", + "notes", + { "siteUid": "uid" }, + { "numberOfDevices": "devicesStatus.numberOfDevices" }, + { "numberOfOfflineDevices": "devicesStatus.numberOfOfflineDevices" }, + { "numberOfOnlineDevices": "devicesStatus.numberOfOnlineDevices" } + ] + } + }, + { + "name": "devices", + "dataStream": { "name": "dattoAllDevices" }, + "timeframe": "none", + "objectMapping": { + "id": "uid", + "name": "hostname", + "type": { "value": "Datto Device" }, + "properties": [ + "deviceClass", + "siteName", + { "deviceUid": "uid" }, + { "siteUid": "siteUid" }, + { "operatingSystem": "operatingSystem" }, + { "onlineStatus": "onlineStatus" }, + { "lastSeen": "lastSeen" }, + { "intIpAddress": "intIpAddress" }, + { "extIpAddress": "extIpAddress" } + ] + } + } + ] +} From 0c79064b6a291a99b0138afa9bb8c62e1be5a3e4 Mon Sep 17 00:00:00 2001 From: Tim Wheeler <63284593+TimWheeler-SQUP@users.noreply.github.com> Date: Thu, 9 Apr 2026 21:31:30 +0100 Subject: [PATCH 04/14] Add readme and cspell --- .github/CODEOWNERS | 1 + cspell.json | 1 + plugins/DattoRMM/v1/cspell.json | 7 +++++ .../v1/dataStreams/dattoAllDevices.json | 2 ++ .../v1/dataStreams/dattoScopeOpenAlerts.json | 4 ++- .../DattoRMM/v1/dataStreams/importSites.json | 2 ++ plugins/DattoRMM/v1/docs/README.md | 26 +++++++++++++++++++ plugins/DattoRMM/v1/metadata.json | 19 +++++++++++--- 8 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 plugins/DattoRMM/v1/cspell.json create mode 100644 plugins/DattoRMM/v1/docs/README.md diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 498bd013..9948a76c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -4,6 +4,7 @@ /.github/* @squaredup/community-moderators # Request review from original author +plugins/DattoRMM/* @TimWheeler-SQUP plugins/DigiCert/* @shaswot77 plugins/FantasyPremierLeague/* @TimWheeler-SQUP plugins/GoogleSheets/* @kieranlangton diff --git a/cspell.json b/cspell.json index d1b7aa60..d563d67b 100644 --- a/cspell.json +++ b/cspell.json @@ -1,5 +1,6 @@ { "words": [ + "Datto", "Phare", "rdap", "whois", diff --git a/plugins/DattoRMM/v1/cspell.json b/plugins/DattoRMM/v1/cspell.json new file mode 100644 index 00000000..de5e43a3 --- /dev/null +++ b/plugins/DattoRMM/v1/cspell.json @@ -0,0 +1,7 @@ +{ + "words": [ + "Datto", + "RMM", + "centrastage" + ] +} diff --git a/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json b/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json index d6965d43..cb47b31a 100644 --- a/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json +++ b/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json @@ -1,6 +1,8 @@ { "name": "dattoAllDevices", "displayName": "Datto all devices", + "description": "All devices across all sites", + "tags": ["Devices"], "baseDataSourceName": "httpRequestUnscoped", "config": { "httpMethod": "get", diff --git a/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json b/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json index 222e702e..2edb311e 100644 --- a/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json +++ b/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json @@ -1,6 +1,8 @@ { "name": "dattoScopeOpenAlerts", "displayName": "Datto scope open alerts", + "description": "Open alerts for a specific site", + "tags": ["Alerts"], "baseDataSourceName": "httpRequestUnscoped", "config": { "httpMethod": "get", @@ -8,7 +10,7 @@ "mode": "none" }, "expandInnerObjects": true, - "endpointPath": "/site/e3e9537b-168c-4ebc-b1ea-f02c7848da21/alerts/open\n", + "endpointPath": "site/{{sourceId}}/alerts/open", "pathToData": "alerts", "getArgs": [], "headers": [] diff --git a/plugins/DattoRMM/v1/dataStreams/importSites.json b/plugins/DattoRMM/v1/dataStreams/importSites.json index 41f24407..67e88f06 100644 --- a/plugins/DattoRMM/v1/dataStreams/importSites.json +++ b/plugins/DattoRMM/v1/dataStreams/importSites.json @@ -1,6 +1,8 @@ { "name": "importSites", "displayName": "Import Sites", + "description": "All sites in the account", + "tags": ["Sites"], "baseDataSourceName": "httpRequestUnscoped", "config": { "httpMethod": "get", diff --git a/plugins/DattoRMM/v1/docs/README.md b/plugins/DattoRMM/v1/docs/README.md new file mode 100644 index 00000000..a5225b1f --- /dev/null +++ b/plugins/DattoRMM/v1/docs/README.md @@ -0,0 +1,26 @@ +# Before you start + +[Datto RMM](https://www.datto.com/rmm) is a cloud-based Remote Monitoring and Management (RMM) platform used by Managed Service Providers (MSPs) to monitor, manage and support client devices. This plugin lets you import your Datto RMM sites and devices into SquaredUp, and monitor open alerts scoped to individual sites. + +## What is imported + +The following objects are imported and kept in sync: + +- **Sites** — each managed client site, including device counts (total, online, offline) +- **Devices** — all endpoints across all sites, including hostname, operating system, online status, last seen time, and internal/external IP addresses + +## Data streams + +| Data stream | Description | +|-------------|-------------| +| **All Devices** | Returns all devices across every site. Use this to build fleet-wide views or group by site. | +| **Open Alerts** | Returns open alerts scoped to an imported site object. Use this on site dashboards to surface active issues. | + +## Setup + +You will need the **Base URL**, **API Key** and **API Secret** for your Datto RMM account. + +1. Log in to Datto RMM and navigate to **Setup** > **API** +2. Copy the **API URL** — this is your Base URL (e.g. `https://merlot-api.centrastage.net`) +3. Under **API Users**, create a new API user or select an existing one +4. Copy the **API Key** and **API Secret** for that user diff --git a/plugins/DattoRMM/v1/metadata.json b/plugins/DattoRMM/v1/metadata.json index 9158ebe2..0ca1b2af 100644 --- a/plugins/DattoRMM/v1/metadata.json +++ b/plugins/DattoRMM/v1/metadata.json @@ -6,8 +6,9 @@ "name": "@TimWheeler-SQUP", "type": "community" }, - "description": "Datto RMM - Index and search your devices, sites and alerts", - "category": "SquaredUp Internal", + "description": "Monitor and search your Datto RMM devices, sites and alerts.", + "category": "Monitoring", + "importNotSupported": false, "type": "cloud", "schemaVersion": "2.0", "base": { @@ -46,5 +47,17 @@ "oauth2AuthExtraArgs": [], "oauth2Scope": "" } - } + }, + "links": [ + { + "category": "documentation", + "url": "https://github.com/squaredup/plugins/blob/main/plugins/DattoRMM/v1/docs/README.md", + "label": "Help adding this plugin" + }, + { + "category": "source", + "url": "https://github.com/squaredup/plugins/tree/main/plugins/DattoRMM/v1", + "label": "Repository" + } + ] } \ No newline at end of file From aad3849545cc8ffb9ab41af8cbc225e0e70cf74d Mon Sep 17 00:00:00 2001 From: Tim Wheeler <63284593+TimWheeler-SQUP@users.noreply.github.com> Date: Fri, 10 Apr 2026 16:34:27 +0100 Subject: [PATCH 05/14] move keys to header from post body --- plugins/DattoRMM/v1/metadata.json | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/plugins/DattoRMM/v1/metadata.json b/plugins/DattoRMM/v1/metadata.json index 0ca1b2af..69d494a9 100644 --- a/plugins/DattoRMM/v1/metadata.json +++ b/plugins/DattoRMM/v1/metadata.json @@ -6,7 +6,7 @@ "name": "@TimWheeler-SQUP", "type": "community" }, - "description": "Monitor and search your Datto RMM devices, sites and alerts.", + "description": "Find and monitor your Datto RMM devices, sites and alerts.", "category": "Monitoring", "importNotSupported": false, "type": "cloud", @@ -22,7 +22,13 @@ } ], "queryArgs": [], - "oauth2TokenExtraArgs": [ + "oauth2TokenExtraArgs": [], + "oauth2ClientSecret": "public", + "oauth2ClientSecretLocationDuringAuth": "header", + "authMode": "oauth2", + "oauth2GrantType": "clientCredentials", + "baseUrl": "{{baseUrl}}/api/v2/", + "oauth2TokenExtraHeaders": [ { "value": "password", "key": "grant_type" @@ -36,15 +42,8 @@ "key": "password" } ], - "oauth2ClientSecret": "public", - "oauth2ClientSecretLocationDuringAuth": "header", - "authMode": "oauth2", - "oauth2GrantType": "clientCredentials", - "baseUrl": "{{baseUrl}}/api/v2/", - "oauth2TokenExtraHeaders": [], "oauth2ClientId": "public-client", "oauth2TokenUrl": "{{baseUrl}}/auth/oauth/token", - "oauth2AuthExtraArgs": [], "oauth2Scope": "" } }, From a2d6706e29340aa24b001140b788696818248baa Mon Sep 17 00:00:00 2001 From: Tim Wheeler <63284593+TimWheeler-SQUP@users.noreply.github.com> Date: Fri, 10 Apr 2026 16:44:13 +0100 Subject: [PATCH 06/14] Reverse commit --- plugins/DattoRMM/v1/metadata.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/plugins/DattoRMM/v1/metadata.json b/plugins/DattoRMM/v1/metadata.json index 69d494a9..8b0b0ee3 100644 --- a/plugins/DattoRMM/v1/metadata.json +++ b/plugins/DattoRMM/v1/metadata.json @@ -22,13 +22,7 @@ } ], "queryArgs": [], - "oauth2TokenExtraArgs": [], - "oauth2ClientSecret": "public", - "oauth2ClientSecretLocationDuringAuth": "header", - "authMode": "oauth2", - "oauth2GrantType": "clientCredentials", - "baseUrl": "{{baseUrl}}/api/v2/", - "oauth2TokenExtraHeaders": [ + "oauth2TokenExtraArgs": [ { "value": "password", "key": "grant_type" @@ -42,6 +36,12 @@ "key": "password" } ], + "oauth2ClientSecret": "public", + "oauth2ClientSecretLocationDuringAuth": "header", + "authMode": "oauth2", + "oauth2GrantType": "clientCredentials", + "baseUrl": "{{baseUrl}}/api/v2/", + "oauth2TokenExtraHeaders": [], "oauth2ClientId": "public-client", "oauth2TokenUrl": "{{baseUrl}}/auth/oauth/token", "oauth2Scope": "" From 192e24c388c5a409616ca12142a906e18567ec91 Mon Sep 17 00:00:00 2001 From: Tim Wheeler <63284593+TimWheeler-SQUP@users.noreply.github.com> Date: Fri, 10 Apr 2026 17:08:38 +0100 Subject: [PATCH 07/14] fix paging --- plugins/DattoRMM/v1/dataStreams/importSites.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/DattoRMM/v1/dataStreams/importSites.json b/plugins/DattoRMM/v1/dataStreams/importSites.json index 67e88f06..a34f2859 100644 --- a/plugins/DattoRMM/v1/dataStreams/importSites.json +++ b/plugins/DattoRMM/v1/dataStreams/importSites.json @@ -19,7 +19,7 @@ "value": "payload", "label": "payload" }, - "path": "nextPageUrl" + "path": "pageDetails.nextPageUrl" } }, "expandInnerObjects": true, From 29fb265589f11d1434ee6fbdd886836f32267a23 Mon Sep 17 00:00:00 2001 From: Tim Wheeler <63284593+TimWheeler-SQUP@users.noreply.github.com> Date: Sun, 12 Apr 2026 18:37:40 +0100 Subject: [PATCH 08/14] Add closed alerts data stream --- .gitignore | 7 ++ .../v1/dataStreams/dattoAllDevices.json | 81 +++++++++++++------ .../dataStreams/dattoScopeClosedAlerts.json | 81 +++++++++++++++++++ .../v1/dataStreams/dattoScopeOpenAlerts.json | 77 ++++++++++++++---- .../DattoRMM/v1/dataStreams/importSites.json | 9 +-- plugins/DattoRMM/v1/metadata.json | 2 +- plugins/DattoRMM/v1/ui.json | 10 ++- 7 files changed, 214 insertions(+), 53 deletions(-) create mode 100644 plugins/DattoRMM/v1/dataStreams/dattoScopeClosedAlerts.json diff --git a/.gitignore b/.gitignore index 43ec3040..dd3bb92a 100644 --- a/.gitignore +++ b/.gitignore @@ -81,6 +81,13 @@ logs/ *.local.json +############################################ +# Claude Code (local only, never commit) +############################################ + +*.local.md + + ############################################ # Optional: generated assets ############################################ diff --git a/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json b/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json index cb47b31a..63ed8965 100644 --- a/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json +++ b/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json @@ -1,6 +1,6 @@ { "name": "dattoAllDevices", - "displayName": "Datto all devices", + "displayName": "Devices", "description": "All devices across all sites", "tags": ["Devices"], "baseDataSourceName": "httpRequestUnscoped", @@ -23,7 +23,7 @@ } }, "expandInnerObjects": true, - "endpointPath": "account/devices", + "endpointPath": "api/v2/account/devices", "pathToData": "devices", "getArgs": [], "headers": [] @@ -34,6 +34,21 @@ "name": "uid", "visible": false }, + { + "shape": "string", + "name": "id", + "visible": false + }, + { + "shape": "string", + "name": "siteUid", + "visible": false + }, + { + "shape": "string", + "name": "siteId", + "visible": false + }, { "displayName": "Hostname", "shape": "string", @@ -65,18 +80,47 @@ "name": "lastSeen" }, { - "displayName": "Internal IP", - "shape": "string", - "name": "intIpAddress" + "displayName": "Creation Date", + "shape": ["date", { "timeZone": "Etc/UTC" }], + "name": "creationDate" }, { - "displayName": "External IP", - "shape": "string", - "name": "extIpAddress" + "displayName": "Last Audit Date", + "shape": ["date", { "timeZone": "Etc/UTC" }], + "name": "lastAuditDate" }, { - "shape": "string", - "name": "siteUid", + "displayName": "Patches Approved Pending", + "shape": ["number", { "decimalPlaces": 0 }], + "name": "patchManagement.patchesApprovedPending" + }, + { + "displayName": "Patches Installed", + "shape": ["number", { "decimalPlaces": 0 }], + "name": "patchManagement.patchesInstalled" + }, + { + "displayName": "Patches Not Approved", + "shape": ["number", { "decimalPlaces": 0 }], + "name": "patchManagement.patchesNotApproved" + }, + { + "displayName": "Compliance State", + "name": "softwareComplianceState", + "computed": true, + "valueExpression": "{{ $['softwareStatus'] }}", + "shape": ["state", { + "map": { + "success": ["Compliant"], + "error": ["Not Compliant"], + "warning": [], + "unknown": [], + "unmonitored": [] + } + }] + }, + { + "pattern": "udf.*", "visible": false }, { @@ -97,20 +141,5 @@ "lastQuarter", "lastYear", "none" - ], - "defaultShaping": { - "group": { - "by": [ - [ - "siteName", - "uniqueValues" - ] - ], - "aggregate": [ - { - "type": "count" - } - ] - } - } + ] } \ No newline at end of file diff --git a/plugins/DattoRMM/v1/dataStreams/dattoScopeClosedAlerts.json b/plugins/DattoRMM/v1/dataStreams/dattoScopeClosedAlerts.json new file mode 100644 index 00000000..90bdce68 --- /dev/null +++ b/plugins/DattoRMM/v1/dataStreams/dattoScopeClosedAlerts.json @@ -0,0 +1,81 @@ +{ + "name": "dattoScopeClosedAlerts", + "displayName": "Closed Alerts", + "description": "Resolved alerts for a specific site", + "tags": ["Alerts"], + "baseDataSourceName": "httpRequestScopedSingle", + "matches": { + "sourceType": { + "type": "equals", + "value": "Datto Site" + } + }, + "config": { + "httpMethod": "get", + "paging": { + "mode": "none" + }, + "expandInnerObjects": true, + "endpointPath": "api/v2/site/{{objects[0].siteUid}}/alerts/resolved", + "pathToData": "alerts", + "getArgs": [], + "headers": [] + }, + "metadata": [ + { + "shape": "string", + "name": "uid", + "visible": false + }, + { + "name": "sourceId", + "displayName": "Object ID", + "shape": "string", + "visible": false + }, + { + "displayName": "Alert Message", + "shape": "string", + "name": "alertSourceInfo.alertMessage" + }, + { + "displayName": "Alert Type", + "shape": "string", + "name": "alertSourceInfo.alertTypeDescription" + }, + { + "displayName": "Device", + "shape": "string", + "name": "alertSourceInfo.alertContext.hostname" + }, + { + "shape": "string", + "name": "alertSourceInfo.alertContext.deviceUid", + "visible": false + }, + { + "shape": "string", + "name": "alertSourceInfo.alertContext.siteUid", + "visible": false + }, + { + "displayName": "Priority", + "shape": "string", + "name": "priority" + }, + { + "displayName": "Raised", + "shape": ["date", { "timeZone": "Etc/UTC" }], + "name": "timestamp" + }, + { + "displayName": "Resolved", + "shape": ["date", { "timeZone": "Etc/UTC" }], + "name": "resolvedAt" + }, + { + "pattern": ".*" + } + ], + "timeframes": false +} diff --git a/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json b/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json index 2edb311e..48829f06 100644 --- a/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json +++ b/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json @@ -1,32 +1,77 @@ { "name": "dattoScopeOpenAlerts", - "displayName": "Datto scope open alerts", + "displayName": "Open Alerts", "description": "Open alerts for a specific site", "tags": ["Alerts"], - "baseDataSourceName": "httpRequestUnscoped", + "baseDataSourceName": "httpRequestScopedSingle", + "matches": { + "sourceType": { + "type": "equals", + "value": "Datto Site" + } + }, "config": { "httpMethod": "get", "paging": { "mode": "none" }, "expandInnerObjects": true, - "endpointPath": "site/{{sourceId}}/alerts/open", + "endpointPath": "api/v2/site/{{objects[0].siteUid}}/alerts/open", "pathToData": "alerts", "getArgs": [], "headers": [] }, + "metadata": [ + { + "shape": "string", + "name": "uid", + "visible": false + }, + { + "name": "sourceId", + "displayName": "Object ID", + "shape": "string", + "visible": false + }, + { + "displayName": "Alert Message", + "shape": "string", + "name": "alertSourceInfo.alertMessage" + }, + { + "displayName": "Alert Type", + "shape": "string", + "name": "alertSourceInfo.alertTypeDescription" + }, + { + "displayName": "Device", + "shape": "string", + "name": "alertSourceInfo.alertContext.hostname" + }, + { + "shape": "string", + "name": "alertSourceInfo.alertContext.deviceUid", + "visible": false + }, + { + "shape": "string", + "name": "alertSourceInfo.alertContext.siteUid", + "visible": false + }, + { + "displayName": "Priority", + "shape": "string", + "name": "priority" + }, + { + "displayName": "Timestamp", + "shape": ["date", { "timeZone": "Etc/UTC" }], + "name": "timestamp" + }, + { + "pattern": ".*" + } + ], "providesPluginDiagnostics": true, - "timeframes": [ - "last1hour", - "last12hours", - "last24hours", - "last7days", - "last30days", - "thisMonth", - "thisQuarter", - "thisYear", - "lastMonth", - "lastQuarter", - "lastYear" - ] + "timeframes": false } \ No newline at end of file diff --git a/plugins/DattoRMM/v1/dataStreams/importSites.json b/plugins/DattoRMM/v1/dataStreams/importSites.json index a34f2859..15accd54 100644 --- a/plugins/DattoRMM/v1/dataStreams/importSites.json +++ b/plugins/DattoRMM/v1/dataStreams/importSites.json @@ -1,6 +1,6 @@ { "name": "importSites", - "displayName": "Import Sites", + "displayName": "Sites", "description": "All sites in the account", "tags": ["Sites"], "baseDataSourceName": "httpRequestUnscoped", @@ -23,7 +23,7 @@ } }, "expandInnerObjects": true, - "endpointPath": "account/sites", + "endpointPath": "api/v2/account/sites", "pathToData": "sites", "getArgs": [], "headers": [] @@ -96,8 +96,5 @@ "lastQuarter", "lastYear", "none" - ], - "visibility": { - "type": "hidden" - } + ] } \ No newline at end of file diff --git a/plugins/DattoRMM/v1/metadata.json b/plugins/DattoRMM/v1/metadata.json index 8b0b0ee3..bed35bf5 100644 --- a/plugins/DattoRMM/v1/metadata.json +++ b/plugins/DattoRMM/v1/metadata.json @@ -40,7 +40,7 @@ "oauth2ClientSecretLocationDuringAuth": "header", "authMode": "oauth2", "oauth2GrantType": "clientCredentials", - "baseUrl": "{{baseUrl}}/api/v2/", + "baseUrl": "{{baseUrl}}", "oauth2TokenExtraHeaders": [], "oauth2ClientId": "public-client", "oauth2TokenUrl": "{{baseUrl}}/auth/oauth/token", diff --git a/plugins/DattoRMM/v1/ui.json b/plugins/DattoRMM/v1/ui.json index 5e2dba53..c84554a0 100644 --- a/plugins/DattoRMM/v1/ui.json +++ b/plugins/DattoRMM/v1/ui.json @@ -16,8 +16,9 @@ { "type": "text", "name": "apiKey", - "label": "Client ID", - "placeholder": "Enter your Datto RMM API Client ID", + "label": "API Key", + "placeholder": "Enter your Datto RMM API Key", + "help": "Enter the API Key from the Datto RMM Access Control screen https://rmm.datto.com/help/en/Content/2SETUP/APIv2.htm", "validation": { "required": true } @@ -25,8 +26,9 @@ { "type": "password", "name": "apiSecret", - "label": "Client Secret", - "placeholder": "Enter your Datto RMM API Client Secret", + "label": "API Secret", + "placeholder": "Enter your Datto RMM API Secret Key", + "help": "Enter the API Secret Key from the Datto RMM Access Control screen", "validation": { "required": true } From f39cbfbb72f7783d41c940152e0364db57aa76c7 Mon Sep 17 00:00:00 2001 From: Tim Wheeler <63284593+TimWheeler-SQUP@users.noreply.github.com> Date: Wed, 1 Apr 2026 21:27:12 +0100 Subject: [PATCH 09/14] New Datto plugin - Import, 4 datastreams and Oauth2 setup --- .github/CODEOWNERS | 1 + .gitignore | 7 + cspell.json | 1 + plugins/DattoRMM/v1/cspell.json | 7 + plugins/DattoRMM/v1/custom_types.json | 16 ++ .../v1/dataStreams/dattoAllDevices.json | 145 ++++++++++++++++++ .../dataStreams/dattoScopeClosedAlerts.json | 81 ++++++++++ .../v1/dataStreams/dattoScopeOpenAlerts.json | 77 ++++++++++ .../DattoRMM/v1/dataStreams/importSites.json | 100 ++++++++++++ plugins/DattoRMM/v1/docs/README.md | 26 ++++ plugins/DattoRMM/v1/icon.png | Bin 0 -> 2437 bytes .../DattoRMM/v1/indexDefinitions/default.json | 43 ++++++ plugins/DattoRMM/v1/metadata.json | 62 ++++++++ plugins/DattoRMM/v1/ui.json | 36 +++++ 14 files changed, 602 insertions(+) create mode 100644 plugins/DattoRMM/v1/cspell.json create mode 100644 plugins/DattoRMM/v1/custom_types.json create mode 100644 plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json create mode 100644 plugins/DattoRMM/v1/dataStreams/dattoScopeClosedAlerts.json create mode 100644 plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json create mode 100644 plugins/DattoRMM/v1/dataStreams/importSites.json create mode 100644 plugins/DattoRMM/v1/docs/README.md create mode 100644 plugins/DattoRMM/v1/icon.png create mode 100644 plugins/DattoRMM/v1/indexDefinitions/default.json create mode 100644 plugins/DattoRMM/v1/metadata.json create mode 100644 plugins/DattoRMM/v1/ui.json diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 498bd013..9948a76c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -4,6 +4,7 @@ /.github/* @squaredup/community-moderators # Request review from original author +plugins/DattoRMM/* @TimWheeler-SQUP plugins/DigiCert/* @shaswot77 plugins/FantasyPremierLeague/* @TimWheeler-SQUP plugins/GoogleSheets/* @kieranlangton diff --git a/.gitignore b/.gitignore index 43ec3040..dd3bb92a 100644 --- a/.gitignore +++ b/.gitignore @@ -81,6 +81,13 @@ logs/ *.local.json +############################################ +# Claude Code (local only, never commit) +############################################ + +*.local.md + + ############################################ # Optional: generated assets ############################################ diff --git a/cspell.json b/cspell.json index d1b7aa60..d563d67b 100644 --- a/cspell.json +++ b/cspell.json @@ -1,5 +1,6 @@ { "words": [ + "Datto", "Phare", "rdap", "whois", diff --git a/plugins/DattoRMM/v1/cspell.json b/plugins/DattoRMM/v1/cspell.json new file mode 100644 index 00000000..de5e43a3 --- /dev/null +++ b/plugins/DattoRMM/v1/cspell.json @@ -0,0 +1,7 @@ +{ + "words": [ + "Datto", + "RMM", + "centrastage" + ] +} diff --git a/plugins/DattoRMM/v1/custom_types.json b/plugins/DattoRMM/v1/custom_types.json new file mode 100644 index 00000000..3629a3c3 --- /dev/null +++ b/plugins/DattoRMM/v1/custom_types.json @@ -0,0 +1,16 @@ +[ + { + "icon": "building", + "name": "Datto Site", + "plural": "Sites", + "singular": "Site", + "sourceType": "Datto Site" + }, + { + "icon": "desktop", + "name": "Datto Device", + "plural": "Devices", + "singular": "Device", + "sourceType": "Datto Device" + } +] diff --git a/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json b/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json new file mode 100644 index 00000000..63ed8965 --- /dev/null +++ b/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json @@ -0,0 +1,145 @@ +{ + "name": "dattoAllDevices", + "displayName": "Devices", + "description": "All devices across all sites", + "tags": ["Devices"], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "paging": { + "mode": "nextUrl", + "pageSize": { + "realm": { + "value": "none", + "label": "none" + } + }, + "in": { + "realm": { + "value": "payload", + "label": "payload" + }, + "path": "pageDetails.nextPageUrl" + } + }, + "expandInnerObjects": true, + "endpointPath": "api/v2/account/devices", + "pathToData": "devices", + "getArgs": [], + "headers": [] + }, + "metadata": [ + { + "shape": "string", + "name": "uid", + "visible": false + }, + { + "shape": "string", + "name": "id", + "visible": false + }, + { + "shape": "string", + "name": "siteUid", + "visible": false + }, + { + "shape": "string", + "name": "siteId", + "visible": false + }, + { + "displayName": "Hostname", + "shape": "string", + "name": "hostname" + }, + { + "displayName": "Site", + "shape": "string", + "name": "siteName" + }, + { + "displayName": "Device Class", + "shape": "string", + "name": "deviceClass" + }, + { + "displayName": "Operating System", + "shape": "string", + "name": "operatingSystem" + }, + { + "displayName": "Online Status", + "shape": "string", + "name": "onlineStatus" + }, + { + "displayName": "Last Seen", + "shape": "date", + "name": "lastSeen" + }, + { + "displayName": "Creation Date", + "shape": ["date", { "timeZone": "Etc/UTC" }], + "name": "creationDate" + }, + { + "displayName": "Last Audit Date", + "shape": ["date", { "timeZone": "Etc/UTC" }], + "name": "lastAuditDate" + }, + { + "displayName": "Patches Approved Pending", + "shape": ["number", { "decimalPlaces": 0 }], + "name": "patchManagement.patchesApprovedPending" + }, + { + "displayName": "Patches Installed", + "shape": ["number", { "decimalPlaces": 0 }], + "name": "patchManagement.patchesInstalled" + }, + { + "displayName": "Patches Not Approved", + "shape": ["number", { "decimalPlaces": 0 }], + "name": "patchManagement.patchesNotApproved" + }, + { + "displayName": "Compliance State", + "name": "softwareComplianceState", + "computed": true, + "valueExpression": "{{ $['softwareStatus'] }}", + "shape": ["state", { + "map": { + "success": ["Compliant"], + "error": ["Not Compliant"], + "warning": [], + "unknown": [], + "unmonitored": [] + } + }] + }, + { + "pattern": "udf.*", + "visible": false + }, + { + "pattern": ".*" + } + ], + "providesPluginDiagnostics": true, + "timeframes": [ + "last1hour", + "last12hours", + "last24hours", + "last7days", + "last30days", + "thisMonth", + "thisQuarter", + "thisYear", + "lastMonth", + "lastQuarter", + "lastYear", + "none" + ] +} \ No newline at end of file diff --git a/plugins/DattoRMM/v1/dataStreams/dattoScopeClosedAlerts.json b/plugins/DattoRMM/v1/dataStreams/dattoScopeClosedAlerts.json new file mode 100644 index 00000000..90bdce68 --- /dev/null +++ b/plugins/DattoRMM/v1/dataStreams/dattoScopeClosedAlerts.json @@ -0,0 +1,81 @@ +{ + "name": "dattoScopeClosedAlerts", + "displayName": "Closed Alerts", + "description": "Resolved alerts for a specific site", + "tags": ["Alerts"], + "baseDataSourceName": "httpRequestScopedSingle", + "matches": { + "sourceType": { + "type": "equals", + "value": "Datto Site" + } + }, + "config": { + "httpMethod": "get", + "paging": { + "mode": "none" + }, + "expandInnerObjects": true, + "endpointPath": "api/v2/site/{{objects[0].siteUid}}/alerts/resolved", + "pathToData": "alerts", + "getArgs": [], + "headers": [] + }, + "metadata": [ + { + "shape": "string", + "name": "uid", + "visible": false + }, + { + "name": "sourceId", + "displayName": "Object ID", + "shape": "string", + "visible": false + }, + { + "displayName": "Alert Message", + "shape": "string", + "name": "alertSourceInfo.alertMessage" + }, + { + "displayName": "Alert Type", + "shape": "string", + "name": "alertSourceInfo.alertTypeDescription" + }, + { + "displayName": "Device", + "shape": "string", + "name": "alertSourceInfo.alertContext.hostname" + }, + { + "shape": "string", + "name": "alertSourceInfo.alertContext.deviceUid", + "visible": false + }, + { + "shape": "string", + "name": "alertSourceInfo.alertContext.siteUid", + "visible": false + }, + { + "displayName": "Priority", + "shape": "string", + "name": "priority" + }, + { + "displayName": "Raised", + "shape": ["date", { "timeZone": "Etc/UTC" }], + "name": "timestamp" + }, + { + "displayName": "Resolved", + "shape": ["date", { "timeZone": "Etc/UTC" }], + "name": "resolvedAt" + }, + { + "pattern": ".*" + } + ], + "timeframes": false +} diff --git a/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json b/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json new file mode 100644 index 00000000..48829f06 --- /dev/null +++ b/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json @@ -0,0 +1,77 @@ +{ + "name": "dattoScopeOpenAlerts", + "displayName": "Open Alerts", + "description": "Open alerts for a specific site", + "tags": ["Alerts"], + "baseDataSourceName": "httpRequestScopedSingle", + "matches": { + "sourceType": { + "type": "equals", + "value": "Datto Site" + } + }, + "config": { + "httpMethod": "get", + "paging": { + "mode": "none" + }, + "expandInnerObjects": true, + "endpointPath": "api/v2/site/{{objects[0].siteUid}}/alerts/open", + "pathToData": "alerts", + "getArgs": [], + "headers": [] + }, + "metadata": [ + { + "shape": "string", + "name": "uid", + "visible": false + }, + { + "name": "sourceId", + "displayName": "Object ID", + "shape": "string", + "visible": false + }, + { + "displayName": "Alert Message", + "shape": "string", + "name": "alertSourceInfo.alertMessage" + }, + { + "displayName": "Alert Type", + "shape": "string", + "name": "alertSourceInfo.alertTypeDescription" + }, + { + "displayName": "Device", + "shape": "string", + "name": "alertSourceInfo.alertContext.hostname" + }, + { + "shape": "string", + "name": "alertSourceInfo.alertContext.deviceUid", + "visible": false + }, + { + "shape": "string", + "name": "alertSourceInfo.alertContext.siteUid", + "visible": false + }, + { + "displayName": "Priority", + "shape": "string", + "name": "priority" + }, + { + "displayName": "Timestamp", + "shape": ["date", { "timeZone": "Etc/UTC" }], + "name": "timestamp" + }, + { + "pattern": ".*" + } + ], + "providesPluginDiagnostics": true, + "timeframes": false +} \ No newline at end of file diff --git a/plugins/DattoRMM/v1/dataStreams/importSites.json b/plugins/DattoRMM/v1/dataStreams/importSites.json new file mode 100644 index 00000000..15accd54 --- /dev/null +++ b/plugins/DattoRMM/v1/dataStreams/importSites.json @@ -0,0 +1,100 @@ +{ + "name": "importSites", + "displayName": "Sites", + "description": "All sites in the account", + "tags": ["Sites"], + "baseDataSourceName": "httpRequestUnscoped", + "config": { + "httpMethod": "get", + "paging": { + "mode": "nextUrl", + "pageSize": { + "realm": { + "value": "none", + "label": "none" + } + }, + "in": { + "realm": { + "value": "payload", + "label": "payload" + }, + "path": "pageDetails.nextPageUrl" + } + }, + "expandInnerObjects": true, + "endpointPath": "api/v2/account/sites", + "pathToData": "sites", + "getArgs": [], + "headers": [] + }, + "metadata": [ + { + "shape": "string", + "name": "uid", + "visible": false + }, + { + "displayName": "Name", + "shape": "string", + "name": "name" + }, + { + "displayName": "Description", + "shape": "string", + "name": "description" + }, + { + "displayName": "Notes", + "shape": "string", + "name": "notes" + }, + { + "displayName": "Total Devices", + "shape": [ + "number", + { + "decimalPlaces": 0 + } + ], + "name": "devicesStatus.numberOfDevices" + }, + { + "displayName": "Offline Devices", + "shape": [ + "number", + { + "decimalPlaces": 0 + } + ], + "name": "devicesStatus.numberOfOfflineDevices" + }, + { + "displayName": "Online Devices", + "shape": [ + "number", + { + "decimalPlaces": 0 + } + ], + "name": "devicesStatus.numberOfOnlineDevices" + }, + { + "pattern": ".*" + } + ], + "timeframes": [ + "last1hour", + "last12hours", + "last24hours", + "last7days", + "last30days", + "thisMonth", + "thisQuarter", + "thisYear", + "lastMonth", + "lastQuarter", + "lastYear", + "none" + ] +} \ No newline at end of file diff --git a/plugins/DattoRMM/v1/docs/README.md b/plugins/DattoRMM/v1/docs/README.md new file mode 100644 index 00000000..a5225b1f --- /dev/null +++ b/plugins/DattoRMM/v1/docs/README.md @@ -0,0 +1,26 @@ +# Before you start + +[Datto RMM](https://www.datto.com/rmm) is a cloud-based Remote Monitoring and Management (RMM) platform used by Managed Service Providers (MSPs) to monitor, manage and support client devices. This plugin lets you import your Datto RMM sites and devices into SquaredUp, and monitor open alerts scoped to individual sites. + +## What is imported + +The following objects are imported and kept in sync: + +- **Sites** — each managed client site, including device counts (total, online, offline) +- **Devices** — all endpoints across all sites, including hostname, operating system, online status, last seen time, and internal/external IP addresses + +## Data streams + +| Data stream | Description | +|-------------|-------------| +| **All Devices** | Returns all devices across every site. Use this to build fleet-wide views or group by site. | +| **Open Alerts** | Returns open alerts scoped to an imported site object. Use this on site dashboards to surface active issues. | + +## Setup + +You will need the **Base URL**, **API Key** and **API Secret** for your Datto RMM account. + +1. Log in to Datto RMM and navigate to **Setup** > **API** +2. Copy the **API URL** — this is your Base URL (e.g. `https://merlot-api.centrastage.net`) +3. Under **API Users**, create a new API user or select an existing one +4. Copy the **API Key** and **API Secret** for that user diff --git a/plugins/DattoRMM/v1/icon.png b/plugins/DattoRMM/v1/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..da4522235a9831e5fa52e5025c8dc6d303da5165 GIT binary patch literal 2437 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 API.", + "validation": { + "required": true, + "pattern": { + "value": "^https?://[^\\s]+$", + "message": "Please enter a valid URL starting with https://" + } + } + }, + { + "type": "text", + "name": "apiKey", + "label": "API Key", + "placeholder": "Enter your Datto RMM API Key", + "help": "Enter the API Key from the Datto RMM Access Control screen https://rmm.datto.com/help/en/Content/2SETUP/APIv2.htm", + "validation": { + "required": true + } + }, + { + "type": "password", + "name": "apiSecret", + "label": "API Secret", + "placeholder": "Enter your Datto RMM API Secret Key", + "help": "Enter the API Secret Key from the Datto RMM Access Control screen", + "validation": { + "required": true + } + } +] From 85fc425544927faab0805601f93b17d9d205a0ab Mon Sep 17 00:00:00 2001 From: Tim Wheeler <63284593+TimWheeler-SQUP@users.noreply.github.com> Date: Mon, 13 Apr 2026 10:01:27 +0100 Subject: [PATCH 10/14] Add paging to data streams --- .gitignore | 7 ------- .../DattoRMM/v1/dataStreams/dattoAllDevices.json | 15 +-------------- .../v1/dataStreams/dattoScopeClosedAlerts.json | 11 +++++++++-- .../v1/dataStreams/dattoScopeOpenAlerts.json | 9 ++++++++- plugins/DattoRMM/v1/dataStreams/importSites.json | 15 +-------------- 5 files changed, 19 insertions(+), 38 deletions(-) diff --git a/.gitignore b/.gitignore index dd3bb92a..43ec3040 100644 --- a/.gitignore +++ b/.gitignore @@ -81,13 +81,6 @@ logs/ *.local.json -############################################ -# Claude Code (local only, never commit) -############################################ - -*.local.md - - ############################################ # Optional: generated assets ############################################ diff --git a/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json b/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json index 63ed8965..da441ba6 100644 --- a/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json +++ b/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json @@ -128,18 +128,5 @@ } ], "providesPluginDiagnostics": true, - "timeframes": [ - "last1hour", - "last12hours", - "last24hours", - "last7days", - "last30days", - "thisMonth", - "thisQuarter", - "thisYear", - "lastMonth", - "lastQuarter", - "lastYear", - "none" - ] + "timeframes": false } \ No newline at end of file diff --git a/plugins/DattoRMM/v1/dataStreams/dattoScopeClosedAlerts.json b/plugins/DattoRMM/v1/dataStreams/dattoScopeClosedAlerts.json index 90bdce68..48b5cd72 100644 --- a/plugins/DattoRMM/v1/dataStreams/dattoScopeClosedAlerts.json +++ b/plugins/DattoRMM/v1/dataStreams/dattoScopeClosedAlerts.json @@ -13,7 +13,14 @@ "config": { "httpMethod": "get", "paging": { - "mode": "none" + "mode": "nextUrl", + "pageSize": { + "realm": { "value": "none", "label": "none" } + }, + "in": { + "realm": { "value": "payload", "label": "payload" }, + "path": "pageDetails.nextPageUrl" + } }, "expandInnerObjects": true, "endpointPath": "api/v2/site/{{objects[0].siteUid}}/alerts/resolved", @@ -71,7 +78,7 @@ { "displayName": "Resolved", "shape": ["date", { "timeZone": "Etc/UTC" }], - "name": "resolvedAt" + "name": "resolvedOn" }, { "pattern": ".*" diff --git a/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json b/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json index 48829f06..7f59aa32 100644 --- a/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json +++ b/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json @@ -13,7 +13,14 @@ "config": { "httpMethod": "get", "paging": { - "mode": "none" + "mode": "nextUrl", + "pageSize": { + "realm": { "value": "none", "label": "none" } + }, + "in": { + "realm": { "value": "payload", "label": "payload" }, + "path": "pageDetails.nextPageUrl" + } }, "expandInnerObjects": true, "endpointPath": "api/v2/site/{{objects[0].siteUid}}/alerts/open", diff --git a/plugins/DattoRMM/v1/dataStreams/importSites.json b/plugins/DattoRMM/v1/dataStreams/importSites.json index 15accd54..2d73df46 100644 --- a/plugins/DattoRMM/v1/dataStreams/importSites.json +++ b/plugins/DattoRMM/v1/dataStreams/importSites.json @@ -83,18 +83,5 @@ "pattern": ".*" } ], - "timeframes": [ - "last1hour", - "last12hours", - "last24hours", - "last7days", - "last30days", - "thisMonth", - "thisQuarter", - "thisYear", - "lastMonth", - "lastQuarter", - "lastYear", - "none" - ] + "timeframes": false } \ No newline at end of file From e12fd6ba9f834a8405546f7633aac63a83cf0f27 Mon Sep 17 00:00:00 2001 From: Tim Wheeler <63284593+TimWheeler-SQUP@users.noreply.github.com> Date: Sun, 26 Apr 2026 22:51:54 +0100 Subject: [PATCH 11/14] Add OOB dashboard --- .../v1/dataStreams/dattoAllDevices.json | 1 - .../v1/dataStreams/dattoScopeOpenAlerts.json | 1 - .../DattoRMM/v1/defaultContent/manifest.json | 8 + .../v1/defaultContent/overview.dash.json | 402 ++++++++++++++++++ .../DattoRMM/v1/defaultContent/scopes.json | 1 + plugins/DattoRMM/v1/docs/README.md | 1 + plugins/DattoRMM/v1/metadata.json | 1 + plugins/DattoRMM/v1/ui.json | 12 +- 8 files changed, 419 insertions(+), 8 deletions(-) create mode 100644 plugins/DattoRMM/v1/defaultContent/manifest.json create mode 100644 plugins/DattoRMM/v1/defaultContent/overview.dash.json create mode 100644 plugins/DattoRMM/v1/defaultContent/scopes.json diff --git a/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json b/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json index da441ba6..ab9fb2a1 100644 --- a/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json +++ b/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json @@ -127,6 +127,5 @@ "pattern": ".*" } ], - "providesPluginDiagnostics": true, "timeframes": false } \ No newline at end of file diff --git a/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json b/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json index 7f59aa32..817a946e 100644 --- a/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json +++ b/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json @@ -79,6 +79,5 @@ "pattern": ".*" } ], - "providesPluginDiagnostics": true, "timeframes": false } \ No newline at end of file diff --git a/plugins/DattoRMM/v1/defaultContent/manifest.json b/plugins/DattoRMM/v1/defaultContent/manifest.json new file mode 100644 index 00000000..965fbdba --- /dev/null +++ b/plugins/DattoRMM/v1/defaultContent/manifest.json @@ -0,0 +1,8 @@ +{ + "items": [ + { + "name": "overview", + "type": "dashboard" + } + ] +} diff --git a/plugins/DattoRMM/v1/defaultContent/overview.dash.json b/plugins/DattoRMM/v1/defaultContent/overview.dash.json new file mode 100644 index 00000000..7a237d14 --- /dev/null +++ b/plugins/DattoRMM/v1/defaultContent/overview.dash.json @@ -0,0 +1,402 @@ +{ + "name": "Overview", + "schemaVersion": "1.4", + "dashboard": { + "_type": "layout/grid", + "contents": [ + { + "static": false, + "w": 1, + "moved": false, + "h": 2, + "x": 0, + "y": 0, + "i": "e5833cd0-afc2-4097-8c2a-9daf8315058e", + "z": 0, + "config": { + "timeframe": "none", + "dataStream": { + "name": "dattoScopeOpenAlerts", + "id": "{{dataStreams.dattoScopeOpenAlerts}}", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "query": "g.V().order().by('__name').hasNot('__canonicalType').has(\"__configId\", within(\"{{configId}}\")).or(__.has(\"sourceType\", \"Datto Site\")).limit(500)", + "bindings": {}, + "queryDetail": {} + }, + "_type": "tile/data-stream", + "description": "", + "monitor": { + "tileRollsUp": true, + "monitorType": "threshold", + "condition": { + "columns": [], + "logic": { + "if": [ + { + ">": [ + { + "var": "count" + }, + 0 + ] + }, + "error" + ] + } + }, + "_type": "simple", + "aggregation": "count", + "groupBy": "__group_by_none__", + "frequency": 15 + }, + "activePluginConfigIds": ["{{configId}}"], + "title": "Open Alerts", + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": { + "type": "count" + }, + "comparisonColumn": "none" + } + } + } + } + }, + { + "static": false, + "w": 1, + "moved": false, + "h": 2, + "x": 1, + "y": 0, + "i": "56be7304-a6ad-4722-8d2c-c85fab005e17", + "z": 0, + "config": { + "timeframe": "none", + "dataStream": { + "name": "dattoScopeClosedAlerts", + "filter": { + "multiOperation": "and", + "filters": [ + { + "column": "priority", + "operation": "equals", + "value": "Critical" + }, + { + "column": "resolvedOn", + "operation": "datewithinlast", + "value": "7", + "unit": "days" + } + ] + }, + "id": "{{dataStreams.dattoScopeClosedAlerts}}", + "pluginConfigId": "{{configId}}" + }, + "scope": { + "query": "g.V().order().by('__name').hasNot('__canonicalType').has(\"__configId\", within(\"{{configId}}\")).or(__.has(\"sourceType\", \"Datto Site\")).limit(500)", + "bindings": {}, + "queryDetail": {} + }, + "_type": "tile/data-stream", + "description": "", + "activePluginConfigIds": ["{{configId}}"], + "title": "Closed Alerts This Week", + "visualisation": { + "type": "data-stream-scalar", + "config": { + "data-stream-scalar": { + "value": { + "type": "count" + }, + "comparisonColumn": "none" + } + } + } + } + }, + { + "static": false, + "w": 2, + "moved": false, + "h": 2, + "x": 2, + "y": 0, + "i": "7510d3d0-076b-417b-b7d5-6eac0790fbb8", + "z": 0, + "config": { + "dataStream": { + "name": "importSites", + "id": "{{dataStreams.importSites}}", + "pluginConfigId": "{{configId}}" + }, + "_type": "tile/data-stream", + "description": "", + "activePluginConfigIds": ["{{configId}}"], + "title": "Devices per Site", + "visualisation": { + "type": "data-stream-donut-chart", + "config": { + "data-stream-donut-chart": { + "valueColumn": "devicesStatus.numberOfDevices", + "hideCenterValue": false, + "showValuesAsPercentage": false, + "legendPosition": "right", + "legendMode": "table", + "labelColumn": "name" + } + } + } + } + }, + { + "static": false, + "w": 2, + "moved": false, + "h": 4, + "x": 0, + "y": 2, + "i": "e4ce7182-387a-4613-8efa-dbbeac25fbf3", + "z": 0, + "config": { + "timeframe": "none", + "scope": { + "query": "g.V().order().by('__name').hasNot('__canonicalType').has(\"__configId\", within(\"{{configId}}\")).or(__.has(\"sourceType\", \"Datto Site\")).limit(500)", + "bindings": {}, + "queryDetail": {} + }, + "dataStream": { + "name": "dattoScopeClosedAlerts", + "filter": { + "filters": [ + { + "column": "timestamp", + "operation": "datewithinlast", + "value": "30", + "unit": "days" + } + ], + "multiOperation": "and" + }, + "id": "{{dataStreams.dattoScopeClosedAlerts}}", + "pluginConfigId": "{{configId}}", + "sort": { + "by": [ + [ + "count", + "desc" + ] + ] + }, + "group": { + "by": [ + [ + "alertSourceInfo.siteName", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "_type": "tile/data-stream", + "description": "Last 30 days", + "activePluginConfigIds": ["{{configId}}"], + "title": "Critical Alerts by Site", + "visualisation": { + "type": "data-stream-bar-chart", + "config": { + "data-stream-bar-chart": { + "xAxisGroup": "none", + "showLegend": false, + "range": { + "type": "auto" + }, + "showGrid": true, + "grouping": false, + "displayMode": "actual", + "xAxisData": "priority", + "showTotals": false, + "yAxisLabel": "", + "horizontalLayout": "vertical", + "showValue": false, + "yAxisData": [], + "showYAxisLabel": true, + "xAxisLabel": "", + "legendPosition": "bottom", + "showXAxisLabel": true + } + } + } + } + }, + { + "static": false, + "w": 2, + "moved": false, + "h": 2, + "x": 2, + "y": 2, + "i": "8915fab0-a2a2-4f4f-aea3-9d29d6657427", + "z": 0, + "config": { + "dataStream": { + "name": "dattoAllDevices", + "id": "{{dataStreams.dattoAllDevices}}", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "deviceType.type", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "_type": "tile/data-stream", + "description": "", + "activePluginConfigIds": ["{{configId}}"], + "title": "Devices by Type", + "visualisation": { + "type": "data-stream-donut-chart", + "config": { + "data-stream-donut-chart": { + "valueColumn": "count", + "hideCenterValue": false, + "showValuesAsPercentage": false, + "legendPosition": "left", + "legendMode": "table", + "labelColumn": "deviceType.type_uniqueValues" + } + } + } + } + }, + { + "static": false, + "w": 1, + "moved": false, + "h": 2, + "x": 2, + "y": 4, + "i": "0bda6fa4-bcb6-4435-815b-286baf4c5ea8", + "z": 0, + "config": { + "timeframe": "last24hours", + "dataStream": { + "name": "dattoAllDevices", + "filter": { + "multiOperation": "and", + "filters": [ + { + "column": "softwareComplianceState", + "operation": "equals", + "value": "error" + } + ] + }, + "id": "{{dataStreams.dattoAllDevices}}", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "deviceType.type", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "_type": "tile/data-stream", + "description": "", + "activePluginConfigIds": ["{{configId}}"], + "title": "Non-Compliant Devices", + "visualisation": { + "type": "data-stream-donut-chart", + "config": { + "data-stream-donut-chart": { + "valueColumn": "count", + "labelColumn": "deviceType.type_uniqueValues" + } + } + } + } + }, + { + "static": false, + "w": 1, + "moved": false, + "h": 2, + "x": 3, + "y": 4, + "i": "b845fc8b-ddbd-4fad-9a30-0dea930d85d9", + "z": 0, + "config": { + "timeframe": "last24hours", + "dataStream": { + "name": "dattoAllDevices", + "filter": { + "multiOperation": "and", + "filters": [ + { + "column": "patchManagement.patchStatus", + "operation": "contains", + "value": "Reboot" + } + ] + }, + "id": "{{dataStreams.dattoAllDevices}}", + "pluginConfigId": "{{configId}}", + "group": { + "by": [ + [ + "deviceType.type", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" + } + ] + } + }, + "_type": "tile/data-stream", + "description": "", + "activePluginConfigIds": ["{{configId}}"], + "title": "Patch Status - Reboot Required", + "visualisation": { + "type": "data-stream-donut-chart", + "config": { + "data-stream-donut-chart": { + "valueColumn": "count", + "labelColumn": "deviceType.type_uniqueValues" + } + } + } + } + } + ], + "version": 54, + "columns": 4 + }, + "path": "overview", + "folderPath": [] +} diff --git a/plugins/DattoRMM/v1/defaultContent/scopes.json b/plugins/DattoRMM/v1/defaultContent/scopes.json new file mode 100644 index 00000000..fe51488c --- /dev/null +++ b/plugins/DattoRMM/v1/defaultContent/scopes.json @@ -0,0 +1 @@ +[] diff --git a/plugins/DattoRMM/v1/docs/README.md b/plugins/DattoRMM/v1/docs/README.md index a5225b1f..d1c518b1 100644 --- a/plugins/DattoRMM/v1/docs/README.md +++ b/plugins/DattoRMM/v1/docs/README.md @@ -15,6 +15,7 @@ The following objects are imported and kept in sync: |-------------|-------------| | **All Devices** | Returns all devices across every site. Use this to build fleet-wide views or group by site. | | **Open Alerts** | Returns open alerts scoped to an imported site object. Use this on site dashboards to surface active issues. | +| **Closed Alerts** | Returns resolved alerts scoped to an imported site object, for a given time range. | ## Setup diff --git a/plugins/DattoRMM/v1/metadata.json b/plugins/DattoRMM/v1/metadata.json index bed35bf5..d9e4125f 100644 --- a/plugins/DattoRMM/v1/metadata.json +++ b/plugins/DattoRMM/v1/metadata.json @@ -47,6 +47,7 @@ "oauth2Scope": "" } }, + "keywords": ["rmm", "monitoring", "alerts", "devices", "msp", "datto"], "links": [ { "category": "documentation", diff --git a/plugins/DattoRMM/v1/ui.json b/plugins/DattoRMM/v1/ui.json index c84554a0..e3d4d705 100644 --- a/plugins/DattoRMM/v1/ui.json +++ b/plugins/DattoRMM/v1/ui.json @@ -16,9 +16,9 @@ { "type": "text", "name": "apiKey", - "label": "API Key", - "placeholder": "Enter your Datto RMM API Key", - "help": "Enter the API Key from the Datto RMM Access Control screen https://rmm.datto.com/help/en/Content/2SETUP/APIv2.htm", + "label": "API key", + "placeholder": "Enter the Datto RMM API key", + "help": "Find the API key in the [Datto RMM Access Control](https://rmm.datto.com/help/en/Content/2SETUP/APIv2.htm) screen", "validation": { "required": true } @@ -26,9 +26,9 @@ { "type": "password", "name": "apiSecret", - "label": "API Secret", - "placeholder": "Enter your Datto RMM API Secret Key", - "help": "Enter the API Secret Key from the Datto RMM Access Control screen", + "label": "API secret", + "placeholder": "Enter the Datto RMM API secret key", + "help": "Find the API secret key in the [Datto RMM Access Control](https://rmm.datto.com/help/en/Content/2SETUP/APIv2.htm) screen", "validation": { "required": true } From 6975b47ac19223d599e7301e22c9bae478ded049 Mon Sep 17 00:00:00 2001 From: Tim Wheeler <63284593+TimWheeler-SQUP@users.noreply.github.com> Date: Sun, 26 Apr 2026 23:05:02 +0100 Subject: [PATCH 12/14] Fix paging....again --- plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json | 10 ++-------- .../v1/dataStreams/dattoScopeClosedAlerts.json | 4 ++-- .../DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json | 4 ++-- plugins/DattoRMM/v1/dataStreams/importSites.json | 10 ++-------- 4 files changed, 8 insertions(+), 20 deletions(-) diff --git a/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json b/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json index ab9fb2a1..9cf4b0fe 100644 --- a/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json +++ b/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json @@ -9,16 +9,10 @@ "paging": { "mode": "nextUrl", "pageSize": { - "realm": { - "value": "none", - "label": "none" - } + "realm": "none" }, "in": { - "realm": { - "value": "payload", - "label": "payload" - }, + "realm": "payload", "path": "pageDetails.nextPageUrl" } }, diff --git a/plugins/DattoRMM/v1/dataStreams/dattoScopeClosedAlerts.json b/plugins/DattoRMM/v1/dataStreams/dattoScopeClosedAlerts.json index 48b5cd72..5b756bfe 100644 --- a/plugins/DattoRMM/v1/dataStreams/dattoScopeClosedAlerts.json +++ b/plugins/DattoRMM/v1/dataStreams/dattoScopeClosedAlerts.json @@ -15,10 +15,10 @@ "paging": { "mode": "nextUrl", "pageSize": { - "realm": { "value": "none", "label": "none" } + "realm": "none" }, "in": { - "realm": { "value": "payload", "label": "payload" }, + "realm": "payload", "path": "pageDetails.nextPageUrl" } }, diff --git a/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json b/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json index 817a946e..22b441b3 100644 --- a/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json +++ b/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json @@ -15,10 +15,10 @@ "paging": { "mode": "nextUrl", "pageSize": { - "realm": { "value": "none", "label": "none" } + "realm": "none" }, "in": { - "realm": { "value": "payload", "label": "payload" }, + "realm": "payload", "path": "pageDetails.nextPageUrl" } }, diff --git a/plugins/DattoRMM/v1/dataStreams/importSites.json b/plugins/DattoRMM/v1/dataStreams/importSites.json index 2d73df46..c0cc65e4 100644 --- a/plugins/DattoRMM/v1/dataStreams/importSites.json +++ b/plugins/DattoRMM/v1/dataStreams/importSites.json @@ -9,16 +9,10 @@ "paging": { "mode": "nextUrl", "pageSize": { - "realm": { - "value": "none", - "label": "none" - } + "realm": "none" }, "in": { - "realm": { - "value": "payload", - "label": "payload" - }, + "realm": "payload", "path": "pageDetails.nextPageUrl" } }, From c3b60c1cd7421979549c9c35b1fadb24ef2eb48f Mon Sep 17 00:00:00 2001 From: Tim Wheeler <63284593+TimWheeler-SQUP@users.noreply.github.com> Date: Wed, 29 Apr 2026 11:44:02 +0100 Subject: [PATCH 13/14] update paging max size --- plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json | 4 +++- plugins/DattoRMM/v1/dataStreams/dattoScopeClosedAlerts.json | 4 +++- plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json | 4 +++- plugins/DattoRMM/v1/dataStreams/importSites.json | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json b/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json index 9cf4b0fe..91048d5f 100644 --- a/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json +++ b/plugins/DattoRMM/v1/dataStreams/dattoAllDevices.json @@ -9,7 +9,9 @@ "paging": { "mode": "nextUrl", "pageSize": { - "realm": "none" + "path": "max", + "realm": "queryArg", + "value": "100" }, "in": { "realm": "payload", diff --git a/plugins/DattoRMM/v1/dataStreams/dattoScopeClosedAlerts.json b/plugins/DattoRMM/v1/dataStreams/dattoScopeClosedAlerts.json index 5b756bfe..54617342 100644 --- a/plugins/DattoRMM/v1/dataStreams/dattoScopeClosedAlerts.json +++ b/plugins/DattoRMM/v1/dataStreams/dattoScopeClosedAlerts.json @@ -15,7 +15,9 @@ "paging": { "mode": "nextUrl", "pageSize": { - "realm": "none" + "path": "max", + "realm": "queryArg", + "value": "100" }, "in": { "realm": "payload", diff --git a/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json b/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json index 22b441b3..e892a591 100644 --- a/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json +++ b/plugins/DattoRMM/v1/dataStreams/dattoScopeOpenAlerts.json @@ -15,7 +15,9 @@ "paging": { "mode": "nextUrl", "pageSize": { - "realm": "none" + "path": "max", + "realm": "queryArg", + "value": "100" }, "in": { "realm": "payload", diff --git a/plugins/DattoRMM/v1/dataStreams/importSites.json b/plugins/DattoRMM/v1/dataStreams/importSites.json index c0cc65e4..a0367cfe 100644 --- a/plugins/DattoRMM/v1/dataStreams/importSites.json +++ b/plugins/DattoRMM/v1/dataStreams/importSites.json @@ -9,7 +9,9 @@ "paging": { "mode": "nextUrl", "pageSize": { - "realm": "none" + "path": "max", + "realm": "queryArg", + "value": "100" }, "in": { "realm": "payload", From 83dfc9eff7e554c233349039f784722e4d5820ee Mon Sep 17 00:00:00 2001 From: Tim Wheeler <63284593+TimWheeler-SQUP@users.noreply.github.com> Date: Thu, 30 Apr 2026 09:32:51 +0100 Subject: [PATCH 14/14] Fix PR review issues Co-authored-by: Copilot --- .../v1/defaultContent/overview.dash.json | 73 ++++++++++--------- plugins/DattoRMM/v1/ui.json | 4 +- 2 files changed, 41 insertions(+), 36 deletions(-) diff --git a/plugins/DattoRMM/v1/defaultContent/overview.dash.json b/plugins/DattoRMM/v1/defaultContent/overview.dash.json index 7a237d14..ce8eafe3 100644 --- a/plugins/DattoRMM/v1/defaultContent/overview.dash.json +++ b/plugins/DattoRMM/v1/defaultContent/overview.dash.json @@ -193,48 +193,53 @@ ] ] }, - "group": { - "by": [ - [ - "alertSourceInfo.siteName", - "uniqueValues" - ] - ], - "aggregate": [ - { - "type": "count" - } - ] + "group": { + "by": [ + [ + "alertSourceInfo.siteName", + "uniqueValues" + ], + [ + "priority", + "uniqueValues" + ] + ], + "aggregate": [ + { + "type": "count" } + ] + } }, "_type": "tile/data-stream", "description": "Last 30 days", "activePluginConfigIds": ["{{configId}}"], - "title": "Critical Alerts by Site", + "title": "Alerts by Site", "visualisation": { "type": "data-stream-bar-chart", - "config": { + "config":{ "data-stream-bar-chart": { - "xAxisGroup": "none", - "showLegend": false, - "range": { - "type": "auto" - }, - "showGrid": true, - "grouping": false, - "displayMode": "actual", - "xAxisData": "priority", - "showTotals": false, - "yAxisLabel": "", - "horizontalLayout": "vertical", - "showValue": false, - "yAxisData": [], - "showYAxisLabel": true, - "xAxisLabel": "", - "legendPosition": "bottom", - "showXAxisLabel": true - } - } + + "xAxisGroup": "priority_uniqueValues", + "showLegend": false, + "range": { + "type": "auto" + }, + "showGrid": true, + "grouping": false, + "displayMode": "actual", + "xAxisData": "alertSourceInfo.siteName_uniqueValues", + "showTotals": false, + "yAxisLabel": "", + "horizontalLayout": "vertical", + "showValue": false, + "yAxisData": [], + "showYAxisLabel": true, + "xAxisLabel": "", + "legendPosition": "bottom", + "showXAxisLabel": true + } + } } } }, diff --git a/plugins/DattoRMM/v1/ui.json b/plugins/DattoRMM/v1/ui.json index e3d4d705..6911a684 100644 --- a/plugins/DattoRMM/v1/ui.json +++ b/plugins/DattoRMM/v1/ui.json @@ -8,13 +8,13 @@ "validation": { "required": true, "pattern": { - "value": "^https?://[^\\s]+$", + "value": "^https://[^\\s]+$", "message": "Please enter a valid URL starting with https://" } } }, { - "type": "text", + "type": "password", "name": "apiKey", "label": "API key", "placeholder": "Enter the Datto RMM API key",