@oneuptime/common 12.0.27 → 12.0.29
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/AnalyticsModels/RumSessionChunk.ts +52 -0
- package/Models/DatabaseModels/CloudResource.ts +17 -1
- package/Models/DatabaseModels/DashboardDomain.ts +43 -0
- package/Models/DatabaseModels/MonitorTemplate.ts +15 -3
- package/Models/DatabaseModels/RumApplication.ts +35 -2
- package/Models/DatabaseModels/StatusPageDomain.ts +43 -0
- package/Server/API/DashboardDomainAPI.ts +74 -0
- package/Server/API/MicrosoftTeamsAPI.ts +81 -180
- package/Server/API/StatusPageDomainAPI.ts +74 -0
- package/Server/API/TelemetryAPI.ts +104 -15
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790200000000-AllowNullMonitorNameOnMonitorTemplate.ts +43 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790300000000-AddCertificateReissueRequestedAtToDomains.ts +40 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
- package/Server/Middleware/ProjectAuthorization.ts +6 -1
- package/Server/Services/DashboardDomainService.ts +131 -0
- package/Server/Services/LogPipelineProcessorService.ts +88 -0
- package/Server/Services/MonitorTemplateService.ts +70 -11
- package/Server/Services/StatusPageDomainService.ts +163 -3
- package/Server/Services/StatusPagePrivateUserSessionService.ts +197 -56
- package/Server/Types/Domain.ts +17 -0
- package/Server/Utils/APIKey/AccessPermission.ts +24 -0
- package/Server/Utils/Greenlock/Greenlock.ts +156 -58
- package/Server/Utils/LogPipelineProcessorValidation.ts +112 -0
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.ts +1094 -45
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.ts +153 -17
- package/Server/Utils/SessionReplay/SessionReplayGateCache.ts +12 -5
- package/Server/Utils/SessionReplay/SessionReplayIdentity.ts +102 -0
- package/Server/Utils/SessionReplay/SessionReplayReadService.ts +11 -2
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.ts +23 -11
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.ts +0 -170
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Authorization.ts +158 -0
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.ts +23 -11
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +35 -13
- package/Tests/App/Dashboard/MonitorTemplateColumnAndFacet.test.tsx +505 -0
- package/Tests/App/StatusPage/StatusPageLoginCodeBootstrap.test.ts +106 -0
- package/Tests/App/StatusPage/StatusPageLoginCodeUtil.test.ts +84 -0
- package/Tests/App/StatusPage/StatusPageRedirectSafety.test.ts +119 -0
- package/Tests/Models/DatabaseModels/SessionReplayModels.test.ts +81 -0
- package/Tests/Models/MonitorTemplateMonitorNameColumn.test.ts +258 -0
- package/Tests/Server/API/CustomDomainReissueSslAPI.test.ts +469 -0
- package/Tests/Server/API/MicrosoftTeamsBotMessagesEndpoint.test.ts +729 -0
- package/Tests/Server/API/MicrosoftTeamsBotTestEndpoint.test.ts +26 -0
- package/Tests/Server/API/MicrosoftTeamsLegacyWebhookRemoval.test.ts +402 -0
- package/Tests/Server/API/SessionReplayAPI.test.ts +232 -0
- package/Tests/Server/Middleware/ProjectAuthorizationApiKeyMiddleware.test.ts +4 -0
- package/Tests/Server/Services/AddCertificateReissueRequestedAtToDomainsMigration.test.ts +287 -0
- package/Tests/Server/Services/CustomDomainCertificateReissue.test.ts +477 -0
- package/Tests/Server/Services/LogPipelineProcessorSaveValidation.test.ts +249 -0
- package/Tests/Server/Services/MonitorTemplateServiceBulkSync.test.ts +549 -0
- package/Tests/Server/Services/MonitorTemplateServiceNetworkDeviceSync.test.ts +16 -3
- package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +57 -0
- package/Tests/Server/Services/SecurityEventLastErrorColumnWidth.test.ts +151 -15
- package/Tests/Server/Services/StatusPagePrivateUserSessionService.test.ts +587 -0
- package/Tests/Server/Types/Database/Permissions/ApiKeyFileAccess.test.ts +286 -0
- package/Tests/Server/Types/Database/Permissions/MonitorTemplateColumnAccess.test.ts +328 -0
- package/Tests/Server/Types/Database/QueryHelperFindWithSameTextAndIsNull.test.ts +83 -0
- package/Tests/Server/Utils/AI/SRE/ConfidenceSignal.test.ts +377 -0
- package/Tests/Server/Utils/APIKey/AccessPermission.test.ts +16 -1
- package/Tests/Server/Utils/Greenlock/CertificateRenewalSchedule.test.ts +250 -0
- package/Tests/Server/Utils/LogPipelineProcessorValidation.test.ts +198 -0
- package/Tests/Server/Utils/SecurityEvent/ConnectorErrorMessage.test.ts +48 -9
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsAuth.test.ts +726 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsClient.test.ts +74 -11
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsErrorHandling.test.ts +1107 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPoller.test.ts +20 -3
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerFailureTaxonomy.test.ts +51 -11
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerHardening.test.ts +1246 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsRequestContract.test.ts +961 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsResponseParsing.test.ts +653 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsActionAuthorization.test.ts +880 -0
- package/Tests/Types/API/HTTPResponse.test.ts +175 -0
- package/Tests/Types/API/Route.test.ts +36 -4
- package/Tests/Types/Database/DatabaseProperty.test.ts +171 -0
- package/Tests/Types/DateLocalShortDateTimeString.test.ts +518 -0
- package/Tests/Types/DateLocalTimeString.test.ts +259 -0
- package/Tests/Types/DateUserPrefers12HourFormat.test.ts +316 -0
- package/Tests/UI/Components/LogsHistogram.test.tsx +41 -2
- package/Tests/UI/Components/LogsViewerEmptyStateTimeRange.test.tsx +212 -0
- package/Tests/UI/Components/TelemetryChartClockFormat.test.tsx +359 -0
- package/Tests/UI/Components/TimeRangePickerClockFormat.test.tsx +422 -0
- package/Tests/UI/Components/TimeRangePickerDropdown.test.tsx +146 -8
- package/Tests/UI/MicrosoftTeams/MicrosoftTeamsMessagingEndpointGuidance.test.tsx +520 -0
- package/Tests/UI/Utils/Navigation.test.ts +82 -0
- package/Tests/Utils/Array.test.ts +100 -0
- package/Tests/Utils/CertificateReissue.test.ts +225 -0
- package/Tests/Utils/Grok/Grok.test.ts +492 -0
- package/Tests/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.test.ts +181 -13
- package/Types/API/Route.ts +20 -5
- package/Types/Date.ts +143 -13
- package/Types/Rum/SessionReplay.ts +76 -1
- package/UI/Components/Date/TimeRangePickerDropdown.tsx +9 -5
- package/UI/Components/LogsViewer/LogsViewer.tsx +12 -7
- package/UI/Components/LogsViewer/components/HistogramTooltip.tsx +18 -17
- package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +21 -28
- package/UI/Components/LogsViewer/components/LogsHistogram.tsx +2 -4
- package/UI/Components/TelemetryViewer/components/TelemetryHistogram.tsx +2 -4
- package/UI/Components/TelemetryViewer/components/TelemetryHistogramTooltip.tsx +17 -16
- package/UI/Utils/Navigation.ts +42 -0
- package/Utils/Array.ts +37 -0
- package/Utils/CertificateReissue.ts +128 -0
- package/Utils/Grok/Grok.ts +461 -0
- package/Utils/Grok/GrokPatterns.ts +118 -0
- package/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.ts +58 -6
- package/build/dist/Models/AnalyticsModels/RumSessionChunk.js +48 -0
- package/build/dist/Models/AnalyticsModels/RumSessionChunk.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CloudResource.js +19 -2
- package/build/dist/Models/DatabaseModels/CloudResource.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DashboardDomain.js +44 -0
- package/build/dist/Models/DatabaseModels/DashboardDomain.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MonitorTemplate.js +17 -4
- package/build/dist/Models/DatabaseModels/MonitorTemplate.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RumApplication.js +37 -3
- package/build/dist/Models/DatabaseModels/RumApplication.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageDomain.js +44 -0
- package/build/dist/Models/DatabaseModels/StatusPageDomain.js.map +1 -1
- package/build/dist/Server/API/DashboardDomainAPI.js +43 -1
- package/build/dist/Server/API/DashboardDomainAPI.js.map +1 -1
- package/build/dist/Server/API/MicrosoftTeamsAPI.js +74 -118
- package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageDomainAPI.js +43 -1
- package/build/dist/Server/API/StatusPageDomainAPI.js.map +1 -1
- package/build/dist/Server/API/TelemetryAPI.js +67 -14
- package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790200000000-AllowNullMonitorNameOnMonitorTemplate.js +34 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790200000000-AllowNullMonitorNameOnMonitorTemplate.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790300000000-AddCertificateReissueRequestedAtToDomains.js +28 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790300000000-AddCertificateReissueRequestedAtToDomains.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/ProjectAuthorization.js +6 -1
- package/build/dist/Server/Middleware/ProjectAuthorization.js.map +1 -1
- package/build/dist/Server/Services/DashboardDomainService.js +104 -0
- package/build/dist/Server/Services/DashboardDomainService.js.map +1 -1
- package/build/dist/Server/Services/LogPipelineProcessorService.js +65 -0
- package/build/dist/Server/Services/LogPipelineProcessorService.js.map +1 -1
- package/build/dist/Server/Services/MonitorTemplateService.js +57 -11
- package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageDomainService.js +132 -3
- package/build/dist/Server/Services/StatusPageDomainService.js.map +1 -1
- package/build/dist/Server/Services/StatusPagePrivateUserSessionService.js +112 -32
- package/build/dist/Server/Services/StatusPagePrivateUserSessionService.js.map +1 -1
- package/build/dist/Server/Types/Domain.js +16 -0
- package/build/dist/Server/Types/Domain.js.map +1 -1
- package/build/dist/Server/Utils/APIKey/AccessPermission.js +24 -0
- package/build/dist/Server/Utils/APIKey/AccessPermission.js.map +1 -1
- package/build/dist/Server/Utils/Greenlock/Greenlock.js +110 -35
- package/build/dist/Server/Utils/Greenlock/Greenlock.js.map +1 -1
- package/build/dist/Server/Utils/LogPipelineProcessorValidation.js +77 -0
- package/build/dist/Server/Utils/LogPipelineProcessorValidation.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.js +777 -36
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js +108 -17
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js.map +1 -1
- package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCache.js.map +1 -1
- package/build/dist/Server/Utils/SessionReplay/SessionReplayIdentity.js +59 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayIdentity.js.map +1 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js +9 -2
- package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js +17 -6
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js +0 -159
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Authorization.js +128 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Authorization.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js +17 -6
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +25 -13
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Types/API/Route.js +16 -5
- package/build/dist/Types/API/Route.js.map +1 -1
- package/build/dist/Types/Date.js +115 -13
- package/build/dist/Types/Date.js.map +1 -1
- package/build/dist/Types/Rum/SessionReplay.js +38 -0
- package/build/dist/Types/Rum/SessionReplay.js.map +1 -1
- package/build/dist/UI/Components/Date/TimeRangePickerDropdown.js +9 -5
- package/build/dist/UI/Components/Date/TimeRangePickerDropdown.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js +12 -7
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/HistogramTooltip.js +15 -14
- package/build/dist/UI/Components/LogsViewer/components/HistogramTooltip.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +17 -22
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js +2 -4
- package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js +2 -4
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogramTooltip.js +15 -14
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogramTooltip.js.map +1 -1
- package/build/dist/UI/Utils/Navigation.js +30 -0
- package/build/dist/UI/Utils/Navigation.js.map +1 -1
- package/build/dist/Utils/Array.js +25 -0
- package/build/dist/Utils/Array.js.map +1 -1
- package/build/dist/Utils/CertificateReissue.js +97 -0
- package/build/dist/Utils/CertificateReissue.js.map +1 -0
- package/build/dist/Utils/Grok/Grok.js +324 -0
- package/build/dist/Utils/Grok/Grok.js.map +1 -0
- package/build/dist/Utils/Grok/GrokPatterns.js +112 -0
- package/build/dist/Utils/Grok/GrokPatterns.js.map +1 -0
- package/build/dist/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.js +63 -3
- package/build/dist/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.js.map +1 -1
- package/package.json +1 -1
- package/UI/Utils/JsonWebToken.ts +0 -14
- package/build/dist/UI/Utils/JsonWebToken.js +0 -10
- package/build/dist/UI/Utils/JsonWebToken.js.map +0 -1
|
@@ -197,6 +197,10 @@ describe("ProjectMiddleware.isValidProjectIdAndApiKeyMiddleware", () => {
|
|
|
197
197
|
oneUptimeRequest.userGlobalAccessPermission?.globalPermissions,
|
|
198
198
|
).not.toContain(Permission.ProjectOwner);
|
|
199
199
|
|
|
200
|
+
expect(
|
|
201
|
+
oneUptimeRequest.userGlobalAccessPermission?.globalPermissions,
|
|
202
|
+
).toContain(Permission.AuthenticatedRequest);
|
|
203
|
+
|
|
200
204
|
const tenantAccessPermission:
|
|
201
205
|
| Dictionary<UserTenantAccessPermission>
|
|
202
206
|
| undefined = oneUptimeRequest.userTenantAccessPermission;
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { AddCertificateReissueRequestedAtToDomains1790300000000 } from "../../../Server/Infrastructure/Postgres/SchemaMigrations/1790300000000-AddCertificateReissueRequestedAtToDomains";
|
|
2
|
+
import SchemaMigrations from "../../../Server/Infrastructure/Postgres/SchemaMigrations/Index";
|
|
3
|
+
import StatusPageDomain from "../../../Models/DatabaseModels/StatusPageDomain";
|
|
4
|
+
import DashboardDomain from "../../../Models/DatabaseModels/DashboardDomain";
|
|
5
|
+
import BaseModel from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
|
|
6
|
+
import ColumnType from "../../../Types/Database/ColumnType";
|
|
7
|
+
import { TableColumnMetadata } from "../../../Types/Database/TableColumn";
|
|
8
|
+
import TableColumnType from "../../../Types/Database/TableColumnType";
|
|
9
|
+
import Permission from "../../../Types/Permission";
|
|
10
|
+
import {
|
|
11
|
+
MigrationInterface,
|
|
12
|
+
QueryRunner,
|
|
13
|
+
getMetadataArgsStorage,
|
|
14
|
+
} from "typeorm";
|
|
15
|
+
import type { ColumnMetadataArgs } from "typeorm/metadata-args/ColumnMetadataArgs";
|
|
16
|
+
import { describe, expect, test } from "@jest/globals";
|
|
17
|
+
|
|
18
|
+
/*
|
|
19
|
+
* The column behind the reissue cooldown, on both custom-domain tables.
|
|
20
|
+
*
|
|
21
|
+
* certificateReissueRequestedAt is the only durable state the throttle has.
|
|
22
|
+
* Three things have to hold or a deployed installation breaks on upgrade:
|
|
23
|
+
*
|
|
24
|
+
* 1. up() adds it to BOTH tables, nullable with no default. NULL means
|
|
25
|
+
* "never reissued", which is true of every domain that exists the day
|
|
26
|
+
* this ships and is what lets the first press of the button through. A
|
|
27
|
+
* NOT NULL DEFAULT now() would put every existing customer into a
|
|
28
|
+
* cooldown they never triggered.
|
|
29
|
+
* 2. down() removes exactly what up() added.
|
|
30
|
+
* 3. the migration is registered in SchemaMigrations/Index.ts — an
|
|
31
|
+
* unregistered migration never runs on boot, so the reissue route's
|
|
32
|
+
* SELECT and conditional UPDATE would 500 on a column that is not there.
|
|
33
|
+
*
|
|
34
|
+
* The model side is asserted alongside it, because a column that exists in
|
|
35
|
+
* Postgres and not on the entity (or vice versa) is the same outage from the
|
|
36
|
+
* customer's side.
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
const MIGRATION_NAME: string =
|
|
40
|
+
"AddCertificateReissueRequestedAtToDomains1790300000000";
|
|
41
|
+
|
|
42
|
+
const COLUMN_NAME: string = "certificateReissueRequestedAt";
|
|
43
|
+
|
|
44
|
+
type MakeQueryRunnerResult = {
|
|
45
|
+
runner: QueryRunner;
|
|
46
|
+
statements: Array<string>;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
type MakeQueryRunnerFunction = () => MakeQueryRunnerResult;
|
|
50
|
+
|
|
51
|
+
const makeQueryRunner: MakeQueryRunnerFunction = (): MakeQueryRunnerResult => {
|
|
52
|
+
const statements: Array<string> = [];
|
|
53
|
+
|
|
54
|
+
const query: (...args: Array<unknown>) => Promise<undefined> = (
|
|
55
|
+
...args: Array<unknown>
|
|
56
|
+
): Promise<undefined> => {
|
|
57
|
+
statements.push(String(args[0]));
|
|
58
|
+
return Promise.resolve(undefined);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
runner: { query } as unknown as QueryRunner,
|
|
63
|
+
statements,
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
describe(`${MIGRATION_NAME} — SQL contract`, () => {
|
|
68
|
+
test("up() adds the column to both domain tables", async () => {
|
|
69
|
+
const { runner, statements } = makeQueryRunner();
|
|
70
|
+
|
|
71
|
+
await new AddCertificateReissueRequestedAtToDomains1790300000000().up(
|
|
72
|
+
runner,
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
expect(statements).toEqual([
|
|
76
|
+
`ALTER TABLE "StatusPageDomain" ADD "${COLUMN_NAME}" TIMESTAMP WITH TIME ZONE`,
|
|
77
|
+
`ALTER TABLE "DashboardDomain" ADD "${COLUMN_NAME}" TIMESTAMP WITH TIME ZONE`,
|
|
78
|
+
]);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
/*
|
|
82
|
+
* NULL is a meaning on this column: the claim query is
|
|
83
|
+
* `certificateReissueRequestedAt <= :cutoff OR IS NULL`, and NULL is the
|
|
84
|
+
* half that says "never reissued, go ahead". A DEFAULT would silently put
|
|
85
|
+
* every domain that already exists into a cooldown on the day of the
|
|
86
|
+
* upgrade, and the first customer to press the button would be refused for
|
|
87
|
+
* something they never did.
|
|
88
|
+
*/
|
|
89
|
+
test("the column is nullable with no default and no backfill", async () => {
|
|
90
|
+
const { runner, statements } = makeQueryRunner();
|
|
91
|
+
|
|
92
|
+
await new AddCertificateReissueRequestedAtToDomains1790300000000().up(
|
|
93
|
+
runner,
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
for (const statement of statements) {
|
|
97
|
+
expect(statement).not.toContain("NOT NULL");
|
|
98
|
+
expect(statement).not.toContain("DEFAULT");
|
|
99
|
+
expect(statement).not.toContain("UPDATE");
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test("it is a timestamp with a timezone, so a cooldown means the same everywhere", async () => {
|
|
104
|
+
const { runner, statements } = makeQueryRunner();
|
|
105
|
+
|
|
106
|
+
await new AddCertificateReissueRequestedAtToDomains1790300000000().up(
|
|
107
|
+
runner,
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
for (const statement of statements) {
|
|
111
|
+
expect(statement).toContain("TIMESTAMP WITH TIME ZONE");
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test("down() drops exactly what up() added, in reverse order", async () => {
|
|
116
|
+
const { runner, statements } = makeQueryRunner();
|
|
117
|
+
|
|
118
|
+
await new AddCertificateReissueRequestedAtToDomains1790300000000().down(
|
|
119
|
+
runner,
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
expect(statements).toEqual([
|
|
123
|
+
`ALTER TABLE "DashboardDomain" DROP COLUMN "${COLUMN_NAME}"`,
|
|
124
|
+
`ALTER TABLE "StatusPageDomain" DROP COLUMN "${COLUMN_NAME}"`,
|
|
125
|
+
]);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test("up() and down() name the same tables", async () => {
|
|
129
|
+
const { runner: upRunner, statements: upStatements } = makeQueryRunner();
|
|
130
|
+
const { runner: downRunner, statements: downStatements } =
|
|
131
|
+
makeQueryRunner();
|
|
132
|
+
|
|
133
|
+
await new AddCertificateReissueRequestedAtToDomains1790300000000().up(
|
|
134
|
+
upRunner,
|
|
135
|
+
);
|
|
136
|
+
await new AddCertificateReissueRequestedAtToDomains1790300000000().down(
|
|
137
|
+
downRunner,
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
type TablesInFunction = (statements: Array<string>) => Array<string>;
|
|
141
|
+
|
|
142
|
+
const tablesIn: TablesInFunction = (
|
|
143
|
+
statements: Array<string>,
|
|
144
|
+
): Array<string> => {
|
|
145
|
+
return statements
|
|
146
|
+
.map((sql: string) => {
|
|
147
|
+
return sql.split(`ALTER TABLE "`)[1]!.split('"')[0]!;
|
|
148
|
+
})
|
|
149
|
+
.sort();
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
expect(tablesIn(downStatements)).toEqual(tablesIn(upStatements));
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
describe(`${MIGRATION_NAME} — registration`, () => {
|
|
157
|
+
/*
|
|
158
|
+
* The step AGENTS.md calls out and the one that fails silently: a migration
|
|
159
|
+
* that is not in this array never runs, so the column is missing in a real
|
|
160
|
+
* deployment while the route both SELECTs and UPDATEs it.
|
|
161
|
+
*/
|
|
162
|
+
test("the migration is registered so it runs on boot", () => {
|
|
163
|
+
const names: Array<string> = SchemaMigrations.map(
|
|
164
|
+
(migration: new () => MigrationInterface): string => {
|
|
165
|
+
return migration.name;
|
|
166
|
+
},
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
expect(names).toContain(MIGRATION_NAME);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
test("it is registered exactly once", () => {
|
|
173
|
+
const occurrences: number = SchemaMigrations.filter(
|
|
174
|
+
(migration: new () => MigrationInterface): boolean => {
|
|
175
|
+
return migration.name === MIGRATION_NAME;
|
|
176
|
+
},
|
|
177
|
+
).length;
|
|
178
|
+
|
|
179
|
+
expect(occurrences).toBe(1);
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
type DomainModelSpec = [
|
|
184
|
+
string,
|
|
185
|
+
new () => BaseModel,
|
|
186
|
+
string,
|
|
187
|
+
Permission,
|
|
188
|
+
Permission,
|
|
189
|
+
];
|
|
190
|
+
|
|
191
|
+
const domainModels: Array<DomainModelSpec> = [
|
|
192
|
+
[
|
|
193
|
+
"StatusPageDomain",
|
|
194
|
+
StatusPageDomain,
|
|
195
|
+
"StatusPageDomain",
|
|
196
|
+
Permission.ReadStatusPageDomain,
|
|
197
|
+
Permission.EditStatusPageDomain,
|
|
198
|
+
],
|
|
199
|
+
[
|
|
200
|
+
"DashboardDomain",
|
|
201
|
+
DashboardDomain,
|
|
202
|
+
"DashboardDomain",
|
|
203
|
+
Permission.ReadDashboardDomain,
|
|
204
|
+
Permission.EditDashboardDomain,
|
|
205
|
+
],
|
|
206
|
+
];
|
|
207
|
+
|
|
208
|
+
describe.each(domainModels)(
|
|
209
|
+
"%s.certificateReissueRequestedAt",
|
|
210
|
+
(
|
|
211
|
+
_name: string,
|
|
212
|
+
modelType: new () => BaseModel,
|
|
213
|
+
tableName: string,
|
|
214
|
+
readPermission: Permission,
|
|
215
|
+
editPermission: Permission,
|
|
216
|
+
) => {
|
|
217
|
+
test("the entity declares the column the migration adds", () => {
|
|
218
|
+
const columns: Array<ColumnMetadataArgs> =
|
|
219
|
+
getMetadataArgsStorage().columns.filter(
|
|
220
|
+
(column: ColumnMetadataArgs) => {
|
|
221
|
+
return (column.target as { name?: string })?.name === tableName;
|
|
222
|
+
},
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
const column: ColumnMetadataArgs | undefined = columns.find(
|
|
226
|
+
(candidate: ColumnMetadataArgs) => {
|
|
227
|
+
return candidate.propertyName === COLUMN_NAME;
|
|
228
|
+
},
|
|
229
|
+
);
|
|
230
|
+
|
|
231
|
+
expect(column).toBeDefined();
|
|
232
|
+
expect(column!.options.type).toBe(ColumnType.Date);
|
|
233
|
+
expect(column!.options.nullable).toBe(true);
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
test("it is a date column in the model metadata", () => {
|
|
237
|
+
const metadata: TableColumnMetadata =
|
|
238
|
+
new modelType().getTableColumnMetadata(
|
|
239
|
+
COLUMN_NAME,
|
|
240
|
+
) as TableColumnMetadata;
|
|
241
|
+
|
|
242
|
+
expect(metadata).toBeDefined();
|
|
243
|
+
expect(metadata.type).toBe(TableColumnType.Date);
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
/*
|
|
247
|
+
* Computed, so it never appears on a create or update payload. The
|
|
248
|
+
* throttle is only a throttle while the customer cannot write the column
|
|
249
|
+
* that holds it — an editable stamp is a cooldown anyone can clear.
|
|
250
|
+
*/
|
|
251
|
+
test("it is computed, so a customer cannot write it", () => {
|
|
252
|
+
const metadata: TableColumnMetadata =
|
|
253
|
+
new modelType().getTableColumnMetadata(
|
|
254
|
+
COLUMN_NAME,
|
|
255
|
+
) as TableColumnMetadata;
|
|
256
|
+
|
|
257
|
+
expect(metadata.computed).toBe(true);
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
test("nobody can create or update it through the CRUD API", () => {
|
|
261
|
+
const accessControl: {
|
|
262
|
+
create: Array<Permission>;
|
|
263
|
+
read: Array<Permission>;
|
|
264
|
+
update: Array<Permission>;
|
|
265
|
+
} = new modelType().getColumnAccessControlFor(COLUMN_NAME)!;
|
|
266
|
+
|
|
267
|
+
expect(accessControl.create).toEqual([]);
|
|
268
|
+
expect(accessControl.update).toEqual([]);
|
|
269
|
+
expect(accessControl.update).not.toContain(editPermission);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
/*
|
|
273
|
+
* Readable, though: the dashboard renders the countdown from this value,
|
|
274
|
+
* so a viewer who can see the domain has to be able to see when its
|
|
275
|
+
* cooldown ends.
|
|
276
|
+
*/
|
|
277
|
+
test("anyone who can read the domain can read the stamp", () => {
|
|
278
|
+
const accessControl: {
|
|
279
|
+
read: Array<Permission>;
|
|
280
|
+
} = new modelType().getColumnAccessControlFor(COLUMN_NAME)!;
|
|
281
|
+
|
|
282
|
+
expect(accessControl.read).toContain(readPermission);
|
|
283
|
+
expect(accessControl.read).toContain(Permission.ProjectOwner);
|
|
284
|
+
expect(accessControl.read).toContain(Permission.ProjectAdmin);
|
|
285
|
+
});
|
|
286
|
+
},
|
|
287
|
+
);
|