@oneuptime/common 14.0.6 → 14.0.7

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.
Files changed (127) hide show
  1. package/Models/DatabaseModels/InventoryItem.ts +23 -12
  2. package/Server/Infrastructure/Postgres/SchemaMigrations/1795200000000-AddInventoryItemProjectEntityKeyIndex.ts +217 -0
  3. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
  4. package/Server/Services/AlertService.ts +32 -36
  5. package/Server/Services/IncidentAlertService.ts +609 -2
  6. package/Server/Services/IncidentService.ts +134 -44
  7. package/Server/Services/InventoryItemService.ts +38 -0
  8. package/Server/Services/IoTDeviceCredentialService.ts +13 -4
  9. package/Server/Services/ScheduledMaintenanceService.ts +50 -46
  10. package/Server/Services/UserNotificationRuleService.ts +55 -53
  11. package/Server/Services/WorkspaceNotificationSummaryService.ts +38 -20
  12. package/Server/Utils/AffectedResources/LinkedAffectedResources.ts +576 -0
  13. package/Server/Utils/Alert/AlertStateChangeAuthorization.ts +129 -0
  14. package/Server/Utils/Inventory/InventoryOverviewAggregation.ts +111 -0
  15. package/Server/Utils/Response.ts +31 -0
  16. package/Server/Utils/Topology/TopologyConcurrencyLimiter.ts +229 -0
  17. package/Server/Utils/Topology/TopologyQueries.ts +1350 -0
  18. package/Server/Utils/Topology/TopologyRequest.ts +463 -0
  19. package/Server/Utils/Topology/TopologyResponseCache.ts +183 -0
  20. package/Server/Utils/Topology/TopologySql.ts +1024 -0
  21. package/Tests/App/Dashboard/AcknowledgeAlertsOnDeclare.test.ts +369 -0
  22. package/Tests/App/Dashboard/AffectedResourcesSlo.test.tsx +1 -1
  23. package/Tests/App/Dashboard/AffectedResourcesSummaryStep.test.tsx +510 -123
  24. package/Tests/App/Dashboard/AlertsTableAffectedResources.test.tsx +490 -0
  25. package/Tests/App/Dashboard/ChangeAlertStateDeclareIncident.test.tsx +886 -0
  26. package/Tests/App/Dashboard/CreateReviewStepRoleSummary.test.tsx +1250 -0
  27. package/Tests/App/Dashboard/CreateReviewStepSelectionSummary.test.tsx +738 -0
  28. package/Tests/App/Dashboard/DeclareIncidentFromAlert.test.ts +417 -0
  29. package/Tests/App/Dashboard/EntityDetailPanel.test.tsx +1948 -229
  30. package/Tests/App/Dashboard/EntityDetailPanelLifecycle.test.tsx +493 -0
  31. package/Tests/App/Dashboard/EntityDetailPanelNavigation.test.tsx +439 -0
  32. package/Tests/App/Dashboard/EventOverviewPages.test.tsx +292 -1
  33. package/Tests/App/Dashboard/EventStatusPanel.test.tsx +798 -2
  34. package/Tests/App/Dashboard/FetchStateAndSeverityElements.test.tsx +669 -0
  35. package/Tests/App/Dashboard/FetchUsers.test.tsx +230 -0
  36. package/Tests/App/Dashboard/IncidentCreateAcknowledgeAlerts.test.tsx +1611 -0
  37. package/Tests/App/Dashboard/InfrastructureExplorer.test.tsx +1365 -57
  38. package/Tests/App/Dashboard/InfrastructureGraph.test.tsx +964 -23
  39. package/Tests/App/Dashboard/InventoryRelationships.test.tsx +885 -0
  40. package/Tests/App/Dashboard/ServiceMapDatabaseLink.test.tsx +201 -15
  41. package/Tests/App/Dashboard/ServiceMapGraph.test.tsx +508 -36
  42. package/Tests/App/Dashboard/TopologyDataLifecycle.test.tsx +583 -0
  43. package/Tests/App/Dashboard/TopologyDataLoading.test.tsx +982 -218
  44. package/Tests/App/Dashboard/TopologyPageNavigation.test.tsx +818 -114
  45. package/Tests/Server/Infrastructure/Postgres/RenameInventoryItemMigration.test.ts +90 -21
  46. package/Tests/Server/Services/DomainService.test.ts +525 -0
  47. package/Tests/Server/Services/IncidentAlertAcknowledgeOnDeclare.test.ts +2630 -0
  48. package/Tests/Server/Services/IncidentAlertPostgres.test.ts +1625 -1
  49. package/Tests/Server/Services/IncidentDeclareAcknowledgeAlerts.test.ts +2189 -0
  50. package/Tests/Server/Services/InventoryItemServiceOverviewCounts.test.ts +345 -0
  51. package/Tests/Server/Services/InventoryOverviewPostgres.test.ts +254 -0
  52. package/Tests/Server/Services/IoTDeviceCredentialService.test.ts +819 -0
  53. package/Tests/Server/Services/LinkedAffectedResourcesCreatedFeed.test.ts +420 -0
  54. package/Tests/Server/Services/SloAffectedResourceCreatedFeed.test.ts +92 -36
  55. package/Tests/Server/Utils/AffectedResources/LinkedAffectedResources.test.ts +858 -0
  56. package/Tests/Server/Utils/Alert/AlertStateChangeAuthorization.test.ts +1172 -0
  57. package/Tests/Server/Utils/Topology/InventoryItemEntityKeyIndexMigration.test.ts +386 -0
  58. package/Tests/Server/Utils/Topology/InventoryItemEntityKeyIndexMigrationPostgres.test.ts +430 -0
  59. package/Tests/Server/Utils/Topology/TopologyActivityParityPostgres.test.ts +279 -0
  60. package/Tests/Server/Utils/Topology/TopologyConcurrencyLimiter.test.ts +534 -0
  61. package/Tests/Server/Utils/Topology/TopologyEstateGenerator.ts +624 -0
  62. package/Tests/Server/Utils/Topology/TopologyJsonResponse.test.ts +90 -0
  63. package/Tests/Server/Utils/Topology/TopologyQueries.test.ts +1634 -0
  64. package/Tests/Server/Utils/Topology/TopologyQueriesDifferentialPostgres.test.ts +683 -0
  65. package/Tests/Server/Utils/Topology/TopologyQueriesPostgres.test.ts +2624 -0
  66. package/Tests/Server/Utils/Topology/TopologyReference.ts +1018 -0
  67. package/Tests/Server/Utils/Topology/TopologyRequest.test.ts +643 -0
  68. package/Tests/Server/Utils/Topology/TopologyResponseCache.test.ts +305 -0
  69. package/Tests/Server/Utils/Topology/TopologySql.test.ts +973 -0
  70. package/Tests/Types/Topology/TopologyTypeRules.test.ts +176 -0
  71. package/Tests/Utils/Incident/IncidentFromAlerts.test.ts +302 -0
  72. package/Types/Incident/IncidentAlertLink.ts +19 -0
  73. package/Types/Telemetry/InventoryLiveness.ts +26 -0
  74. package/Types/Topology/TopologyApi.ts +428 -0
  75. package/Types/Topology/TopologyTypeRules.ts +191 -0
  76. package/Utils/Incident/IncidentFromAlerts.ts +78 -0
  77. package/build/dist/Models/DatabaseModels/InventoryItem.js +20 -11
  78. package/build/dist/Models/DatabaseModels/InventoryItem.js.map +1 -1
  79. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795200000000-AddInventoryItemProjectEntityKeyIndex.js +165 -0
  80. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795200000000-AddInventoryItemProjectEntityKeyIndex.js.map +1 -0
  81. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
  82. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  83. package/build/dist/Server/Services/AlertService.js +21 -33
  84. package/build/dist/Server/Services/AlertService.js.map +1 -1
  85. package/build/dist/Server/Services/IncidentAlertService.js +457 -3
  86. package/build/dist/Server/Services/IncidentAlertService.js.map +1 -1
  87. package/build/dist/Server/Services/IncidentService.js +96 -42
  88. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  89. package/build/dist/Server/Services/InventoryItemService.js +31 -0
  90. package/build/dist/Server/Services/InventoryItemService.js.map +1 -1
  91. package/build/dist/Server/Services/IoTDeviceCredentialService.js +12 -5
  92. package/build/dist/Server/Services/IoTDeviceCredentialService.js.map +1 -1
  93. package/build/dist/Server/Services/ScheduledMaintenanceService.js +37 -40
  94. package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
  95. package/build/dist/Server/Services/UserNotificationRuleService.js +55 -51
  96. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  97. package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js +42 -25
  98. package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js.map +1 -1
  99. package/build/dist/Server/Utils/AffectedResources/LinkedAffectedResources.js +405 -0
  100. package/build/dist/Server/Utils/AffectedResources/LinkedAffectedResources.js.map +1 -0
  101. package/build/dist/Server/Utils/Alert/AlertStateChangeAuthorization.js +112 -0
  102. package/build/dist/Server/Utils/Alert/AlertStateChangeAuthorization.js.map +1 -0
  103. package/build/dist/Server/Utils/Inventory/InventoryOverviewAggregation.js +81 -0
  104. package/build/dist/Server/Utils/Inventory/InventoryOverviewAggregation.js.map +1 -0
  105. package/build/dist/Server/Utils/Response.js +30 -0
  106. package/build/dist/Server/Utils/Response.js.map +1 -1
  107. package/build/dist/Server/Utils/Topology/TopologyConcurrencyLimiter.js +178 -0
  108. package/build/dist/Server/Utils/Topology/TopologyConcurrencyLimiter.js.map +1 -0
  109. package/build/dist/Server/Utils/Topology/TopologyQueries.js +884 -0
  110. package/build/dist/Server/Utils/Topology/TopologyQueries.js.map +1 -0
  111. package/build/dist/Server/Utils/Topology/TopologyRequest.js +275 -0
  112. package/build/dist/Server/Utils/Topology/TopologyRequest.js.map +1 -0
  113. package/build/dist/Server/Utils/Topology/TopologyResponseCache.js +146 -0
  114. package/build/dist/Server/Utils/Topology/TopologyResponseCache.js.map +1 -0
  115. package/build/dist/Server/Utils/Topology/TopologySql.js +688 -0
  116. package/build/dist/Server/Utils/Topology/TopologySql.js.map +1 -0
  117. package/build/dist/Types/Incident/IncidentAlertLink.js +17 -0
  118. package/build/dist/Types/Incident/IncidentAlertLink.js.map +1 -1
  119. package/build/dist/Types/Telemetry/InventoryLiveness.js +23 -0
  120. package/build/dist/Types/Telemetry/InventoryLiveness.js.map +1 -1
  121. package/build/dist/Types/Topology/TopologyApi.js +55 -0
  122. package/build/dist/Types/Topology/TopologyApi.js.map +1 -0
  123. package/build/dist/Types/Topology/TopologyTypeRules.js +165 -0
  124. package/build/dist/Types/Topology/TopologyTypeRules.js.map +1 -0
  125. package/build/dist/Utils/Incident/IncidentFromAlerts.js +38 -0
  126. package/build/dist/Utils/Incident/IncidentFromAlerts.js.map +1 -1
  127. package/package.json +1 -1
