@oneuptime/common 12.0.11 → 12.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.ts +32 -5
- package/Models/DatabaseModels/NetworkDevice.ts +64 -0
- package/Models/DatabaseModels/StatusPage.ts +59 -0
- package/Models/DatabaseModels/StatusPageOidc.ts +2 -0
- package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +19 -2
- package/Server/API/AIChatAPI.ts +55 -56
- package/Server/API/CommonAPI.ts +89 -0
- package/Server/API/MicrosoftTeamsAPI.ts +20 -9
- package/Server/API/SlackAPI.ts +13 -10
- package/Server/API/StatusPageAPI.ts +2197 -2128
- package/Server/API/TelemetryAPI.ts +72 -3
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787500000000-AddEnableSearchEngineIndexingToStatusPage.ts +30 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787600000000-AddNetworkDeviceReachabilityColumns.ts +47 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
- package/Server/Middleware/UserAuthorization.ts +11 -2
- package/Server/Services/ApiKeyPermissionService.ts +116 -2
- package/Server/Services/DatabaseService.ts +17 -6
- package/Server/Services/LogAggregationService.ts +34 -0
- package/Server/Services/LogService.ts +21 -0
- package/Server/Services/NetworkSiteService.ts +12 -0
- package/Server/Services/SpanService.ts +21 -0
- package/Server/Services/TraceAggregationService.ts +15 -0
- package/Server/Services/WorkspaceNotificationRuleService.ts +172 -220
- package/Server/Types/AnalyticsDatabase/ModelPermission.ts +9 -0
- package/Server/Types/Database/Permissions/AccessControlPermission.ts +47 -16
- package/Server/Types/Workflow/Components/Conditions/IfElse.ts +9 -0
- package/Server/Types/Workflow/Components/JavaScript.ts +9 -0
- package/Server/Utils/APIKey/AccessPermission.ts +16 -40
- package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +144 -0
- package/Server/Utils/LogRedaction.ts +576 -0
- package/Server/Utils/Logger.ts +123 -46
- package/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.ts +94 -23
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +12 -0
- package/Server/Utils/Monitor/MonitorResource.ts +29 -9
- package/Server/Utils/Monitor/NetworkInventoryUtil.ts +28 -7
- package/Server/Utils/SessionReplay/SessionReplayGateCacheStore.ts +56 -10
- package/Server/Utils/StartServer.ts +30 -9
- package/Server/Utils/StatusPageSearchEngineIndexing.ts +33 -0
- package/Server/Utils/Telemetry/ResourceEntityFilter.ts +441 -0
- package/Server/Utils/VM/VMRunner.ts +693 -874
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +488 -46
- package/Tests/App/Dashboard/MonitorTypePicker.test.tsx +300 -0
- package/Tests/App/StatusPage/StatusPageIndexPageRobotsMeta.test.ts +130 -0
- package/Tests/Models/DatabaseModels/DatabaseBaseModelToJSONObjectCache.test.ts +180 -0
- package/Tests/Models/StatusPageEnableSearchEngineIndexing.test.ts +157 -0
- package/Tests/Server/API/AIChatCancelAndFeedback.test.ts +23 -1
- package/Tests/Server/API/AIChatRouteAuthorization.test.ts +785 -0
- package/Tests/Server/API/BaseAPIApiKeyAuth.test.ts +21 -8
- package/Tests/Server/API/CommonAPIAuthGuard.test.ts +290 -0
- package/Tests/Server/API/MicrosoftTeamsManifest.test.ts +7 -1
- package/Tests/Server/API/StatusPageOverviewCache.test.ts +474 -0
- package/Tests/Server/API/StatusPageSeoSearchEngineIndexing.test.ts +189 -0
- package/Tests/Server/Infrastructure/InMemoryTTLCache.test.ts +158 -0
- package/Tests/Server/Infrastructure/Postgres/DeviceRoleAndDeclaredLinkParentMigration.test.ts +9 -60
- package/Tests/Server/Middleware/ProjectAuthorizationApiKeyMiddleware.test.ts +24 -15
- package/Tests/Server/Middleware/UserAuthorization.test.ts +79 -0
- package/Tests/Server/Services/AddNetworkDeviceReachabilityColumnsMigration.test.ts +332 -0
- package/Tests/Server/Services/ApiKeyPermissionService.test.ts +347 -0
- package/Tests/Server/Services/DatabaseServiceUpdateDebugLogging.test.ts +282 -0
- package/Tests/Server/Services/NetworkSiteService.test.ts +56 -2
- package/Tests/Server/Services/TelemetryResourceFacetFilters.test.ts +267 -0
- package/Tests/Server/Services/WorkspaceNotificationRuleTestRuleChannels.test.ts +702 -0
- package/Tests/Server/Types/Database/Permissions/AccessControlPermission.test.ts +165 -0
- package/Tests/Server/Types/Workflow/Components/CustomCodeScriptError.test.ts +121 -0
- package/Tests/Server/Utils/APIKey/AccessPermission.test.ts +48 -36
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +213 -0
- package/Tests/Server/Utils/LogRedaction.test.ts +415 -0
- package/Tests/Server/Utils/LoggerCredentialLeak.test.ts +245 -0
- package/Tests/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.test.ts +374 -4
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorJavascriptExpression.test.ts +92 -0
- package/Tests/Server/Utils/Monitor/MonitorResourceIngestedStepSelection.test.ts +455 -0
- package/Tests/Server/Utils/Monitor/NetworkDeviceReachabilityRoundTrip.test.ts +369 -0
- package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +86 -8
- package/Tests/Server/Utils/PrivacyFilterUtil.test.ts +64 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayGateCacheStore.test.ts +207 -0
- package/Tests/Server/Utils/StartServerBodyVerify.test.ts +335 -0
- package/Tests/Server/Utils/StatusPageSearchEngineIndexing.test.ts +60 -0
- package/Tests/Server/Utils/Telemetry/ResourceEntityFilter.test.ts +435 -0
- package/Tests/Server/Utils/VM/VMRunnerIsolation.test.ts +385 -0
- package/Tests/Server/Utils/VM/VMRunnerSsrf.test.ts +3 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelSend.test.ts +607 -62
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsInstalledTeamIdSpace.test.ts +778 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsTeamInstalls.test.ts +44 -10
- package/Tests/Types/API/HostnameFromAuthority.test.ts +164 -0
- package/Tests/Types/Database/AccessControl/ColumnAccessControlCache.test.ts +344 -0
- package/Tests/Types/Database/DatabasePropertyFindOperator.test.ts +518 -0
- package/Tests/Types/Database/TableColumnMetadataCache.test.ts +286 -0
- package/Tests/Types/Monitor/MonitorStep.test.ts +100 -0
- package/Tests/Types/Monitor/MonitorTypeKeywords.test.ts +360 -0
- package/Tests/Types/StatusPage/SearchEngineIndexing.test.ts +86 -0
- package/Tests/Types/Telemetry/ResourceEntityFacet.test.ts +254 -0
- package/Tests/UI/Components/CardSelect.test.tsx +1021 -0
- package/Tests/UI/Components/MasterPage.test.tsx +36 -1
- package/Tests/Utils/Monitor/MonitorMetricType.test.ts +66 -1
- package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +115 -6
- package/Tests/Utils/NetworkDevice/DeviceReachabilityUtil.test.ts +610 -0
- package/Tests/Utils/NetworkSite/SiteStatusRollupUtil.test.ts +114 -45
- package/Types/API/Hostname.ts +79 -0
- package/Types/Database/AccessControl/ColumnAccessControl.ts +33 -11
- package/Types/Database/AccessControl/ColumnBillingAccessControl.ts +33 -11
- package/Types/Database/DatabaseProperty.ts +38 -0
- package/Types/Database/TableColumn.ts +34 -7
- package/Types/Events/Recurring.ts +16 -1
- package/Types/Monitor/CustomCodeMonitor/CustomCodeMonitorResponse.ts +14 -2
- package/Types/Monitor/MonitorStep.ts +13 -1
- package/Types/Monitor/MonitorType.ts +345 -40
- package/Types/Monitor/SSLMonitor/SslMonitorResponse.ts +43 -0
- package/Types/StatusPage/SearchEngineIndexing.ts +61 -0
- package/Types/Telemetry/ResourceEntityFacet.ts +211 -0
- package/UI/Components/CardSelect/CardSelect.tsx +714 -105
- package/UI/Components/EmptyState/EmptyState.tsx +8 -1
- package/UI/Components/Footer/Footer.tsx +32 -6
- package/UI/Components/Forms/Fields/FormField.tsx +3 -0
- package/UI/Components/Forms/Types/Field.ts +8 -0
- package/UI/Components/Loader/PageLoader.tsx +29 -8
- package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +26 -4
- package/UI/Components/Markdown.tsx/LazyMarkdownViewer.tsx +17 -1
- package/UI/Components/MasterPage/MasterPage.tsx +24 -11
- package/Utils/Monitor/MonitorMetricType.ts +16 -1
- package/Utils/Monitor/NetworkTopologyUtil.ts +60 -8
- package/Utils/NetworkDevice/DeviceReachabilityUtil.ts +262 -0
- package/Utils/NetworkSite/SiteStatusRollupUtil.ts +41 -24
- package/Utils/Telemetry/CrossSignalScope.ts +75 -4
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js +20 -4
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +66 -0
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPage.js +60 -0
- package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageOidc.js +2 -0
- package/build/dist/Models/DatabaseModels/StatusPageOidc.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
- package/build/dist/Server/API/AIChatAPI.js +48 -35
- package/build/dist/Server/API/AIChatAPI.js.map +1 -1
- package/build/dist/Server/API/CommonAPI.js +59 -0
- package/build/dist/Server/API/CommonAPI.js.map +1 -1
- package/build/dist/Server/API/MicrosoftTeamsAPI.js +20 -6
- package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
- package/build/dist/Server/API/SlackAPI.js +13 -10
- package/build/dist/Server/API/SlackAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +745 -673
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/API/TelemetryAPI.js +34 -3
- package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787500000000-AddEnableSearchEngineIndexingToStatusPage.js +23 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787500000000-AddEnableSearchEngineIndexingToStatusPage.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787600000000-AddNetworkDeviceReachabilityColumns.js +34 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787600000000-AddNetworkDeviceReachabilityColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/UserAuthorization.js +6 -2
- package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
- package/build/dist/Server/Services/ApiKeyPermissionService.js +90 -1
- package/build/dist/Server/Services/ApiKeyPermissionService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +15 -6
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/LogAggregationService.js +2 -0
- package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
- package/build/dist/Server/Services/LogService.js +16 -0
- package/build/dist/Server/Services/LogService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteService.js +12 -0
- package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
- package/build/dist/Server/Services/SpanService.js +16 -0
- package/build/dist/Server/Services/SpanService.js.map +1 -1
- package/build/dist/Server/Services/TraceAggregationService.js +2 -0
- package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
- package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +137 -164
- package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js +9 -0
- package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/AccessControlPermission.js +21 -13
- package/build/dist/Server/Types/Database/Permissions/AccessControlPermission.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/Conditions/IfElse.js +8 -0
- package/build/dist/Server/Types/Workflow/Components/Conditions/IfElse.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/JavaScript.js +8 -0
- package/build/dist/Server/Types/Workflow/Components/JavaScript.js.map +1 -1
- package/build/dist/Server/Utils/APIKey/AccessPermission.js +9 -32
- package/build/dist/Server/Utils/APIKey/AccessPermission.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +87 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
- package/build/dist/Server/Utils/LogRedaction.js +449 -0
- package/build/dist/Server/Utils/LogRedaction.js.map +1 -0
- package/build/dist/Server/Utils/Logger.js +98 -45
- package/build/dist/Server/Utils/Logger.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.js +65 -13
- package/build/dist/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +12 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +20 -3
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +27 -7
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
- package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCacheStore.js +29 -10
- package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCacheStore.js.map +1 -1
- package/build/dist/Server/Utils/StartServer.js +10 -7
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/StatusPageSearchEngineIndexing.js +24 -0
- package/build/dist/Server/Utils/StatusPageSearchEngineIndexing.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js +311 -0
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js.map +1 -0
- package/build/dist/Server/Utils/VM/VMRunner.js +402 -525
- package/build/dist/Server/Utils/VM/VMRunner.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +366 -37
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Types/API/Hostname.js +63 -0
- package/build/dist/Types/API/Hostname.js.map +1 -1
- package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js +20 -6
- package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js.map +1 -1
- package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js +20 -6
- package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js.map +1 -1
- package/build/dist/Types/Database/DatabaseProperty.js +38 -0
- package/build/dist/Types/Database/DatabaseProperty.js.map +1 -1
- package/build/dist/Types/Database/TableColumn.js +24 -6
- package/build/dist/Types/Database/TableColumn.js.map +1 -1
- package/build/dist/Types/Events/Recurring.js +13 -1
- package/build/dist/Types/Events/Recurring.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +9 -1
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorType.js +330 -31
- package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
- package/build/dist/Types/StatusPage/SearchEngineIndexing.js +55 -0
- package/build/dist/Types/StatusPage/SearchEngineIndexing.js.map +1 -0
- package/build/dist/Types/Telemetry/ResourceEntityFacet.js +156 -0
- package/build/dist/Types/Telemetry/ResourceEntityFacet.js.map +1 -0
- package/build/dist/UI/Components/CardSelect/CardSelect.js +360 -40
- package/build/dist/UI/Components/CardSelect/CardSelect.js.map +1 -1
- package/build/dist/UI/Components/EmptyState/EmptyState.js +1 -1
- package/build/dist/UI/Components/EmptyState/EmptyState.js.map +1 -1
- package/build/dist/UI/Components/Footer/Footer.js +7 -4
- package/build/dist/UI/Components/Footer/Footer.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/FormField.js +1 -1
- package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
- package/build/dist/UI/Components/Loader/PageLoader.js +15 -5
- package/build/dist/UI/Components/Loader/PageLoader.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +16 -3
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/LazyMarkdownViewer.js +13 -1
- package/build/dist/UI/Components/Markdown.tsx/LazyMarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/MasterPage/MasterPage.js +10 -2
- package/build/dist/UI/Components/MasterPage/MasterPage.js.map +1 -1
- package/build/dist/Utils/Monitor/MonitorMetricType.js +13 -1
- package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +34 -7
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js +177 -0
- package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js.map +1 -0
- package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js +23 -27
- package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js.map +1 -1
- package/build/dist/Utils/Telemetry/CrossSignalScope.js +44 -4
- package/build/dist/Utils/Telemetry/CrossSignalScope.js.map +1 -1
- package/package.json +1 -1
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
} from "../../../Server/Utils/Express";
|
|
13
13
|
import Response from "../../../Server/Utils/Response";
|
|
14
14
|
import { mockRouter } from "./Helpers";
|
|
15
|
-
import ApiKeyPermission from "../../../Models/DatabaseModels/ApiKeyPermission";
|
|
16
15
|
import LogPipeline from "../../../Models/DatabaseModels/LogPipeline";
|
|
17
16
|
import Monitor from "../../../Models/DatabaseModels/Monitor";
|
|
18
17
|
import BadDataException from "../../../Types/Exception/BadDataException";
|
|
@@ -25,6 +24,19 @@ import UserType from "../../../Types/UserType";
|
|
|
25
24
|
import { getJestSpyOn } from "../../Spy";
|
|
26
25
|
import { beforeEach, describe, expect, it, jest } from "@jest/globals";
|
|
27
26
|
|
|
27
|
+
/*
|
|
28
|
+
* PasswordHash has a known, pre-existing TS5.9 compile failure under ts-jest
|
|
29
|
+
* (Buffer vs BinaryLike) that breaks every suite whose import graph reaches
|
|
30
|
+
* it. Nothing here touches password hashing; stub the module before the
|
|
31
|
+
* service import graph drags it into compilation.
|
|
32
|
+
*/
|
|
33
|
+
jest.mock("../../../Server/Utils/PasswordHash", () => {
|
|
34
|
+
return {
|
|
35
|
+
__esModule: true,
|
|
36
|
+
default: class PasswordHashStub {},
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
|
|
28
40
|
jest.mock("../../../Server/Utils/Express", () => {
|
|
29
41
|
return {
|
|
30
42
|
getRouter: () => {
|
|
@@ -225,12 +237,13 @@ describe("BaseAPI CRUD auth contract for the ApiKey header (issue #3004)", () =>
|
|
|
225
237
|
): void => {
|
|
226
238
|
findApiKey.mockResolvedValue({ id: API_KEY_ID, projectId: PROJECT_ID });
|
|
227
239
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
240
|
+
findApiKeyPermissions.mockResolvedValue([
|
|
241
|
+
{
|
|
242
|
+
permission: permission,
|
|
243
|
+
labelIds: [],
|
|
244
|
+
isBlockPermission: false,
|
|
245
|
+
},
|
|
246
|
+
]);
|
|
234
247
|
};
|
|
235
248
|
|
|
236
249
|
beforeEach(() => {
|
|
@@ -250,7 +263,7 @@ describe("BaseAPI CRUD auth contract for the ApiKey header (issue #3004)", () =>
|
|
|
250
263
|
);
|
|
251
264
|
findApiKeyPermissions = getJestSpyOn(
|
|
252
265
|
ApiKeyPermissionService,
|
|
253
|
-
"
|
|
266
|
+
"findPermissionsByApiKeyId",
|
|
254
267
|
).mockResolvedValue([]);
|
|
255
268
|
getJestSpyOn(GlobalConfigService, "findOneBy").mockResolvedValue(null);
|
|
256
269
|
|
|
@@ -479,3 +479,293 @@ describe("CommonAPI.assertTenantScoped", () => {
|
|
|
479
479
|
}).not.toThrow();
|
|
480
480
|
});
|
|
481
481
|
});
|
|
482
|
+
|
|
483
|
+
/*
|
|
484
|
+
* Tests for CommonAPI.assertPermittedInProject — the third guard in the set.
|
|
485
|
+
*
|
|
486
|
+
* assertAuthenticatedProjectMember answers "are you in this project?" and
|
|
487
|
+
* assertResourceBelongsToProject answers "is this row in that project?".
|
|
488
|
+
* Neither answers "are you allowed to read this KIND of thing?", which is the
|
|
489
|
+
* question a CRUD read answers from the model's own access control lists and
|
|
490
|
+
* a custom route reading with `isRoot: true` skips entirely.
|
|
491
|
+
*
|
|
492
|
+
* The subtle part, and the reason this has its own tests: models routinely
|
|
493
|
+
* list Permission.Public as a reader (LlmProvider does, so the shared global
|
|
494
|
+
* providers stay visible), while getUserPermissions merges Public into EVERY
|
|
495
|
+
* caller's permission set — anonymous ones included. Intersecting the two
|
|
496
|
+
* lists as they come would therefore admit anybody. The guard first narrows
|
|
497
|
+
* the model's list to the permissions a team can actually grant inside a
|
|
498
|
+
* project.
|
|
499
|
+
*/
|
|
500
|
+
function buildPermittedProps(data: {
|
|
501
|
+
projectId: ObjectID;
|
|
502
|
+
granted: Array<Permission>;
|
|
503
|
+
blocked?: Array<Permission> | undefined;
|
|
504
|
+
isMasterAdmin?: boolean | undefined;
|
|
505
|
+
}): DatabaseCommonInteractionProps {
|
|
506
|
+
const permissions: Array<UserPermission> = data.granted.map(
|
|
507
|
+
(permission: Permission) => {
|
|
508
|
+
return {
|
|
509
|
+
_type: "UserPermission",
|
|
510
|
+
permission: permission,
|
|
511
|
+
labelIds: [],
|
|
512
|
+
isBlockPermission: false,
|
|
513
|
+
} as UserPermission;
|
|
514
|
+
},
|
|
515
|
+
);
|
|
516
|
+
|
|
517
|
+
for (const blocked of data.blocked || []) {
|
|
518
|
+
permissions.push({
|
|
519
|
+
_type: "UserPermission",
|
|
520
|
+
permission: blocked,
|
|
521
|
+
labelIds: [],
|
|
522
|
+
isBlockPermission: true,
|
|
523
|
+
} as UserPermission);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
const tenantPermission: UserTenantAccessPermission = {
|
|
527
|
+
_type: "UserTenantAccessPermission",
|
|
528
|
+
projectId: data.projectId,
|
|
529
|
+
permissions: permissions,
|
|
530
|
+
} as UserTenantAccessPermission;
|
|
531
|
+
|
|
532
|
+
const dictionary: Dictionary<UserTenantAccessPermission> = {};
|
|
533
|
+
dictionary[data.projectId.toString()] = tenantPermission;
|
|
534
|
+
|
|
535
|
+
return {
|
|
536
|
+
tenantId: data.projectId,
|
|
537
|
+
userId: ObjectID.generate(),
|
|
538
|
+
userTenantAccessPermission: dictionary,
|
|
539
|
+
isMasterAdmin: data.isMasterAdmin,
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
describe("CommonAPI.assertPermittedInProject", () => {
|
|
544
|
+
test("admits a caller holding one of the allowed permissions", () => {
|
|
545
|
+
const projectId: ObjectID = ObjectID.generate();
|
|
546
|
+
|
|
547
|
+
expect(() => {
|
|
548
|
+
CommonAPI.assertPermittedInProject({
|
|
549
|
+
databaseProps: buildPermittedProps({
|
|
550
|
+
projectId: projectId,
|
|
551
|
+
granted: [Permission.ProjectMember],
|
|
552
|
+
}),
|
|
553
|
+
allowedPermissions: [Permission.ProjectOwner, Permission.ProjectMember],
|
|
554
|
+
});
|
|
555
|
+
}).not.toThrow();
|
|
556
|
+
});
|
|
557
|
+
|
|
558
|
+
test("admits a caller holding any one of several allowed permissions", () => {
|
|
559
|
+
const projectId: ObjectID = ObjectID.generate();
|
|
560
|
+
|
|
561
|
+
expect(() => {
|
|
562
|
+
CommonAPI.assertPermittedInProject({
|
|
563
|
+
databaseProps: buildPermittedProps({
|
|
564
|
+
projectId: projectId,
|
|
565
|
+
granted: [Permission.ReadProjectIncident, Permission.SettingsViewer],
|
|
566
|
+
}),
|
|
567
|
+
allowedPermissions: [
|
|
568
|
+
Permission.ProjectOwner,
|
|
569
|
+
Permission.SettingsViewer,
|
|
570
|
+
],
|
|
571
|
+
});
|
|
572
|
+
}).not.toThrow();
|
|
573
|
+
});
|
|
574
|
+
|
|
575
|
+
test("refuses a member of the project who holds none of them", () => {
|
|
576
|
+
const projectId: ObjectID = ObjectID.generate();
|
|
577
|
+
|
|
578
|
+
const thrown: unknown = captureThrown(() => {
|
|
579
|
+
CommonAPI.assertPermittedInProject({
|
|
580
|
+
databaseProps: buildPermittedProps({
|
|
581
|
+
projectId: projectId,
|
|
582
|
+
granted: [Permission.ReadProjectIncident],
|
|
583
|
+
}),
|
|
584
|
+
allowedPermissions: [Permission.ProjectOwner, Permission.ProjectAdmin],
|
|
585
|
+
});
|
|
586
|
+
});
|
|
587
|
+
|
|
588
|
+
expect(thrown).toBeInstanceOf(NotAuthorizedException);
|
|
589
|
+
expect((thrown as Exception).message).toBe(
|
|
590
|
+
"You do not have permission to access this project's data.",
|
|
591
|
+
);
|
|
592
|
+
});
|
|
593
|
+
|
|
594
|
+
test("uses the caller-supplied message when one is given", () => {
|
|
595
|
+
const projectId: ObjectID = ObjectID.generate();
|
|
596
|
+
|
|
597
|
+
const thrown: unknown = captureThrown(() => {
|
|
598
|
+
CommonAPI.assertPermittedInProject({
|
|
599
|
+
databaseProps: buildPermittedProps({
|
|
600
|
+
projectId: projectId,
|
|
601
|
+
granted: [],
|
|
602
|
+
}),
|
|
603
|
+
allowedPermissions: [Permission.ProjectOwner],
|
|
604
|
+
errorMessage:
|
|
605
|
+
"You do not have permission to read this project's AI providers.",
|
|
606
|
+
});
|
|
607
|
+
});
|
|
608
|
+
|
|
609
|
+
expect((thrown as Exception).message).toBe(
|
|
610
|
+
"You do not have permission to read this project's AI providers.",
|
|
611
|
+
);
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
/*
|
|
615
|
+
* The regression this guard exists to prevent. Public is in many models'
|
|
616
|
+
* read lists and in every caller's permission set, so a naive intersection
|
|
617
|
+
* would always succeed.
|
|
618
|
+
*/
|
|
619
|
+
test("Permission.Public in the allowed list does not admit an ordinary member", () => {
|
|
620
|
+
const projectId: ObjectID = ObjectID.generate();
|
|
621
|
+
|
|
622
|
+
expect(() => {
|
|
623
|
+
CommonAPI.assertPermittedInProject({
|
|
624
|
+
databaseProps: buildPermittedProps({
|
|
625
|
+
projectId: projectId,
|
|
626
|
+
granted: [Permission.ReadProjectIncident],
|
|
627
|
+
}),
|
|
628
|
+
allowedPermissions: [Permission.Public, Permission.ProjectOwner],
|
|
629
|
+
});
|
|
630
|
+
}).toThrow(NotAuthorizedException);
|
|
631
|
+
});
|
|
632
|
+
|
|
633
|
+
test("Permission.Public in the allowed list does not admit an anonymous caller", () => {
|
|
634
|
+
const props: DatabaseCommonInteractionProps = {
|
|
635
|
+
tenantId: ObjectID.generate(),
|
|
636
|
+
};
|
|
637
|
+
|
|
638
|
+
expect(() => {
|
|
639
|
+
CommonAPI.assertPermittedInProject({
|
|
640
|
+
databaseProps: props,
|
|
641
|
+
allowedPermissions: [Permission.Public],
|
|
642
|
+
});
|
|
643
|
+
}).toThrow(NotAuthorizedException);
|
|
644
|
+
});
|
|
645
|
+
|
|
646
|
+
test("Permission.CurrentUser, which every logged-in caller carries, does not admit them either", () => {
|
|
647
|
+
const projectId: ObjectID = ObjectID.generate();
|
|
648
|
+
|
|
649
|
+
expect(() => {
|
|
650
|
+
CommonAPI.assertPermittedInProject({
|
|
651
|
+
databaseProps: buildPermittedProps({
|
|
652
|
+
projectId: projectId,
|
|
653
|
+
granted: [Permission.ReadProjectIncident],
|
|
654
|
+
}),
|
|
655
|
+
allowedPermissions: [Permission.CurrentUser, Permission.ProjectOwner],
|
|
656
|
+
});
|
|
657
|
+
}).toThrow(NotAuthorizedException);
|
|
658
|
+
});
|
|
659
|
+
|
|
660
|
+
test("an allowed list with nothing tenant-assignable in it denies everyone", () => {
|
|
661
|
+
const projectId: ObjectID = ObjectID.generate();
|
|
662
|
+
|
|
663
|
+
expect(() => {
|
|
664
|
+
CommonAPI.assertPermittedInProject({
|
|
665
|
+
databaseProps: buildPermittedProps({
|
|
666
|
+
projectId: projectId,
|
|
667
|
+
granted: [Permission.ProjectOwner],
|
|
668
|
+
}),
|
|
669
|
+
allowedPermissions: [Permission.Public, Permission.CurrentUser],
|
|
670
|
+
});
|
|
671
|
+
}).toThrow(NotAuthorizedException);
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
test("an empty allowed list denies everyone", () => {
|
|
675
|
+
const projectId: ObjectID = ObjectID.generate();
|
|
676
|
+
|
|
677
|
+
expect(() => {
|
|
678
|
+
CommonAPI.assertPermittedInProject({
|
|
679
|
+
databaseProps: buildPermittedProps({
|
|
680
|
+
projectId: projectId,
|
|
681
|
+
granted: [Permission.ProjectOwner],
|
|
682
|
+
}),
|
|
683
|
+
allowedPermissions: [],
|
|
684
|
+
});
|
|
685
|
+
}).toThrow(NotAuthorizedException);
|
|
686
|
+
});
|
|
687
|
+
|
|
688
|
+
/*
|
|
689
|
+
* userTenantAccessPermission holds grants AND denials in one array,
|
|
690
|
+
* discriminated only by isBlockPermission. Reading it raw would count a
|
|
691
|
+
* team's explicit block row as a grant.
|
|
692
|
+
*/
|
|
693
|
+
test("a BLOCK row for an allowed permission is not counted as a grant of it", () => {
|
|
694
|
+
const projectId: ObjectID = ObjectID.generate();
|
|
695
|
+
|
|
696
|
+
expect(() => {
|
|
697
|
+
CommonAPI.assertPermittedInProject({
|
|
698
|
+
databaseProps: buildPermittedProps({
|
|
699
|
+
projectId: projectId,
|
|
700
|
+
granted: [Permission.ReadProjectIncident],
|
|
701
|
+
blocked: [Permission.ProjectOwner, Permission.ProjectMember],
|
|
702
|
+
}),
|
|
703
|
+
allowedPermissions: [Permission.ProjectOwner, Permission.ProjectMember],
|
|
704
|
+
});
|
|
705
|
+
}).toThrow(NotAuthorizedException);
|
|
706
|
+
});
|
|
707
|
+
|
|
708
|
+
test("permissions granted in ANOTHER project do not count", () => {
|
|
709
|
+
const callersProjectId: ObjectID = ObjectID.generate();
|
|
710
|
+
const targetProjectId: ObjectID = ObjectID.generate();
|
|
711
|
+
|
|
712
|
+
const props: DatabaseCommonInteractionProps = buildPermittedProps({
|
|
713
|
+
projectId: callersProjectId,
|
|
714
|
+
granted: [Permission.ProjectOwner],
|
|
715
|
+
});
|
|
716
|
+
|
|
717
|
+
// The header names the target project; the grants are for another one.
|
|
718
|
+
props.tenantId = targetProjectId;
|
|
719
|
+
|
|
720
|
+
expect(() => {
|
|
721
|
+
CommonAPI.assertPermittedInProject({
|
|
722
|
+
databaseProps: props,
|
|
723
|
+
allowedPermissions: [Permission.ProjectOwner],
|
|
724
|
+
});
|
|
725
|
+
}).toThrow(NotAuthorizedException);
|
|
726
|
+
});
|
|
727
|
+
|
|
728
|
+
test("a master admin bypasses the permission check", () => {
|
|
729
|
+
const projectId: ObjectID = ObjectID.generate();
|
|
730
|
+
|
|
731
|
+
expect(() => {
|
|
732
|
+
CommonAPI.assertPermittedInProject({
|
|
733
|
+
databaseProps: buildPermittedProps({
|
|
734
|
+
projectId: projectId,
|
|
735
|
+
granted: [],
|
|
736
|
+
isMasterAdmin: true,
|
|
737
|
+
}),
|
|
738
|
+
allowedPermissions: [Permission.ProjectOwner],
|
|
739
|
+
});
|
|
740
|
+
}).not.toThrow();
|
|
741
|
+
});
|
|
742
|
+
|
|
743
|
+
/*
|
|
744
|
+
* The guard answers one question only. Membership is assertAuthenticated-
|
|
745
|
+
* ProjectMember's job, and a route must call both — this test documents
|
|
746
|
+
* that calling only this one is not enough.
|
|
747
|
+
*/
|
|
748
|
+
test("does not itself check membership — that stays with assertAuthenticatedProjectMember", () => {
|
|
749
|
+
const projectId: ObjectID = ObjectID.generate();
|
|
750
|
+
const props: DatabaseCommonInteractionProps = buildPermittedProps({
|
|
751
|
+
projectId: projectId,
|
|
752
|
+
granted: [Permission.ProjectOwner],
|
|
753
|
+
});
|
|
754
|
+
|
|
755
|
+
expect(() => {
|
|
756
|
+
CommonAPI.assertPermittedInProject({
|
|
757
|
+
databaseProps: props,
|
|
758
|
+
allowedPermissions: [Permission.ProjectOwner],
|
|
759
|
+
});
|
|
760
|
+
}).not.toThrow();
|
|
761
|
+
|
|
762
|
+
props.userId = undefined;
|
|
763
|
+
|
|
764
|
+
expect(() => {
|
|
765
|
+
CommonAPI.assertPermittedInProject({
|
|
766
|
+
databaseProps: props,
|
|
767
|
+
allowedPermissions: [Permission.ProjectOwner],
|
|
768
|
+
});
|
|
769
|
+
}).not.toThrow();
|
|
770
|
+
});
|
|
771
|
+
});
|
|
@@ -127,7 +127,7 @@ describe("MicrosoftTeamsAPI.getTeamsAppManifest", () => {
|
|
|
127
127
|
expect(names).not.toContain("ChatMessage.Send.Chat");
|
|
128
128
|
});
|
|
129
129
|
|
|
130
|
-
test("declares exactly the
|
|
130
|
+
test("declares exactly the six expected resource-specific permissions", () => {
|
|
131
131
|
const permissions: Array<JSONObject> =
|
|
132
132
|
getResourceSpecificPermissions(getManifest());
|
|
133
133
|
const names: Array<string> = permissions.map((permission: JSONObject) => {
|
|
@@ -140,6 +140,12 @@ describe("MicrosoftTeamsAPI.getTeamsAppManifest", () => {
|
|
|
140
140
|
"Channel.Create.Group",
|
|
141
141
|
"ChatMessage.Read.Chat",
|
|
142
142
|
"ChatMember.Read.Chat",
|
|
143
|
+
/*
|
|
144
|
+
* Lets OneUptime verify, per team, that the installed OneUptime app
|
|
145
|
+
* is the package built from this deployment before telling an admin
|
|
146
|
+
* their app is missing.
|
|
147
|
+
*/
|
|
148
|
+
"TeamsAppInstallation.Read.Group",
|
|
143
149
|
].sort(),
|
|
144
150
|
);
|
|
145
151
|
});
|