@saltcorn/admin-models 1.6.3-beta.1 → 1.7.0-alpha.1

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 (99) hide show
  1. package/cjs/index.cjs +18 -0
  2. package/cjs/models/backup-retention.cjs +18 -0
  3. package/cjs/models/backup.cjs +18 -0
  4. package/cjs/models/config-check.cjs +18 -0
  5. package/cjs/models/file-globs.cjs +18 -0
  6. package/cjs/models/pack.cjs +18 -0
  7. package/cjs/models/snapshot.cjs +18 -0
  8. package/cjs/models/tenant.cjs +18 -0
  9. package/cjs/models/zip-extract.cjs +18 -0
  10. package/cjs/models/zip-format.cjs +18 -0
  11. package/cjs/models/zip-worker.cjs +18 -0
  12. package/cjs/models/zip-writer.cjs +18 -0
  13. package/cjs/models/zip.cjs +18 -0
  14. package/dist/index.d.ts +6 -5
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +12 -18
  17. package/dist/index.js.map +1 -1
  18. package/dist/models/backup-retention.d.ts +57 -0
  19. package/dist/models/backup-retention.d.ts.map +1 -0
  20. package/dist/models/backup-retention.js +108 -0
  21. package/dist/models/backup-retention.js.map +1 -0
  22. package/dist/models/backup.d.ts +7 -3
  23. package/dist/models/backup.d.ts.map +1 -1
  24. package/dist/models/backup.js +479 -409
  25. package/dist/models/backup.js.map +1 -1
  26. package/dist/models/config-check.d.ts +2 -1
  27. package/dist/models/config-check.d.ts.map +1 -1
  28. package/dist/models/config-check.js +16 -23
  29. package/dist/models/config-check.js.map +1 -1
  30. package/dist/models/file-globs.d.ts +34 -0
  31. package/dist/models/file-globs.d.ts.map +1 -0
  32. package/dist/models/file-globs.js +47 -0
  33. package/dist/models/file-globs.js.map +1 -0
  34. package/dist/models/pack.d.ts +3 -2
  35. package/dist/models/pack.d.ts.map +1 -1
  36. package/dist/models/pack.js +147 -151
  37. package/dist/models/pack.js.map +1 -1
  38. package/dist/models/snapshot.d.ts +1 -1
  39. package/dist/models/snapshot.d.ts.map +1 -1
  40. package/dist/models/snapshot.js +26 -29
  41. package/dist/models/snapshot.js.map +1 -1
  42. package/dist/models/tenant.d.ts +1 -1
  43. package/dist/models/tenant.d.ts.map +1 -1
  44. package/dist/models/tenant.js +45 -48
  45. package/dist/models/tenant.js.map +1 -1
  46. package/dist/models/zip-extract.d.ts +14 -0
  47. package/dist/models/zip-extract.d.ts.map +1 -0
  48. package/dist/models/zip-extract.js +110 -0
  49. package/dist/models/zip-extract.js.map +1 -0
  50. package/dist/models/zip-format.d.ts +57 -0
  51. package/dist/models/zip-format.d.ts.map +1 -0
  52. package/dist/models/zip-format.js +106 -0
  53. package/dist/models/zip-format.js.map +1 -0
  54. package/dist/models/zip-worker.d.ts +2 -0
  55. package/dist/models/zip-worker.d.ts.map +1 -0
  56. package/dist/models/zip-worker.js +177 -0
  57. package/dist/models/zip-worker.js.map +1 -0
  58. package/dist/models/zip-writer.d.ts +75 -0
  59. package/dist/models/zip-writer.d.ts.map +1 -0
  60. package/dist/models/zip-writer.js +321 -0
  61. package/dist/models/zip-writer.js.map +1 -0
  62. package/dist/models/zip.d.ts +101 -0
  63. package/dist/models/zip.d.ts.map +1 -0
  64. package/dist/models/zip.js +211 -0
  65. package/dist/models/zip.js.map +1 -0
  66. package/dist/tests/backup-retention.test.d.ts +2 -0
  67. package/dist/tests/backup-retention.test.d.ts.map +1 -0
  68. package/dist/tests/backup-retention.test.js +134 -0
  69. package/dist/tests/backup-retention.test.js.map +1 -0
  70. package/dist/tests/backup.test.d.ts +2 -0
  71. package/dist/tests/backup.test.d.ts.map +1 -0
  72. package/dist/tests/backup.test.js +385 -0
  73. package/dist/tests/backup.test.js.map +1 -0
  74. package/dist/tests/cfgcheck.test.d.ts +2 -0
  75. package/dist/tests/cfgcheck.test.d.ts.map +1 -0
  76. package/dist/tests/cfgcheck.test.js +32 -0
  77. package/dist/tests/cfgcheck.test.js.map +1 -0
  78. package/dist/tests/file-globs.test.d.ts +2 -0
  79. package/dist/tests/file-globs.test.d.ts.map +1 -0
  80. package/dist/tests/file-globs.test.js +66 -0
  81. package/dist/tests/file-globs.test.js.map +1 -0
  82. package/dist/tests/pack.test.d.ts +2 -0
  83. package/dist/tests/pack.test.d.ts.map +1 -0
  84. package/dist/tests/pack.test.js +780 -0
  85. package/dist/tests/pack.test.js.map +1 -0
  86. package/dist/tests/random.test.d.ts +2 -0
  87. package/dist/tests/random.test.d.ts.map +1 -0
  88. package/dist/tests/random.test.js +150 -0
  89. package/dist/tests/random.test.js.map +1 -0
  90. package/dist/tests/tenant.test.d.ts +2 -0
  91. package/dist/tests/tenant.test.d.ts.map +1 -0
  92. package/dist/tests/tenant.test.js +106 -0
  93. package/dist/tests/tenant.test.js.map +1 -0
  94. package/dist/tests/zip.test.d.ts +2 -0
  95. package/dist/tests/zip.test.d.ts.map +1 -0
  96. package/dist/tests/zip.test.js +319 -0
  97. package/dist/tests/zip.test.js.map +1 -0
  98. package/gen-cjs-shims.cjs +71 -0
  99. package/package.json +39 -29
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=backup-retention.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backup-retention.test.d.ts","sourceRoot":"","sources":["../../tests/backup-retention.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,134 @@
1
+ import { selectBackupsToDelete, selectBackupsToDeleteGrouped, } from "../models/backup-retention.js";
2
+ import { describe, it, expect } from "@saltcorn/db-common/test_expect";
3
+ const mkEntry = (iso, key) => ({
4
+ key: key || `sc-backup-Site-${iso}.zip`,
5
+ date: new Date(`${iso}T03:00:00Z`),
6
+ });
7
+ /** N consecutive daily backups ending at `end` (inclusive), newest last */
8
+ const dailySeries = (end, n, prefix = "Site") => {
9
+ const endDate = new Date(`${end}T03:00:00Z`);
10
+ const out = [];
11
+ for (let i = n - 1; i >= 0; i--) {
12
+ const d = new Date(endDate.getTime() - i * 86400000);
13
+ const iso = d.toISOString().slice(0, 10);
14
+ out.push({ key: `sc-backup-${prefix}-${iso}.zip`, date: d });
15
+ }
16
+ return out;
17
+ };
18
+ const policy = (p) => ({
19
+ keep_daily: 0,
20
+ keep_weekly: 0,
21
+ keep_monthly: 0,
22
+ keep_yearly: 0,
23
+ keep_min: 0,
24
+ ...p,
25
+ });
26
+ describe("selectBackupsToDelete", () => {
27
+ it("returns nothing for an empty list", () => {
28
+ expect(selectBackupsToDelete([], policy({ keep_daily: 7 }))).toEqual([]);
29
+ });
30
+ it("keeps the last N daily backups", () => {
31
+ const entries = dailySeries("2026-07-26", 30);
32
+ const del = selectBackupsToDelete(entries, policy({ keep_daily: 7 }));
33
+ expect(del).toHaveLength(23);
34
+ const deletedKeys = new Set(del.map((e) => e.key));
35
+ // the 7 newest must survive
36
+ for (const e of entries.slice(-7))
37
+ expect(deletedKeys.has(e.key)).toBe(false);
38
+ });
39
+ it("keeps one backup per ISO week for keep_weekly", () => {
40
+ const entries = dailySeries("2026-07-26", 28); // 4+ ISO weeks
41
+ const del = selectBackupsToDelete(entries, policy({ keep_weekly: 4 }));
42
+ const kept = entries.filter((e) => !del.includes(e));
43
+ expect(kept).toHaveLength(4);
44
+ // one kept backup per week, all on distinct days
45
+ const days = new Set(kept.map((e) => e.date.toISOString().slice(0, 10)));
46
+ expect(days.size).toBe(4);
47
+ });
48
+ it("a single backup can satisfy multiple tiers", () => {
49
+ const entries = [mkEntry("2026-07-26")];
50
+ const del = selectBackupsToDelete(entries, policy({
51
+ keep_daily: 7,
52
+ keep_weekly: 4,
53
+ keep_monthly: 12,
54
+ keep_yearly: 3,
55
+ }));
56
+ expect(del).toEqual([]);
57
+ });
58
+ it("combined GFS policy over a year of daily backups", () => {
59
+ const entries = dailySeries("2026-07-26", 365);
60
+ const del = selectBackupsToDelete(entries, policy({
61
+ keep_daily: 7,
62
+ keep_weekly: 4,
63
+ keep_monthly: 12,
64
+ keep_yearly: 3,
65
+ }));
66
+ const kept = entries.length - del.length;
67
+ // 7 daily + 4 weekly + 12 monthly + yearly, minus overlaps
68
+ expect(kept).toBeGreaterThanOrEqual(12);
69
+ expect(kept).toBeLessThanOrEqual(26);
70
+ });
71
+ it("keep_min prevents deleting the last backups even when all are old", () => {
72
+ // 5 backups, all several years old, policy window long passed
73
+ const entries = dailySeries("2020-01-05", 5);
74
+ const del = selectBackupsToDelete(entries, policy({ keep_daily: 7, keep_min: 3 }));
75
+ // keep_daily keeps 5 (each its own day-bucket within capacity 7)
76
+ expect(del).toEqual([]);
77
+ // stricter: only 1 daily slot, keep_min=3 → exactly 2 deleted
78
+ const del2 = selectBackupsToDelete(entries, policy({ keep_daily: 1, keep_min: 3 }));
79
+ expect(del2).toHaveLength(2);
80
+ });
81
+ it("never deletes everything when keep_min > 0", () => {
82
+ const entries = dailySeries("2019-06-01", 10);
83
+ const del = selectBackupsToDelete(entries, policy({ keep_min: 1 }));
84
+ expect(del).toHaveLength(9);
85
+ // the newest is the one retained
86
+ expect(del.map((e) => e.key)).not.toContain(entries[9].key);
87
+ });
88
+ it("keeps the newest backup of each of the last N months", () => {
89
+ // one backup every 5 days for a year
90
+ const entries = [];
91
+ const end = new Date("2026-07-26T03:00:00Z").getTime();
92
+ for (let i = 72; i >= 0; i--) {
93
+ const d = new Date(end - i * 5 * 86400000);
94
+ entries.push({
95
+ key: `sc-backup-Site-${d.toISOString().slice(0, 10)}.zip`,
96
+ date: d,
97
+ });
98
+ }
99
+ const del = selectBackupsToDelete(entries, policy({ keep_monthly: 3 }));
100
+ const kept = entries.filter((e) => !del.includes(e));
101
+ expect(kept).toHaveLength(3);
102
+ const months = new Set(kept.map((e) => e.date.toISOString().slice(0, 7)));
103
+ expect(months.size).toBe(3);
104
+ });
105
+ });
106
+ describe("selectBackupsToDeleteGrouped", () => {
107
+ it("applies the policy per tenant", () => {
108
+ const root = dailySeries("2026-07-26", 10, "Root");
109
+ const t1 = dailySeries("2026-07-26", 10, "tenant1");
110
+ const del = selectBackupsToDeleteGrouped([...root, ...t1], policy({ keep_daily: 7 }));
111
+ // 3 deleted per tenant — tenants do not steal each other's slots
112
+ expect(del).toHaveLength(6);
113
+ expect(del.filter((e) => e.key.includes("Root"))).toHaveLength(3);
114
+ expect(del.filter((e) => e.key.includes("tenant1"))).toHaveLength(3);
115
+ });
116
+ it("groups by basename, ignoring the key path prefix", () => {
117
+ const withPrefix = dailySeries("2026-07-26", 10).map((e) => ({
118
+ ...e,
119
+ key: `backups/prod/${e.key}`,
120
+ }));
121
+ const del = selectBackupsToDeleteGrouped(withPrefix, policy({ keep_daily: 7 }));
122
+ expect(del).toHaveLength(3);
123
+ });
124
+ it("groups non-matching filenames by their own basename", () => {
125
+ const odd = {
126
+ key: "manual-export.zip",
127
+ date: new Date("2020-01-01T00:00:00Z"),
128
+ };
129
+ const del = selectBackupsToDeleteGrouped([odd, ...dailySeries("2026-07-26", 3)], policy({ keep_daily: 1, keep_min: 1 }));
130
+ // the odd file forms its own group and is kept by its own keep_min
131
+ expect(del.map((e) => e.key)).not.toContain("manual-export.zip");
132
+ });
133
+ });
134
+ //# sourceMappingURL=backup-retention.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backup-retention.test.js","sourceRoot":"","sources":["../../tests/backup-retention.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=backup.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backup.test.d.ts","sourceRoot":"","sources":["../../tests/backup.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,385 @@
1
+ import db from "@saltcorn/data/db/index";
2
+ import { getState } from "@saltcorn/data/db/state";
3
+ import basePlugin from "@saltcorn/data/base-plugin";
4
+ getState().registerPlugin("base", basePlugin);
5
+ import backup from "../models/backup.js";
6
+ const { create_backup, restore, auto_backup_now } = backup;
7
+ import reset from "@saltcorn/data/db/reset_schema";
8
+ import fixtures from "@saltcorn/data/db/fixtures";
9
+ import { unlink, mkdtemp, writeFile, readdir, rm, stat } from "fs/promises";
10
+ import { join } from "path";
11
+ import { tmpdir } from "os";
12
+ import Table from "@saltcorn/data/models/table";
13
+ import View from "@saltcorn/data/models/view";
14
+ import User from "@saltcorn/data/models/user";
15
+ import * as config from "@saltcorn/data/models/config";
16
+ const { setConfig, getConfig } = config;
17
+ import Trigger from "@saltcorn/data/models/trigger";
18
+ import Library from "@saltcorn/data/models/library";
19
+ import MetaData from "@saltcorn/data/models/metadata";
20
+ import Role from "@saltcorn/data/models/role";
21
+ import WorkflowStep from "@saltcorn/data/models/workflow_step";
22
+ import { assertIsSet, assertsObjectIsUser, } from "@saltcorn/data/tests/assertions";
23
+ import { afterAll, describe, it, expect, beforeAll, jest, } from "@saltcorn/db-common/test_expect";
24
+ import Field from "@saltcorn/data/models/field";
25
+ import File from "@saltcorn/data/models/file";
26
+ import Zip from "adm-zip";
27
+ import * as mocks from "@saltcorn/data/tests/mocks";
28
+ const { mockReqRes, plugin_with_routes } = mocks;
29
+ afterAll(db.close);
30
+ beforeAll(async () => {
31
+ await reset();
32
+ await fixtures();
33
+ getState().registerPlugin("mock_plugin", plugin_with_routes());
34
+ });
35
+ jest.setTimeout(30000);
36
+ describe("Backup and restore", () => {
37
+ it("should create and restore backup", async () => {
38
+ await setConfig("site_name", "backups rule!");
39
+ await setConfig("menu_items", [
40
+ {
41
+ type: "Page",
42
+ label: "a_page",
43
+ min_role: 100,
44
+ pagename: "a_page",
45
+ },
46
+ {
47
+ url: "https://www.bbc.co.uk/news",
48
+ icon: "undefined",
49
+ text: "BBC",
50
+ type: "Link",
51
+ label: "BBC",
52
+ style: "",
53
+ location: "Standard",
54
+ min_role: 100,
55
+ },
56
+ ]);
57
+ const sn1 = await getConfig("site_name");
58
+ expect(sn1).toBe("backups rule!");
59
+ await Role.create({ role: "paid", id: 60 });
60
+ await Table.create("myblanktable", { min_role_read: 60 });
61
+ const vtbl = await Table.create("myversionedtable", {
62
+ min_role_read: 80,
63
+ versioned: true,
64
+ });
65
+ await Field.create({
66
+ name: "name",
67
+ type: "String",
68
+ table: vtbl,
69
+ });
70
+ await vtbl.insertRow({ name: "Fred" });
71
+ await vtbl.updateRow({ name: "Sam" }, 1);
72
+ await vtbl.insertRow({ name: 'My \nSp\\ecial "Friend"' });
73
+ await Trigger.create({
74
+ name: "footrig",
75
+ table_id: 1,
76
+ when_trigger: "Insert",
77
+ action: "run_js_code",
78
+ configuration: { code: "console.log('new user')" },
79
+ });
80
+ await Trigger.create({
81
+ name: "hourtrig",
82
+ when_trigger: "Hourly",
83
+ action: "run_js_code",
84
+ configuration: { code: "console.log('cuckoo')" },
85
+ });
86
+ const trigger = await Trigger.create({
87
+ action: "Workflow",
88
+ when_trigger: "Never",
89
+ name: "mywf",
90
+ });
91
+ await WorkflowStep.create({
92
+ trigger_id: trigger.id,
93
+ name: "first_step",
94
+ next_step: "second_step",
95
+ action_name: "run_js_code",
96
+ initial_step: true,
97
+ configuration: { code: `return {x:1}` },
98
+ });
99
+ await WorkflowStep.create({
100
+ trigger_id: trigger.id,
101
+ name: "second_step",
102
+ next_step: "third_step",
103
+ action_name: "run_js_code",
104
+ initial_step: false,
105
+ configuration: { code: `return {y:x+1}` },
106
+ });
107
+ await Library.create({
108
+ name: "foo",
109
+ icon: "fa-bar",
110
+ layout: { baz: "bar" },
111
+ });
112
+ await MetaData.create({
113
+ type: "PromptSummary",
114
+ name: "View45",
115
+ user_id: 1,
116
+ written_at: new Date(),
117
+ body: { foo: { bar: 1 }, baz: 7 },
118
+ });
119
+ await Table.create("JoeTable", {
120
+ provider_name: "provtab",
121
+ provider_cfg: { middle_name: "Robinette" },
122
+ });
123
+ await User.table.update({
124
+ min_role_read: 40,
125
+ description: "Users are the best",
126
+ });
127
+ await getState().refresh_tables();
128
+ const fnm = await create_backup();
129
+ const t1 = Table.findOne({ name: "books" });
130
+ assertIsSet(t1);
131
+ const t1c = await t1.countRows();
132
+ const v1 = await View.find();
133
+ expect(!!t1).toBe(true);
134
+ await reset();
135
+ const admu = await User.create({
136
+ email: "admin@foo.com",
137
+ password: "AhGGr6rhu45",
138
+ role_id: 1,
139
+ });
140
+ assertsObjectIsUser(admu);
141
+ expect(typeof admu.password).toBe("string");
142
+ expect(User.table.min_role_read).toBe(1);
143
+ const t2 = Table.findOne({ name: "books" });
144
+ expect(t2).toBe(null);
145
+ const sn0 = await getConfig("site_name");
146
+ expect(sn0).toBe("Saltcorn");
147
+ const menus0 = await getConfig("menu_items", []);
148
+ expect(menus0.length).toBe(7); // newly liberated menu items
149
+ //restore
150
+ const restore_res = await restore(fnm, (p) => { });
151
+ await unlink(fnm);
152
+ expect(restore_res).toBe(undefined);
153
+ const t3 = Table.findOne({ name: "books" });
154
+ assertIsSet(t3);
155
+ expect(!!t3).toBe(true);
156
+ const t5 = Table.findOne({ name: "myblanktable" });
157
+ assertIsSet(t5);
158
+ const t6 = Table.findOne({ name: "myversionedtable" });
159
+ assertIsSet(t6);
160
+ const vhist = await t6.get_history();
161
+ expect(vhist.length).toBe(3);
162
+ const t6row = await t6.getRow({ id: 2 });
163
+ assertIsSet(t6row);
164
+ expect(t6row.name).toBe('My \nSp\\ecial "Friend"');
165
+ expect(!!t5).toBe(true);
166
+ expect(t5.min_role_read).toBe(60);
167
+ const t3c = await t3.countRows();
168
+ expect(t1c).toBe(t3c);
169
+ const v2 = await View.find();
170
+ expect(v1.length).toBe(v2.length);
171
+ const sn = await getConfig("site_name");
172
+ expect(sn).toBe("backups rule!");
173
+ const menus = await getConfig("menu_items");
174
+ expect(menus.length).toBe(2);
175
+ expect(menus[0].type).toBe("Page");
176
+ expect(menus[0].pagename).toBe("a_page");
177
+ expect(menus[1].type).toBe("Link");
178
+ expect(menus[1].url).toBe("https://www.bbc.co.uk/news");
179
+ await t3.insertRow({ author: "Marcus Rediker", pages: 224 });
180
+ const staff = await User.findOne({ email: "staff@foo.com" });
181
+ expect(!!staff).toBe(true);
182
+ assertsObjectIsUser(staff);
183
+ expect(typeof staff.password).toBe("string");
184
+ const trig = await Trigger.findOne({ name: "footrig" });
185
+ expect(!!trig).toBe(true);
186
+ const htrig = await Trigger.findOne({ name: "hourtrig" });
187
+ expect(!!htrig).toBe(true);
188
+ const mywf = await Trigger.findOne({ name: "mywf" });
189
+ expect(!!mywf).toBe(true);
190
+ const mySteps = await WorkflowStep.find({ trigger_id: mywf.id });
191
+ expect(mySteps.length).toBe(2);
192
+ const lib = await Library.findOne({ name: "foo" });
193
+ expect(!!lib).toBe(true);
194
+ const md = await MetaData.findOne({ type: "PromptSummary" });
195
+ expect(!!md).toBe(true);
196
+ expect(md.body.foo.bar).toBe(1);
197
+ const tp = Table.findOne({ name: "JoeTable" });
198
+ expect(tp?.provider_name).toBe("provtab");
199
+ expect(tp?.provider_cfg?.middle_name).toBe("Robinette");
200
+ expect(staff.checkPassword("ghrarhr54hg")).toBe(true);
201
+ expect(User.table.min_role_read).toBe(40);
202
+ expect(User.table.description).toBe("Users are the best");
203
+ });
204
+ });
205
+ describe("auto backup retention to local directory", () => {
206
+ it("deletes backups not retained by the tiered policy", async () => {
207
+ const dir = await mkdtemp(join(tmpdir(), "sc-backup-retention-"));
208
+ const prefix = getState().getConfig("backup_file_prefix");
209
+ await getState().setConfig("site_name", "RetTest");
210
+ await getState().setConfig("auto_backup_destination", "Local directory");
211
+ await getState().setConfig("auto_backup_directory", dir);
212
+ await getState().setConfig("auto_backup_retention_mode", "Tiered (GFS)");
213
+ await getState().setConfig("auto_backup_keep_daily", 1);
214
+ await getState().setConfig("auto_backup_keep_weekly", 0);
215
+ await getState().setConfig("auto_backup_keep_monthly", 0);
216
+ await getState().setConfig("auto_backup_keep_yearly", 0);
217
+ await getState().setConfig("auto_backup_keep_min", 1);
218
+ // older backups of the same site, plus files the policy must not touch
219
+ for (const day of ["2020-01-01-00-00", "2020-01-02-00-00"])
220
+ await writeFile(join(dir, `${prefix}RetTest-${day}.zip`), "old");
221
+ await writeFile(join(dir, "not-a-backup.zip"), "keep me");
222
+ await writeFile(join(dir, `${prefix}RetTest-2020-01-03.txt`), "keep me");
223
+ await auto_backup_now();
224
+ const remaining = await readdir(dir);
225
+ // one backup of this site is retained (keep_daily=1, all in one day bucket)
226
+ expect(remaining.filter((f) => f.startsWith(`${prefix}RetTest`) && f.endsWith(".zip"))).toHaveLength(1);
227
+ // files outside the backup prefix or not zips are never deleted
228
+ expect(remaining).toContain("not-a-backup.zip");
229
+ expect(remaining).toContain(`${prefix}RetTest-2020-01-03.txt`);
230
+ await rm(dir, { recursive: true, force: true });
231
+ });
232
+ it("does not delete anything when retention is not configured", async () => {
233
+ const dir = await mkdtemp(join(tmpdir(), "sc-backup-retention-"));
234
+ const prefix = getState().getConfig("backup_file_prefix");
235
+ await getState().setConfig("auto_backup_directory", dir);
236
+ await getState().setConfig("auto_backup_retention_mode", "Expiration");
237
+ await getState().setConfig("auto_backup_expire_days", null);
238
+ for (const day of ["2020-01-01-00-00", "2020-01-02-00-00"])
239
+ await writeFile(join(dir, `${prefix}RetTest-${day}.zip`), "old");
240
+ await auto_backup_now();
241
+ const remaining = await readdir(dir);
242
+ expect(remaining).toContain(`${prefix}RetTest-2020-01-01-00-00.zip`);
243
+ expect(remaining).toContain(`${prefix}RetTest-2020-01-02-00-00.zip`);
244
+ await rm(dir, { recursive: true, force: true });
245
+ });
246
+ });
247
+ describe("backup file exclusion", () => {
248
+ it("excludes files matching the configured globs", async () => {
249
+ await File.ensure_file_store();
250
+ const mv = async (fnm) => {
251
+ await writeFile(fnm, "cecinestpasunpng");
252
+ };
253
+ await File.from_req_files({ mimetype: "video/mp4", name: "bigvideo.mp4", mv, size: 16 }, 1, 100);
254
+ await File.from_req_files({ mimetype: "image/png", name: "keepme.png", mv, size: 16 }, 1, 100);
255
+ await File.new_folder("cache");
256
+ await File.from_req_files({ mimetype: "image/png", name: "thumb.png", mv, size: 16 }, 1, 100, "cache");
257
+ await getState().setConfig("backup_exclude_file_globs", "*.mp4, cache/**");
258
+ const fnm = await create_backup();
259
+ const zip = new Zip(fnm);
260
+ const entries = zip.getEntries().map((e) => e.entryName);
261
+ const filesCsv = zip.readAsText("files.csv");
262
+ await unlink(fnm);
263
+ await getState().setConfig("backup_exclude_file_globs", "");
264
+ expect(entries).toContain("files/keepme.png");
265
+ expect(entries.filter((e) => e.includes("bigvideo"))).toHaveLength(0);
266
+ expect(entries.filter((e) => e.includes("thumb.png"))).toHaveLength(0);
267
+ // excluded files are also left out of the file metadata
268
+ expect(filesCsv.includes("keepme.png")).toBe(true);
269
+ expect(filesCsv.includes("bigvideo.mp4")).toBe(false);
270
+ expect(filesCsv.includes("thumb.png")).toBe(false);
271
+ });
272
+ it("includes all files when no globs are configured", async () => {
273
+ const fnm = await create_backup();
274
+ const entries = new Zip(fnm)
275
+ .getEntries()
276
+ .map((e) => e.entryName)
277
+ .join("\n");
278
+ await unlink(fnm);
279
+ expect(entries.includes("bigvideo.mp4")).toBe(true);
280
+ expect(entries.includes("keepme.png")).toBe(true);
281
+ expect(entries.includes("thumb.png")).toBe(true);
282
+ });
283
+ });
284
+ describe("backup destinations", () => {
285
+ // backup file names are built from the site name, and the other test files
286
+ // run in parallel in this same working directory - so give this file's
287
+ // backups a name only it produces
288
+ const siteName = "DestTest";
289
+ /** zips of this site left lying around in the working directory */
290
+ const strayBackups = async () => {
291
+ const prefix = getState().getConfig("backup_file_prefix");
292
+ return (await readdir(process.cwd())).filter((f) => f.startsWith(`${prefix}${siteName}-`) && f.endsWith(".zip"));
293
+ };
294
+ it("writes a local directory backup into the directory itself", async () => {
295
+ // the OS temporary directory is usually a different filesystem (tmpfs on
296
+ // most Linux distributions), like the Docker volumes and external drives
297
+ // of issue #4332: the backup must be written where it belongs rather than
298
+ // written elsewhere and renamed, because renaming across filesystems
299
+ // fails with EXDEV
300
+ const dir = await mkdtemp(join(tmpdir(), "sc-backup-dest-"));
301
+ await getState().setConfig("site_name", siteName);
302
+ await getState().setConfig("auto_backup_destination", "Local directory");
303
+ await getState().setConfig("auto_backup_directory", dir);
304
+ await getState().setConfig("auto_backup_retention_mode", "Expiration");
305
+ await getState().setConfig("auto_backup_expire_days", null);
306
+ await auto_backup_now();
307
+ const written = (await readdir(dir)).filter((f) => f.endsWith(".zip"));
308
+ expect(written).toHaveLength(1);
309
+ // and it is a readable backup, not a truncated or empty file
310
+ const zip = new Zip(join(dir, written[0]));
311
+ expect(zip.getEntries().map((e) => e.entryName)).toContain("pack.json");
312
+ // nothing was staged in the working directory on the way there
313
+ expect(await strayBackups()).toHaveLength(0);
314
+ await rm(dir, { recursive: true, force: true });
315
+ });
316
+ it("creates no local file when backing up to Saltcorn files", async () => {
317
+ await File.ensure_file_store();
318
+ await getState().setConfig("site_name", siteName);
319
+ await getState().setConfig("auto_backup_destination", "Saltcorn files");
320
+ // in a folder of its own: on SQLite every test file shares one file
321
+ // store, and a file appearing and disappearing in its root upsets the
322
+ // test files listing it in parallel
323
+ await getState().setConfig("auto_backup_directory", "desttest-backups");
324
+ await auto_backup_now();
325
+ const backupFile = (await File.find({ folder: "desttest-backups", mime_sub: "zip" })).find((f) => f.filename.startsWith(getState().getConfig("backup_file_prefix")));
326
+ assertIsSet(backupFile);
327
+ // the size recorded in the file listing is the size on disk
328
+ const stats = await stat(backupFile.location);
329
+ expect(backupFile.size_kb).toBe(Math.round(stats.size / 1024));
330
+ expect(await strayBackups()).toHaveLength(0);
331
+ await backupFile.delete();
332
+ });
333
+ });
334
+ describe("encrypted backups", () => {
335
+ const password = "hunter2!";
336
+ afterAll(async () => {
337
+ await getState().setConfig("backup_password", "");
338
+ });
339
+ it("encrypts the backup with the configured password", async () => {
340
+ await getState().setConfig("backup_password", password);
341
+ const fnm = await create_backup();
342
+ try {
343
+ const zip = new Zip(fnm);
344
+ // the entry names are readable, the contents are not
345
+ expect(zip.getEntries().map((e) => e.entryName)).toContain("pack.json");
346
+ expect(() => zip.readFile("pack.json")).toThrow();
347
+ const pack = JSON.parse(zip.readFile("pack.json", password).toString());
348
+ expect(Array.isArray(pack.tables)).toBe(true);
349
+ }
350
+ finally {
351
+ await unlink(fnm);
352
+ }
353
+ });
354
+ it("restores an encrypted backup", async () => {
355
+ await getState().setConfig("backup_password", password);
356
+ const fnm = await create_backup();
357
+ try {
358
+ await reset();
359
+ expect(Table.findOne({ name: "books" })).toBe(null);
360
+ const err = await restore(fnm, (p) => { }, true, password);
361
+ expect(err).toBe(undefined);
362
+ const books = Table.findOne({ name: "books" });
363
+ assertIsSet(books);
364
+ }
365
+ finally {
366
+ await unlink(fnm);
367
+ }
368
+ });
369
+ it("reports that a password is required when it is missing", async () => {
370
+ await getState().setConfig("backup_password", password);
371
+ const fnm = await create_backup();
372
+ try {
373
+ let error;
374
+ await restore(fnm, (p) => { }, true).catch((e) => {
375
+ error = e;
376
+ });
377
+ expect(error).toBeTruthy();
378
+ expect(error.requiresPassword).toBe(true);
379
+ }
380
+ finally {
381
+ await unlink(fnm);
382
+ }
383
+ });
384
+ });
385
+ //# sourceMappingURL=backup.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backup.test.js","sourceRoot":"","sources":["../../tests/backup.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cfgcheck.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cfgcheck.test.d.ts","sourceRoot":"","sources":["../../tests/cfgcheck.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,32 @@
1
+ import db from "@saltcorn/data/db/index";
2
+ import { getState } from "@saltcorn/data/db/state";
3
+ import { afterAll, describe, it, expect, beforeAll, jest, } from "@saltcorn/db-common/test_expect";
4
+ import { runConfigurationCheck } from "../models/config-check.js";
5
+ import * as mocks from "@saltcorn/data/tests/mocks";
6
+ import basePlugin from "@saltcorn/data/base-plugin";
7
+ import sbadmin2 from "@saltcorn/sbadmin2";
8
+ import reset from "@saltcorn/data/db/reset_schema";
9
+ import fixtures from "@saltcorn/data/db/fixtures";
10
+ const { mockReqRes } = mocks;
11
+ getState().registerPlugin("base", basePlugin);
12
+ getState().registerPlugin("sbadmin2", sbadmin2);
13
+ beforeAll(async () => {
14
+ await reset();
15
+ await fixtures();
16
+ });
17
+ afterAll(async () => {
18
+ await db.close();
19
+ });
20
+ jest.setTimeout(30000);
21
+ // todo tests for broken view
22
+ // todo tests for broken trigger / action
23
+ // todo tests for broken page
24
+ describe("config check", () => {
25
+ it("runs", async () => {
26
+ const { errors, passes, pass } = await runConfigurationCheck(mockReqRes.req);
27
+ expect(errors).toStrictEqual([]);
28
+ expect(passes.length).toBeGreaterThan(10);
29
+ expect(pass).toBe(true);
30
+ });
31
+ });
32
+ //# sourceMappingURL=cfgcheck.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cfgcheck.test.js","sourceRoot":"","sources":["../../tests/cfgcheck.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAEzC,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAEnD,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,EAAE,EACF,MAAM,EACN,SAAS,EACT,IAAI,GACL,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,KAAK,KAAK,MAAM,4BAA4B,CAAC;AACpD,OAAO,UAAU,MAAM,4BAA4B,CAAC;AACpD,OAAO,QAAQ,MAAM,oBAAoB,CAAC;AAC1C,OAAO,KAAK,MAAM,gCAAgC,CAAC;AACnD,OAAO,QAAQ,MAAM,4BAA4B,CAAC;AAElD,MAAM,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC;AAE7B,QAAQ,EAAG,CAAC,cAAc,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAC/C,QAAQ,EAAG,CAAC,cAAc,CAAC,UAAU,EAAE,QAAe,CAAC,CAAC;AAExD,SAAS,CAAC,KAAK,IAAI,EAAE;IACnB,MAAM,KAAK,EAAE,CAAC;IACd,MAAM,QAAQ,EAAE,CAAC;AACnB,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,KAAK,IAAI,EAAE;IAClB,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;AACnB,CAAC,CAAC,CAAC;AACH,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;AACvB,6BAA6B;AAC7B,yCAAyC;AACzC,6BAA6B;AAC7B,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,EAAE,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE;QACpB,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,qBAAqB,CAC1D,UAAU,CAAC,GAAG,CACf,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;QACjC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;QAC1C,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=file-globs.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-globs.test.d.ts","sourceRoot":"","sources":["../../tests/file-globs.test.ts"],"names":[],"mappings":""}