forked from veridatum-labs/earnproof-backend
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdatabase-reset.spec.ts
More file actions
161 lines (146 loc) · 5.12 KB
/
Copy pathdatabase-reset.spec.ts
File metadata and controls
161 lines (146 loc) · 5.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
import {
DestructiveResetRefusedError,
assertResetAllowed,
databaseNameFromUrl,
} from "./database-reset";
/**
* Reset guard.
*
* These are the tests that stand between a contributor's muscle memory and a
* truncated production database, so they are written as a refusal matrix rather
* than as a happy path with a couple of negative cases: every way in has to be
* closed, not most of them.
*/
const LOCAL = "postgresql://earnproof:pw@localhost:5432/earnproof_test";
describe("assertResetAllowed", () => {
it("permits a locally hosted, disposably named database with confirmation", () => {
expect(() =>
assertResetAllowed({
nodeEnv: "development",
databaseUrl: LOCAL,
confirmDatabase: "earnproof_test",
}),
).not.toThrow();
});
it("refuses when NODE_ENV is production", () => {
expect(() =>
assertResetAllowed({
nodeEnv: "production",
databaseUrl: LOCAL,
confirmDatabase: "earnproof_test",
}),
).toThrow(DestructiveResetRefusedError);
});
it("refuses production even when the override is set", () => {
// The override exists for disposable environments whose hostnames are not
// local. It must not become a way to reset production.
expect(() =>
assertResetAllowed({
nodeEnv: "production",
databaseUrl: LOCAL,
confirmDatabase: "earnproof_test",
allowOverride: "true",
}),
).toThrow(/NODE_ENV is production/);
});
it.each([
["no database URL", { databaseUrl: undefined }],
["an empty database URL", { databaseUrl: " " }],
["an unparseable database URL", { databaseUrl: "not-a-url" }],
[
"a URL naming no database",
{ databaseUrl: "postgresql://earnproof:pw@localhost:5432" },
],
])("refuses %s", (_label, override) => {
expect(() =>
assertResetAllowed({
nodeEnv: "development",
confirmDatabase: "earnproof_test",
...override,
}),
).toThrow(DestructiveResetRefusedError);
});
it("refuses a production-shaped database name even on localhost", () => {
// The realistic accident: a laptop shell still holding a tunnelled
// connection to something that is not disposable.
expect(() =>
assertResetAllowed({
nodeEnv: "development",
databaseUrl: "postgresql://earnproof:pw@localhost:5432/earnproof",
confirmDatabase: "earnproof",
}),
).toThrow(/is not named as a test, dev or local database/);
});
it("refuses a remote host by default", () => {
expect(() =>
assertResetAllowed({
nodeEnv: "development",
databaseUrl: "postgresql://earnproof:pw@db.example.com:5432/earnproof_test",
confirmDatabase: "earnproof_test",
}),
).toThrow(/is not recognised as local/);
});
it("allows a remote host only with an explicit override", () => {
expect(() =>
assertResetAllowed({
nodeEnv: "test",
databaseUrl: "postgresql://earnproof:pw@db.example.com:5432/earnproof_ci",
confirmDatabase: "earnproof_ci",
allowOverride: "true",
}),
).not.toThrow();
});
it("refuses without a confirmation, and names what to type", () => {
expect(() =>
assertResetAllowed({ nodeEnv: "development", databaseUrl: LOCAL }),
).toThrow(/CONFIRM_RESET="earnproof_test"/);
});
it("refuses a confirmation that names a different database", () => {
// The exact case the confirmation exists for: the operator means the local
// database, the environment points at another one.
expect(() =>
assertResetAllowed({
nodeEnv: "development",
databaseUrl: LOCAL,
confirmDatabase: "earnproof_dev",
}),
).toThrow(/does not name the target database/);
});
it("refuses a truthy-looking confirmation that is not the name", () => {
for (const confirmation of ["true", "yes", "y", "1", "confirm"]) {
expect(() =>
assertResetAllowed({
nodeEnv: "development",
databaseUrl: LOCAL,
confirmDatabase: confirmation,
}),
).toThrow(DestructiveResetRefusedError);
}
});
it("never leaks the database password in a refusal message", () => {
// A safety message that prints the connection string turns a guard into a
// credential leak, in a terminal that is often pasted into an issue.
try {
assertResetAllowed({
nodeEnv: "development",
databaseUrl: "postgresql://earnproof:sup3r-s3cret@db.example.com:5432/earnproof_test",
confirmDatabase: "earnproof_test",
});
throw new Error("expected a refusal");
} catch (error) {
expect((error as Error).message).not.toContain("sup3r-s3cret");
expect((error as Error).message).toContain("db.example.com");
}
});
});
describe("databaseNameFromUrl", () => {
it("returns the database name", () => {
expect(databaseNameFromUrl(LOCAL)).toBe("earnproof_test");
});
it("returns nothing for a URL with no database or an unparseable one", () => {
expect(
databaseNameFromUrl("postgresql://earnproof:pw@localhost:5432"),
).toBeUndefined();
expect(databaseNameFromUrl("nonsense")).toBeUndefined();
});
});