@@ -0,0 +1,230 @@
1
+ import "@testing-library/jest-dom";
2
+ import {
3
+ afterEach,
4
+ beforeEach,
5
+ describe,
6
+ expect,
7
+ jest,
8
+ test,
9
+ } from "@jest/globals";
10
+ import { cleanup, render, RenderResult, waitFor } from "@testing-library/react";
11
+ import * as React from "react";
12
+ import getJestMockFunction, { MockFunction } from "../../MockType";
13
+
14
+ /*
15
+ * FetchUsers names the people a create wizard's review step lists - the owners
16
+ * of a scheduled maintenance event or an alert episode, and the people under
17
+ * each incident role. It used to list them from the User model by id, which
18
+ * the server refuses for anyone but a master admin: a User is readable only by
19
+ * that user, so a project owner reviewing their own choices read "You do not
20
+ * have permission to access another user's User" instead of the names.
21
+ *
22
+ * It now looks the people up through TeamMember, the project-scoped link to
23
+ * User the dashboard can list. These tests pin that request, that a person in
24
+ * several teams is listed once, the order, and the error path.
25
+ */
26
+
27
+ const getListMock: MockFunction = getJestMockFunction();
28
+
29
+ jest.mock("../../../UI/Utils/ModelAPI/ModelAPI", () => {
30
+ return {
31
+ __esModule: true,
32
+ default: {
33
+ getList: (...args: Array<unknown>) => {
34
+ return getListMock(...args);
35
+ },
36
+ },
37
+ };
38
+ });
39
+
40
+ import FetchUsers from "../../../../App/FeatureSet/Dashboard/src/Components/User/FetchUsers";
41
+ import TeamMember from "../../../Models/DatabaseModels/TeamMember";
42
+ import User from "../../../Models/DatabaseModels/User";
43
+ import Includes from "../../../Types/BaseDatabase/Includes";
44
+ import Email from "../../../Types/Email";
45
+ import Name from "../../../Types/Name";
46
+ import ObjectID from "../../../Types/ObjectID";
47
+ import ProjectUtil from "../../../UI/Utils/Project";
48
+
49
+ const PROJECT_ID: string = "3b1d7c2e-5f4a-4e6b-9c8d-7a6f5e4d3c2b";
50
+
51
+ // What the server says when the User model is listed by other users' ids.
52
+ const USER_MODEL_REFUSAL: string =
53
+ "You do not have permission to access another user's User.";
54
+
55
+ const LOOKUP_FAILURE_MESSAGE: string = "Could not reach the server right now.";
56
+
57
+ type UserFixture = {
58
+ id: string;
59
+ name: string;
60
+ email: string;
61
+ // How many of the project's teams this person is in.
62
+ teams: number;
63
+ };
64
+
65
+ const ZOE: UserFixture = {
66
+ id: "55555555-5555-4555-8555-000000000001",
67
+ name: "Zoe Adeyemi",
68
+ email: "zoe@example.com",
69
+ teams: 1,
70
+ };
71
+
72
+ const ALICE: UserFixture = {
73
+ id: "55555555-5555-4555-8555-000000000002",
74
+ name: "Alice Nakamura",
75
+ email: "alice@example.com",
76
+ teams: 3,
77
+ };
78
+
79
+ const MARCO: UserFixture = {
80
+ id: "55555555-5555-4555-8555-000000000003",
81
+ name: "Marco Rossi",
82
+ email: "marco@example.com",
83
+ teams: 1,
84
+ };
85
+
86
+ const USER_FIXTURES: Array<UserFixture> = [ZOE, ALICE, MARCO];
87
+
88
+ type ListRequest = {
89
+ modelType: unknown;
90
+ query: Record<string, unknown>;
91
+ select: Record<string, unknown>;
92
+ };
93
+
94
+ type ListAnswer = {
95
+ data: Array<TeamMember>;
96
+ count: number;
97
+ skip: number;
98
+ limit: number;
99
+ };
100
+
101
+ function teamMembersOf(fixture: UserFixture): Array<TeamMember> {
102
+ return Array.from({ length: fixture.teams }, (): TeamMember => {
103
+ const user: User = new User();
104
+ user._id = fixture.id;
105
+ user.name = new Name(fixture.name);
106
+ user.email = new Email(fixture.email);
107
+
108
+ const teamMember: TeamMember = new TeamMember();
109
+ teamMember._id = ObjectID.generate().toString();
110
+ teamMember.user = user;
111
+ return teamMember;
112
+ });
113
+ }
114
+
115
+ /*
116
+ * Answers like the server would for a project owner: TeamMember rows by user
117
+ * id, one per team, and a refusal for any list of the User model.
118
+ */
119
+ async function answerList(request: ListRequest): Promise<ListAnswer> {
120
+ if (request.modelType === User) {
121
+ throw new Error(USER_MODEL_REFUSAL);
122
+ }
123
+
124
+ const userIdQuery: unknown = request.query["userId"];
125
+
126
+ if (request.modelType !== TeamMember || !(userIdQuery instanceof Includes)) {
127
+ return { data: [], count: 0, skip: 0, limit: 0 };
128
+ }
129
+
130
+ const ids: Array<string> = userIdQuery.values.map(
131
+ (value: string | ObjectID | number): string => {
132
+ return value.toString();
133
+ },
134
+ );
135
+
136
+ const data: Array<TeamMember> = USER_FIXTURES.filter(
137
+ (fixture: UserFixture): boolean => {
138
+ return ids.includes(fixture.id);
139
+ },
140
+ ).flatMap(teamMembersOf);
141
+
142
+ return { data: data, count: data.length, skip: 0, limit: data.length };
143
+ }
144
+
145
+ function idsOf(fixtures: Array<UserFixture>): Array<ObjectID> {
146
+ return fixtures.map((fixture: UserFixture): ObjectID => {
147
+ return new ObjectID(fixture.id);
148
+ });
149
+ }
150
+
151
+ async function renderUsers(
152
+ fixtures: Array<UserFixture>,
153
+ ): Promise<RenderResult> {
154
+ const result: RenderResult = render(<FetchUsers userIds={idsOf(fixtures)} />);
155
+
156
+ await waitFor(() => {
157
+ expect(result.queryByTestId("component-loader")).toBeNull();
158
+ });
159
+
160
+ return result;
161
+ }
162
+
163
+ describe("FetchUsers", () => {
164
+ beforeEach(() => {
165
+ getListMock.mockReset();
166
+ getListMock.mockImplementation(answerList as never);
167
+
168
+ jest
169
+ .spyOn(ProjectUtil, "getCurrentProjectId")
170
+ .mockReturnValue(new ObjectID(PROJECT_ID));
171
+ });
172
+
173
+ afterEach(() => {
174
+ cleanup();
175
+ jest.restoreAllMocks();
176
+ });
177
+
178
+ test("names the people even though the User model refuses to list them", async () => {
179
+ const { container } = await renderUsers([ZOE, MARCO]);
180
+
181
+ expect(container).toHaveTextContent(ZOE.name);
182
+ expect(container).toHaveTextContent(MARCO.name);
183
+ expect(container).not.toHaveTextContent(USER_MODEL_REFUSAL);
184
+ });
185
+
186
+ test("looks the people up once, through TeamMember in the current project, for exactly their ids", async () => {
187
+ await renderUsers([ZOE, ALICE]);
188
+
189
+ expect(getListMock).toHaveBeenCalledTimes(1);
190
+
191
+ const request: ListRequest = getListMock.mock.calls[0]![0] as ListRequest;
192
+ const userIdQuery: Includes = request.query["userId"] as Includes;
193
+
194
+ expect(request.modelType).toBe(TeamMember);
195
+ expect(String(request.query["projectId"])).toBe(PROJECT_ID);
196
+ expect(
197
+ userIdQuery.values
198
+ .map((value: string | ObjectID | number): string => {
199
+ return value.toString();
200
+ })
201
+ .sort(),
202
+ ).toEqual([ZOE.id, ALICE.id].sort());
203
+ expect(request.select).toEqual(
204
+ expect.objectContaining({
205
+ user: expect.objectContaining({ _id: true, name: true, email: true }),
206
+ }),
207
+ );
208
+ });
209
+
210
+ test("lists a person in several teams once, and everyone by name", async () => {
211
+ const { container } = await renderUsers([ZOE, ALICE, MARCO]);
212
+
213
+ const text: string = container.textContent || "";
214
+
215
+ expect(text.split(ALICE.name)).toHaveLength(2);
216
+ expect(text.indexOf(ALICE.name)).toBeLessThan(text.indexOf(MARCO.name));
217
+ expect(text.indexOf(MARCO.name)).toBeLessThan(text.indexOf(ZOE.name));
218
+ });
219
+
220
+ test("shows the error when the lookup fails", async () => {
221
+ getListMock.mockImplementation((async (): Promise<ListAnswer> => {
222
+ throw new Error(LOOKUP_FAILURE_MESSAGE);
223
+ }) as never);
224
+
225
+ const { container } = await renderUsers([ZOE]);
226
+
227
+ expect(container).toHaveTextContent(LOOKUP_FAILURE_MESSAGE);
228
+ expect(container).not.toHaveTextContent(ZOE.name);
229
+ });
230
+ });