@easy-cms/core 1.18.0 → 1.19.0
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/dist/{chunk-NTAFZ4M6.js → chunk-FZCQXH5M.js} +169 -10
- package/dist/{config-CpeC7EvC.d.ts → config-U1mRwD4t.d.ts} +21 -0
- package/dist/{handler-BpKo6gh0.d.ts → handler-D2y4WSSM.d.ts} +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +1 -1
- package/dist/internal.d.ts +2 -2
- package/dist/internal.js +1 -1
- package/dist/{plugin-_XG-lqA5.d.ts → plugin-DRV5HA4a.d.ts} +1 -1
- package/dist/plugin.d.ts +2 -2
- package/package.json +1 -1
|
@@ -154,6 +154,7 @@ var ROLES = "user-roles";
|
|
|
154
154
|
var USER_IDENTITIES = "user-identities";
|
|
155
155
|
var AUDIT_LOGS = "audit-logs";
|
|
156
156
|
var OUTBOX = "outbox";
|
|
157
|
+
var RATE_LIMITS = "rate-limits";
|
|
157
158
|
var INTERNAL_COLLECTIONS = /* @__PURE__ */ new Set([
|
|
158
159
|
SESSIONS,
|
|
159
160
|
LOGIN_ATTEMPTS,
|
|
@@ -166,7 +167,8 @@ var INTERNAL_COLLECTIONS = /* @__PURE__ */ new Set([
|
|
|
166
167
|
ROLES,
|
|
167
168
|
USER_IDENTITIES,
|
|
168
169
|
AUDIT_LOGS,
|
|
169
|
-
OUTBOX
|
|
170
|
+
OUTBOX,
|
|
171
|
+
RATE_LIMITS
|
|
170
172
|
]);
|
|
171
173
|
var DEFAULT_ROLES = ["admin", "editor"];
|
|
172
174
|
var CREATED_BY_FIELD = {
|
|
@@ -640,6 +642,17 @@ var outboxCollection = {
|
|
|
640
642
|
{ name: "error", type: "text" }
|
|
641
643
|
]
|
|
642
644
|
};
|
|
645
|
+
var rateLimitsCollection = {
|
|
646
|
+
slug: RATE_LIMITS,
|
|
647
|
+
access: { read: nobody, create: nobody, update: nobody, delete: nobody },
|
|
648
|
+
fields: [
|
|
649
|
+
// `<anonymous|user|apiKey>:<id or HMAC of the IP>:<window number>`
|
|
650
|
+
{ name: "key", type: "text", required: true, unique: true },
|
|
651
|
+
{ name: "count", type: "number", required: true },
|
|
652
|
+
// When the window is over, for clearing old rows.
|
|
653
|
+
{ name: "expiresAt", type: "text", required: true, index: true }
|
|
654
|
+
]
|
|
655
|
+
};
|
|
643
656
|
var emailDeliveriesCollection = {
|
|
644
657
|
slug: EMAIL_DELIVERIES,
|
|
645
658
|
access: { read: nobody, create: nobody, update: nobody, delete: nobody },
|
|
@@ -3977,7 +3990,7 @@ var VersionStore = class {
|
|
|
3977
3990
|
};
|
|
3978
3991
|
|
|
3979
3992
|
// src/local-api.ts
|
|
3980
|
-
import { createHash as createHash5, createHmac as
|
|
3993
|
+
import { createHash as createHash5, createHmac as createHmac8, randomBytes as randomBytes6, randomUUID as randomUUID3 } from "crypto";
|
|
3981
3994
|
|
|
3982
3995
|
// src/auth/common-passwords.ts
|
|
3983
3996
|
var LIST = `
|
|
@@ -4473,6 +4486,141 @@ function entryOf(row) {
|
|
|
4473
4486
|
};
|
|
4474
4487
|
}
|
|
4475
4488
|
|
|
4489
|
+
// src/rate-limit.ts
|
|
4490
|
+
import { createHmac as createHmac5 } from "crypto";
|
|
4491
|
+
var SYNC_MS = 5e3;
|
|
4492
|
+
var DEFAULTS = { window: 60, anonymous: 300, users: 1200, apiKeys: 1200 };
|
|
4493
|
+
var RateLimiter = class {
|
|
4494
|
+
constructor(db, secret, logger, settings) {
|
|
4495
|
+
this.db = db;
|
|
4496
|
+
this.secret = secret;
|
|
4497
|
+
this.logger = logger;
|
|
4498
|
+
this.settings = { ...DEFAULTS, ...settings };
|
|
4499
|
+
}
|
|
4500
|
+
db;
|
|
4501
|
+
secret;
|
|
4502
|
+
logger;
|
|
4503
|
+
counts = /* @__PURE__ */ new Map();
|
|
4504
|
+
settings;
|
|
4505
|
+
lastSync = Date.now();
|
|
4506
|
+
syncing;
|
|
4507
|
+
warnedNoIp = false;
|
|
4508
|
+
/**
|
|
4509
|
+
* Counts a request, or returns the seconds until the client may send another when it is over
|
|
4510
|
+
* its limit. Health checks and the cron's `jobs/run` aren't counted (the caller skips them).
|
|
4511
|
+
*/
|
|
4512
|
+
hit(user, ip, now = Date.now()) {
|
|
4513
|
+
const client = this.client(user, ip);
|
|
4514
|
+
if (!client) return void 0;
|
|
4515
|
+
const [kind, id, limit] = client;
|
|
4516
|
+
const windowMs = this.settings.window * 1e3;
|
|
4517
|
+
const bucket = Math.floor(now / windowMs);
|
|
4518
|
+
const key = `${kind}:${id}:${bucket}`;
|
|
4519
|
+
let count = this.counts.get(key);
|
|
4520
|
+
if (!count) {
|
|
4521
|
+
count = { total: 0, pending: 0, ends: (bucket + 1) * windowMs };
|
|
4522
|
+
this.counts.set(key, count);
|
|
4523
|
+
}
|
|
4524
|
+
if (now - this.lastSync >= SYNC_MS && !this.syncing) void this.sync(now);
|
|
4525
|
+
if (count.total + count.pending >= limit)
|
|
4526
|
+
return Math.max(1, Math.ceil((count.ends - now) / 1e3));
|
|
4527
|
+
count.pending++;
|
|
4528
|
+
return void 0;
|
|
4529
|
+
}
|
|
4530
|
+
/** Who is counted, and their limit; `undefined` when nothing limits them. */
|
|
4531
|
+
client(user, ip) {
|
|
4532
|
+
const { anonymous, users, apiKeys } = this.settings;
|
|
4533
|
+
const key = user?.apiKey;
|
|
4534
|
+
if (key) return apiKeys === false ? void 0 : ["apiKey", String(key.id), apiKeys];
|
|
4535
|
+
if (user) return users === false ? void 0 : ["user", String(user.id), users];
|
|
4536
|
+
if (anonymous === false) return void 0;
|
|
4537
|
+
if (!ip) {
|
|
4538
|
+
if (!this.warnedNoIp) {
|
|
4539
|
+
this.warnedNoIp = true;
|
|
4540
|
+
this.logger.warn(
|
|
4541
|
+
"rateLimit: the client IP is unknown, so visitors who are not signed in are not limited. Behind a proxy, set trustProxy on the adapter."
|
|
4542
|
+
);
|
|
4543
|
+
}
|
|
4544
|
+
return void 0;
|
|
4545
|
+
}
|
|
4546
|
+
const hashed = createHmac5("sha256", this.secret).update(`rate:${ip}`).digest("base64url");
|
|
4547
|
+
return ["anonymous", hashed.slice(0, 22), anonymous];
|
|
4548
|
+
}
|
|
4549
|
+
/**
|
|
4550
|
+
* Adds what this instance counted to the database and reads the totals back; forgets windows
|
|
4551
|
+
* that are over. Runs in the background every few seconds; `await` it in tests.
|
|
4552
|
+
*/
|
|
4553
|
+
sync(now = Date.now()) {
|
|
4554
|
+
this.lastSync = now;
|
|
4555
|
+
this.syncing ??= this.write(now).catch((error) => this.logger.warn(`rateLimit: counts not saved: ${String(error)}`)).finally(() => {
|
|
4556
|
+
this.syncing = void 0;
|
|
4557
|
+
});
|
|
4558
|
+
return this.syncing;
|
|
4559
|
+
}
|
|
4560
|
+
async write(now) {
|
|
4561
|
+
for (const [key, count] of this.counts) {
|
|
4562
|
+
if (count.ends <= now) {
|
|
4563
|
+
this.counts.delete(key);
|
|
4564
|
+
continue;
|
|
4565
|
+
}
|
|
4566
|
+
const added = count.pending;
|
|
4567
|
+
count.pending = 0;
|
|
4568
|
+
count.total = await this.add(key, count, added) ?? count.total + added;
|
|
4569
|
+
}
|
|
4570
|
+
}
|
|
4571
|
+
/** Adds `by` to the key's row (made if missing) and returns the new total. */
|
|
4572
|
+
async add(key, count, by) {
|
|
4573
|
+
count.id ??= await this.rowId(key);
|
|
4574
|
+
if (count.id === void 0) {
|
|
4575
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
4576
|
+
try {
|
|
4577
|
+
const created = await this.db.create({
|
|
4578
|
+
collection: RATE_LIMITS,
|
|
4579
|
+
data: {
|
|
4580
|
+
key,
|
|
4581
|
+
count: by,
|
|
4582
|
+
expiresAt: new Date(count.ends).toISOString(),
|
|
4583
|
+
createdAt: stamp,
|
|
4584
|
+
updatedAt: stamp
|
|
4585
|
+
}
|
|
4586
|
+
});
|
|
4587
|
+
count.id = created.id;
|
|
4588
|
+
return by;
|
|
4589
|
+
} catch (error) {
|
|
4590
|
+
count.id = await this.rowId(key);
|
|
4591
|
+
if (count.id === void 0) throw error;
|
|
4592
|
+
}
|
|
4593
|
+
}
|
|
4594
|
+
return this.db.increment({ collection: RATE_LIMITS, id: count.id, field: "count", by });
|
|
4595
|
+
}
|
|
4596
|
+
async rowId(key) {
|
|
4597
|
+
const { docs } = await this.db.find({
|
|
4598
|
+
collection: RATE_LIMITS,
|
|
4599
|
+
where: { key: { equals: key } },
|
|
4600
|
+
sort: [],
|
|
4601
|
+
limit: 1,
|
|
4602
|
+
page: 1
|
|
4603
|
+
});
|
|
4604
|
+
return docs[0]?.id;
|
|
4605
|
+
}
|
|
4606
|
+
/** Deletes the rows of windows that are over. From `runJobs`. */
|
|
4607
|
+
async clear(now = /* @__PURE__ */ new Date()) {
|
|
4608
|
+
let deleted = 0;
|
|
4609
|
+
for (; ; ) {
|
|
4610
|
+
const { docs } = await this.db.find({
|
|
4611
|
+
collection: RATE_LIMITS,
|
|
4612
|
+
where: { expiresAt: { lt: now.toISOString() } },
|
|
4613
|
+
sort: ["id"],
|
|
4614
|
+
limit: 500,
|
|
4615
|
+
page: 1
|
|
4616
|
+
});
|
|
4617
|
+
for (const row of docs) await this.db.delete({ collection: RATE_LIMITS, id: row.id });
|
|
4618
|
+
deleted += docs.length;
|
|
4619
|
+
if (docs.length < 500) return deleted;
|
|
4620
|
+
}
|
|
4621
|
+
}
|
|
4622
|
+
};
|
|
4623
|
+
|
|
4476
4624
|
// src/remote-file.ts
|
|
4477
4625
|
import { lookup as dnsLookup } from "dns";
|
|
4478
4626
|
import { request as httpRequest } from "http";
|
|
@@ -4715,7 +4863,7 @@ function read(response, maxBytes, deadline) {
|
|
|
4715
4863
|
var keys = (list) => new Set(list.split(/\s+/).filter(Boolean));
|
|
4716
4864
|
var CONFIG = keys(`secret previousSecrets db serverURL cors cronSecret timeZone webhooks events jobs localization routes admin
|
|
4717
4865
|
upload auth collections globals endpoints cliCommands onRequest fieldTypes apiKeys email backups
|
|
4718
|
-
audit logs countCacheSeconds maxPage httpCache outbox search telemetry plugins`);
|
|
4866
|
+
audit logs countCacheSeconds maxPage httpCache outbox rateLimit search telemetry plugins`);
|
|
4719
4867
|
var ADMIN = keys("path locale brand siteURL nav commands modules pages dashboard switcher");
|
|
4720
4868
|
var AUTH = keys(`roles rbac tokenExpiration maxLoginAttempts lockWindow trustedOrigins
|
|
4721
4869
|
resetPasswordExpiration inviteExpiration providers providerSignUp password setupCode members emails`);
|
|
@@ -4723,6 +4871,7 @@ var MEMBERS = keys("roles signUp pages emails");
|
|
|
4723
4871
|
var UPLOAD = keys("dir maxFileSize mimeTypes storage imageSizes fromURL folders privateStorage");
|
|
4724
4872
|
var BACKUPS = keys("frequency at keep dir storage sqlite encryptionKey");
|
|
4725
4873
|
var AUDIT = keys("keepDays values failedLogins scope");
|
|
4874
|
+
var RATE_LIMIT = keys("window anonymous users apiKeys");
|
|
4726
4875
|
var LOGS = keys("format requests");
|
|
4727
4876
|
var COLLECTION = keys(`slug labels fields useAsTitle drafts versions schedule preview access hooks
|
|
4728
4877
|
admin httpCache search`);
|
|
@@ -4848,6 +4997,7 @@ function checkConfigKeys(config, add) {
|
|
|
4848
4997
|
check2(c.upload, "upload", "upload", UPLOAD, add);
|
|
4849
4998
|
check2(c.backups, "backups", "backups", BACKUPS, add);
|
|
4850
4999
|
if (isObject(c.audit)) check2(c.audit, "audit", "audit", AUDIT, add);
|
|
5000
|
+
if (isObject(c.rateLimit)) check2(c.rateLimit, "rateLimit", "rateLimit", RATE_LIMIT, add);
|
|
4851
5001
|
check2(c.logs, "logs", "logs", LOGS, add);
|
|
4852
5002
|
for (const [kind, list] of [
|
|
4853
5003
|
["collections", c.collections],
|
|
@@ -5204,13 +5354,13 @@ var SearchIndex = class {
|
|
|
5204
5354
|
};
|
|
5205
5355
|
|
|
5206
5356
|
// src/webhooks.ts
|
|
5207
|
-
import { createHmac as
|
|
5357
|
+
import { createHmac as createHmac7, randomUUID as randomUUID2 } from "crypto";
|
|
5208
5358
|
|
|
5209
5359
|
// src/webhook-signature.ts
|
|
5210
|
-
import { createHmac as
|
|
5360
|
+
import { createHmac as createHmac6, timingSafeEqual as timingSafeEqual5 } from "crypto";
|
|
5211
5361
|
var TOLERANCE_SECONDS = 5 * 60;
|
|
5212
5362
|
function signWebhook(secret, delivery, timestamp, body) {
|
|
5213
|
-
return `v1=${
|
|
5363
|
+
return `v1=${createHmac6("sha256", secret).update(`${delivery}.${timestamp}.${body}`).digest("hex")}`;
|
|
5214
5364
|
}
|
|
5215
5365
|
function header(headers, name) {
|
|
5216
5366
|
if (headers instanceof Headers) return headers.get(name) ?? void 0;
|
|
@@ -5411,7 +5561,7 @@ var Webhooks = class {
|
|
|
5411
5561
|
const timestamp = Math.floor(Date.now() / 1e3);
|
|
5412
5562
|
headers["x-easy-cms-timestamp"] = String(timestamp);
|
|
5413
5563
|
headers["x-easy-cms-signature-v2"] = signWebhook(hook.secret, delivery, timestamp, body);
|
|
5414
|
-
headers["x-easy-cms-signature"] = `sha256=${
|
|
5564
|
+
headers["x-easy-cms-signature"] = `sha256=${createHmac7("sha256", hook.secret).update(body).digest("hex")}`;
|
|
5415
5565
|
}
|
|
5416
5566
|
try {
|
|
5417
5567
|
const response = await this.fetcher(hook.url, {
|
|
@@ -7096,6 +7246,7 @@ async function resolveConfig(input) {
|
|
|
7096
7246
|
...config.email ? [emailDeliveriesCollection] : [],
|
|
7097
7247
|
...(config.jobs?.length ?? 0) > 0 ? [jobRunsCollection] : [],
|
|
7098
7248
|
...config.outbox ? [outboxCollection] : [],
|
|
7249
|
+
...config.rateLimit ? [rateLimitsCollection] : [],
|
|
7099
7250
|
databaseBackupsCollection,
|
|
7100
7251
|
...config.auth?.rbac ? [rolesCollection] : [],
|
|
7101
7252
|
...(config.auth?.providers?.length ?? 0) > 0 ? [userIdentitiesCollection] : [],
|
|
@@ -7166,7 +7317,7 @@ function cacheableResponse(request, body, status, headers, times, tags) {
|
|
|
7166
7317
|
}
|
|
7167
7318
|
|
|
7168
7319
|
// src/version.ts
|
|
7169
|
-
var VERSION = true ? "1.
|
|
7320
|
+
var VERSION = true ? "1.19.0" : "0.0.0-dev";
|
|
7170
7321
|
|
|
7171
7322
|
// src/telemetry.ts
|
|
7172
7323
|
var DB_CALLS = /* @__PURE__ */ new Set([
|
|
@@ -7444,6 +7595,8 @@ var EasyCMS = class {
|
|
|
7444
7595
|
mailer;
|
|
7445
7596
|
/** With `outbox: true`: runs after hooks and events from rows saves write. */
|
|
7446
7597
|
outbox;
|
|
7598
|
+
/** @internal Requests per client (`rateLimit`), for the REST API. */
|
|
7599
|
+
rateLimiter;
|
|
7447
7600
|
/** With `search`: keeps the index in step with published documents. */
|
|
7448
7601
|
searchIndex;
|
|
7449
7602
|
/** @internal With `telemetry`: OpenTelemetry spans and metrics (set by `createEasyCMS`). */
|
|
@@ -7484,6 +7637,7 @@ var EasyCMS = class {
|
|
|
7484
7637
|
() => this.runOutbox(entry, done, mark)
|
|
7485
7638
|
) : this.runOutbox(entry, done, mark)
|
|
7486
7639
|
) : void 0;
|
|
7640
|
+
this.rateLimiter = config.rateLimit ? new RateLimiter(db, config.secret, logger, config.rateLimit) : void 0;
|
|
7487
7641
|
this.searchIndex = config.search ? new SearchIndex(
|
|
7488
7642
|
config.search,
|
|
7489
7643
|
config.collections,
|
|
@@ -7830,7 +7984,7 @@ var EasyCMS = class {
|
|
|
7830
7984
|
/** A value with its HMAC (`secret`), for `purpose` only: `<base64url JSON>.<signature>`. */
|
|
7831
7985
|
sign(purpose, value) {
|
|
7832
7986
|
const payload = Buffer.from(JSON.stringify(value)).toString("base64url");
|
|
7833
|
-
const mac =
|
|
7987
|
+
const mac = createHmac8("sha256", this.config.secret).update(`${purpose}:${payload}`);
|
|
7834
7988
|
return `${payload}.${mac.digest("base64url")}`;
|
|
7835
7989
|
}
|
|
7836
7990
|
/** The value of a token made by `sign`, or `undefined` when it isn't genuine. */
|
|
@@ -7957,7 +8111,7 @@ var EasyCMS = class {
|
|
|
7957
8111
|
return signedWith(secretsOf(this.config), `media:${key}:${at}`, signature);
|
|
7958
8112
|
}
|
|
7959
8113
|
mediaSignature(key, expires) {
|
|
7960
|
-
return
|
|
8114
|
+
return createHmac8("sha256", this.config.secret).update(`media:${key}:${expires}`).digest("base64url");
|
|
7961
8115
|
}
|
|
7962
8116
|
/**
|
|
7963
8117
|
* How many documents use any of these files in a top-level upload field (rich text and fields
|
|
@@ -8974,6 +9128,7 @@ var EasyCMS = class {
|
|
|
8974
9128
|
(error) => this.logger.error(`Backups: ${error.message}`, { error })
|
|
8975
9129
|
);
|
|
8976
9130
|
await this.audit.upkeep(now).catch((error) => this.logger.error(`Audit log: ${error.message}`, { error }));
|
|
9131
|
+
await this.rateLimiter?.clear(now).catch((error) => this.logger.error(`Rate limits: ${error.message}`, { error }));
|
|
8977
9132
|
const result = {
|
|
8978
9133
|
scheduled,
|
|
8979
9134
|
webhooks: await this.retryWebhooks(now),
|
|
@@ -12242,6 +12397,10 @@ async function respondNow(cms, request, url, path, root, options, production, re
|
|
|
12242
12397
|
trustProxy: options.trustProxy === true
|
|
12243
12398
|
};
|
|
12244
12399
|
const method = request.method.toUpperCase();
|
|
12400
|
+
const isJobsRun = !root && segments[0] === "jobs" && segments[1] === "run";
|
|
12401
|
+
const wait = isJobsRun ? void 0 : cms.rateLimiter?.hit(user, options.getClientIp?.(request));
|
|
12402
|
+
if (wait !== void 0)
|
|
12403
|
+
throw new TooManyRequestsError("Too many requests: try again later", wait);
|
|
12245
12404
|
if (method !== "GET" && method !== "HEAD") checkCsrf(cms, ctx);
|
|
12246
12405
|
const audit = {
|
|
12247
12406
|
user,
|
|
@@ -3366,6 +3366,20 @@ interface AuthConfig {
|
|
|
3366
3366
|
readonly passwordChanged?: PasswordEmailFn;
|
|
3367
3367
|
};
|
|
3368
3368
|
}
|
|
3369
|
+
interface RateLimitConfig {
|
|
3370
|
+
/** Seconds each count lasts. Default 60. */
|
|
3371
|
+
readonly window?: number;
|
|
3372
|
+
/**
|
|
3373
|
+
* Requests per window from one IP without signing in. Default 300; `false`: no limit. Needs the
|
|
3374
|
+
* client's IP: behind a proxy, set `trustProxy` on the adapter (without it, visitors aren't
|
|
3375
|
+
* limited, and the log says so once).
|
|
3376
|
+
*/
|
|
3377
|
+
readonly anonymous?: number | false;
|
|
3378
|
+
/** Requests per window from one signed-in user (the admin included). Default 1200; `false`: no limit. */
|
|
3379
|
+
readonly users?: number | false;
|
|
3380
|
+
/** Requests per window with one API key. Default 1200; `false`: no limit. */
|
|
3381
|
+
readonly apiKeys?: number | false;
|
|
3382
|
+
}
|
|
3369
3383
|
/** What `onRequest` receives. */
|
|
3370
3384
|
interface OnRequestArgs {
|
|
3371
3385
|
readonly headers: Headers;
|
|
@@ -3673,6 +3687,13 @@ interface Config {
|
|
|
3673
3687
|
* Default `false`: hooks run in the request, after the save.
|
|
3674
3688
|
*/
|
|
3675
3689
|
readonly outbox?: boolean;
|
|
3690
|
+
/**
|
|
3691
|
+
* Limits requests to the API per client and minute, counted across instances: each visitor's
|
|
3692
|
+
* IP, each signed-in user and each API key. Over the limit, the API answers `429` with
|
|
3693
|
+
* `Retry-After`. `{}` uses the defaults. Needs a migration for the `rate-limits` table. Default
|
|
3694
|
+
* off.
|
|
3695
|
+
*/
|
|
3696
|
+
readonly rateLimit?: RateLimitConfig;
|
|
3676
3697
|
/**
|
|
3677
3698
|
* Relevance-ranked search of the collections that have `search`, e.g. `memorySearch()` for
|
|
3678
3699
|
* development and small sites, or an adapter for a search engine. Published documents are
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { I as ID, C as Config, E as EasyCMS, L as LocalizationConfig, F as Field, a as FieldError, b as FilterOptions, c as CreateEasyCMSOptions, R as ResolvedConfig } from './config-
|
|
1
|
+
import { I as ID, C as Config, E as EasyCMS, L as LocalizationConfig, F as Field, a as FieldError, b as FilterOptions, c as CreateEasyCMSOptions, R as ResolvedConfig } from './config-U1mRwD4t.js';
|
|
2
2
|
|
|
3
3
|
/** Decrypts a file from `encryptBackup`; throws for another key or a changed file. */
|
|
4
4
|
declare function decryptBackup(data: Uint8Array, encryptionKey: string): Uint8Array;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { P as PaginatedDocs, I as ID, d as EmailSetting, W as WebhookPayload } from './config-
|
|
2
|
-
export { A as ADAPTER_API_VERSION, e as ADMIN_ICONS, f as Access, g as AccessArgs, h as AccessOptions, i as AdminBrand, j as AdminCommand, k as AdminComponent, l as AdminConfig, m as AdminFieldArgs, n as AdminIcon, o as AdminLocale, p as AdminPage, q as AdminRole, r as AdminRoleChange, s as AdminRoleField, t as AdminRoleTarget, u as AdminRoleView, v as AdminRoles, w as AdminSso, x as AdminSwitcher, y as AdminViewAccess, z as AfterChangeHook, B as AfterDeleteHook, D as AfterReadHook, G as ApiKeyContext, H as ApiKeyGlobalOperation, J as ApiKeyOperation, K as ApiKeyPermissions, M as ArrayField, N as AuditChange, O as AuditConfig, Q as AuditEntry, S as AuditLog, T as AuditPage, U as AuditVerification, V as Auth, X as AuthConfig, Y as AuthProvider, Z as AuthProviderProfile, _ as AuthProviderRequest, $ as AuthUser, a0 as BackupsConfig, a1 as BeforeChangeHook, a2 as BeforeDeleteHook, a3 as BeforeValidateHook, a4 as Block, a5 as BlocksField, a6 as BooleanField, a7 as BuiltinApiKeysCollection, a8 as BuiltinMediaCollection, a9 as BuiltinMediaFoldersCollection, aa as BuiltinUsersCollection, ab as BundleHints, ac as CliCommand, ad as CollectionAccess, ae as CollectionAdmin, af as CollectionConfig, ag as CollectionDocument, ah as CollectionHooks, ai as CollectionListAdmin, aj as CollectionSearch, ak as CollectionSlug, C as Config, al as ConfigError, am as ConfigIssue, an as ContainerAdmin, c as CreateEasyCMSOptions, ao as CreateInput, ap as CreateMigrationResult, aq as CursorDocs, ar as CustomField, as as CustomFieldTypes, at as DashboardWidget, au as Database, av as DatabaseAdapter, aw as DatabaseInitArgs, ax as DatabaseTransfer, ay as DateField, az as DepthOptions, aA as DirectUpload, aB as DiskStorageOptions, aC as DocumentOf, E as EasyCMS, aD as EasyCMSError, aE as EmailAdapter, aF as EmailField, aG as EmailMessage, aH as Endpoint, aI as EndpointRequest, aJ as ErrorCode, aK as FIELD_TYPES, F as Field, aL as FieldAccess, aM as FieldAccessFn, aN as FieldAdmin, a as FieldError, aO as FieldRule, aP as FieldType, aQ as FieldTypeBase, aR as FieldTypeDefinition, aS as FieldTypeValidateContext, aT as FieldValidate, aU as FieldValidateContext, aV as FieldValue, aW as FieldsInput, aX as FieldsValue, b as FilterOptions, aY as FilterOptionsArgs, aZ as FindAfterArgs, a_ as FindArgs, a$ as FindOptions, b0 as FolderLevel, b1 as FolderPermissions, b2 as ForbiddenError, b3 as GlobalAccess, b4 as GlobalConfig, b5 as GlobalDocument, b6 as GlobalHooks, b7 as GlobalInput, b8 as GlobalSlug, b9 as GroupField, ba as ImageSize, bb as IncrementOptions, bc as InferCollection, bd as InferGlobal, be as JobConfig, bf as JsonField, bg as KeysetPage, bh as Label, bi as LayoutNode, bj as LivePreview, bk as LocaleOf, L as LocalizationConfig, bl as LogDetails, bm as Logger, bn as LoginArgs, bo as LogsConfig, bp as MediaDocument, bq as MediaSize, br as MembersConfig, bs as MembersSignup, bt as MigrationInfo, bu as NavGroup, bv as NotFoundError, bw as NumberField, bx as OnRequest, by as OnRequestArgs, bz as Operation, bA as OutboxRow, bB as PLUGIN_API_VERSION, bC as PasswordEmail, bD as PasswordEmailArgs, bE as PasswordEmailFn, bF as PasswordLinkOptions, bG as PayloadTooLargeError, bH as Plugin, bI as PluginInfo, bJ as PluginTypes, bK as PreviewTarget, bL as PreviewURL, bM as QueryError, bN as ROLE_OPERATIONS, bO as RawDocument, bP as ReadOptions, bQ as RelationshipField, bR as RequestContext, R as ResolvedConfig, bS as RichTextDocument, bT as RichTextField, bU as Role, bV as RoleOperation, bW as RolePermissions, bX as Roles, bY as RoutesConfig, bZ as ScheduledPublish, b_ as SchemaError, b$ as SchemaMode, c0 as SearchAdapter, c1 as SearchEntry, c2 as SearchHits, c3 as SearchOptions, c4 as SearchQuery, c5 as SearchResults, c6 as SearchSetting, c7 as SelectField, c8 as SelectOption, c9 as Session, ca as SidebarPanel, cb as SignupArgs, cc as SignupResult, cd as SingleSignOn, ce as SlugField, cf as SlugOf, cg as SsoOutcome, ch as SsoProviderRef, ci as StorageAdapter, cj as StoredFile, ck as TRIGRAM_LIKE_MIN, cl as TelemetryConfig, cm as TextField, cn as TextareaField, co as TooManyRequestsError, cp as TypedPlugin, cq as UnauthorizedError, cr as UncountedDocs, cs as UpdateInput, ct as UpdateOptions, cu as UploadConfig, cv as UploadField, cw as UploadFromURLConfig, cx as UserIdentity, cy as ValidationError, cz as Version, cA as VersionSummary, cB as VersionsConfig, cC as WEBHOOK_EVENTS, cD as WebhookConfig, cE as WebhookEvent, cF as Where, cG as WhereOperators, cH as anyone, cI as consoleEmail, cJ as consoleLogger, cK as createEasyCMS, cL as defineConfig, cM as defineFieldType, cN as definePlugin, cO as diskStorage, cP as hasRows, cQ as isAdmin, cR as isHasMany, cS as isSignedIn, cT as isStaff, cU as isSystemAdmin, cV as jsonLogger, cW as memorySearch, cX as mimeAllowedBy, cY as rowFields, cZ as silentLogger, c_ as uniqueWithinOf } from './config-
|
|
3
|
-
export { A as ADMIN_API_VERSION, a as AdminCollection, b as AdminComponentRef, c as AdminElementProps, d as AdminField, e as AdminGlobal, f as AdminLayoutNode, g as AdminNavGroup, h as AdminNavItem, i as AdminNavNode, j as AdminPageRef, k as AdminPageRoute, l as AdminSchema, m as AdminWidgetRef, S as SetFieldDetail, w as warnDeprecated } from './plugin-
|
|
4
|
-
export { A as AdminBackup, a as AdminBackups, b as ApiHandlerOptions, B as BackupState, L as LoadConfigOptions, R as RestHandler, c as RestHandlerOptions, d as createApiHandler, e as createRestHandler, l as loadConfig, r as resolveConfig, s as sharedEasyCMS, f as slugify } from './handler-
|
|
1
|
+
import { P as PaginatedDocs, I as ID, d as EmailSetting, W as WebhookPayload } from './config-U1mRwD4t.js';
|
|
2
|
+
export { A as ADAPTER_API_VERSION, e as ADMIN_ICONS, f as Access, g as AccessArgs, h as AccessOptions, i as AdminBrand, j as AdminCommand, k as AdminComponent, l as AdminConfig, m as AdminFieldArgs, n as AdminIcon, o as AdminLocale, p as AdminPage, q as AdminRole, r as AdminRoleChange, s as AdminRoleField, t as AdminRoleTarget, u as AdminRoleView, v as AdminRoles, w as AdminSso, x as AdminSwitcher, y as AdminViewAccess, z as AfterChangeHook, B as AfterDeleteHook, D as AfterReadHook, G as ApiKeyContext, H as ApiKeyGlobalOperation, J as ApiKeyOperation, K as ApiKeyPermissions, M as ArrayField, N as AuditChange, O as AuditConfig, Q as AuditEntry, S as AuditLog, T as AuditPage, U as AuditVerification, V as Auth, X as AuthConfig, Y as AuthProvider, Z as AuthProviderProfile, _ as AuthProviderRequest, $ as AuthUser, a0 as BackupsConfig, a1 as BeforeChangeHook, a2 as BeforeDeleteHook, a3 as BeforeValidateHook, a4 as Block, a5 as BlocksField, a6 as BooleanField, a7 as BuiltinApiKeysCollection, a8 as BuiltinMediaCollection, a9 as BuiltinMediaFoldersCollection, aa as BuiltinUsersCollection, ab as BundleHints, ac as CliCommand, ad as CollectionAccess, ae as CollectionAdmin, af as CollectionConfig, ag as CollectionDocument, ah as CollectionHooks, ai as CollectionListAdmin, aj as CollectionSearch, ak as CollectionSlug, C as Config, al as ConfigError, am as ConfigIssue, an as ContainerAdmin, c as CreateEasyCMSOptions, ao as CreateInput, ap as CreateMigrationResult, aq as CursorDocs, ar as CustomField, as as CustomFieldTypes, at as DashboardWidget, au as Database, av as DatabaseAdapter, aw as DatabaseInitArgs, ax as DatabaseTransfer, ay as DateField, az as DepthOptions, aA as DirectUpload, aB as DiskStorageOptions, aC as DocumentOf, E as EasyCMS, aD as EasyCMSError, aE as EmailAdapter, aF as EmailField, aG as EmailMessage, aH as Endpoint, aI as EndpointRequest, aJ as ErrorCode, aK as FIELD_TYPES, F as Field, aL as FieldAccess, aM as FieldAccessFn, aN as FieldAdmin, a as FieldError, aO as FieldRule, aP as FieldType, aQ as FieldTypeBase, aR as FieldTypeDefinition, aS as FieldTypeValidateContext, aT as FieldValidate, aU as FieldValidateContext, aV as FieldValue, aW as FieldsInput, aX as FieldsValue, b as FilterOptions, aY as FilterOptionsArgs, aZ as FindAfterArgs, a_ as FindArgs, a$ as FindOptions, b0 as FolderLevel, b1 as FolderPermissions, b2 as ForbiddenError, b3 as GlobalAccess, b4 as GlobalConfig, b5 as GlobalDocument, b6 as GlobalHooks, b7 as GlobalInput, b8 as GlobalSlug, b9 as GroupField, ba as ImageSize, bb as IncrementOptions, bc as InferCollection, bd as InferGlobal, be as JobConfig, bf as JsonField, bg as KeysetPage, bh as Label, bi as LayoutNode, bj as LivePreview, bk as LocaleOf, L as LocalizationConfig, bl as LogDetails, bm as Logger, bn as LoginArgs, bo as LogsConfig, bp as MediaDocument, bq as MediaSize, br as MembersConfig, bs as MembersSignup, bt as MigrationInfo, bu as NavGroup, bv as NotFoundError, bw as NumberField, bx as OnRequest, by as OnRequestArgs, bz as Operation, bA as OutboxRow, bB as PLUGIN_API_VERSION, bC as PasswordEmail, bD as PasswordEmailArgs, bE as PasswordEmailFn, bF as PasswordLinkOptions, bG as PayloadTooLargeError, bH as Plugin, bI as PluginInfo, bJ as PluginTypes, bK as PreviewTarget, bL as PreviewURL, bM as QueryError, bN as ROLE_OPERATIONS, bO as RawDocument, bP as ReadOptions, bQ as RelationshipField, bR as RequestContext, R as ResolvedConfig, bS as RichTextDocument, bT as RichTextField, bU as Role, bV as RoleOperation, bW as RolePermissions, bX as Roles, bY as RoutesConfig, bZ as ScheduledPublish, b_ as SchemaError, b$ as SchemaMode, c0 as SearchAdapter, c1 as SearchEntry, c2 as SearchHits, c3 as SearchOptions, c4 as SearchQuery, c5 as SearchResults, c6 as SearchSetting, c7 as SelectField, c8 as SelectOption, c9 as Session, ca as SidebarPanel, cb as SignupArgs, cc as SignupResult, cd as SingleSignOn, ce as SlugField, cf as SlugOf, cg as SsoOutcome, ch as SsoProviderRef, ci as StorageAdapter, cj as StoredFile, ck as TRIGRAM_LIKE_MIN, cl as TelemetryConfig, cm as TextField, cn as TextareaField, co as TooManyRequestsError, cp as TypedPlugin, cq as UnauthorizedError, cr as UncountedDocs, cs as UpdateInput, ct as UpdateOptions, cu as UploadConfig, cv as UploadField, cw as UploadFromURLConfig, cx as UserIdentity, cy as ValidationError, cz as Version, cA as VersionSummary, cB as VersionsConfig, cC as WEBHOOK_EVENTS, cD as WebhookConfig, cE as WebhookEvent, cF as Where, cG as WhereOperators, cH as anyone, cI as consoleEmail, cJ as consoleLogger, cK as createEasyCMS, cL as defineConfig, cM as defineFieldType, cN as definePlugin, cO as diskStorage, cP as hasRows, cQ as isAdmin, cR as isHasMany, cS as isSignedIn, cT as isStaff, cU as isSystemAdmin, cV as jsonLogger, cW as memorySearch, cX as mimeAllowedBy, cY as rowFields, cZ as silentLogger, c_ as uniqueWithinOf } from './config-U1mRwD4t.js';
|
|
3
|
+
export { A as ADMIN_API_VERSION, a as AdminCollection, b as AdminComponentRef, c as AdminElementProps, d as AdminField, e as AdminGlobal, f as AdminLayoutNode, g as AdminNavGroup, h as AdminNavItem, i as AdminNavNode, j as AdminPageRef, k as AdminPageRoute, l as AdminSchema, m as AdminWidgetRef, S as SetFieldDetail, w as warnDeprecated } from './plugin-DRV5HA4a.js';
|
|
4
|
+
export { A as AdminBackup, a as AdminBackups, b as ApiHandlerOptions, B as BackupState, L as LoadConfigOptions, R as RestHandler, c as RestHandlerOptions, d as createApiHandler, e as createRestHandler, l as loadConfig, r as resolveConfig, s as sharedEasyCMS, f as slugify } from './handler-D2y4WSSM.js';
|
|
5
5
|
export { FieldCondition, matchesCondition } from './conditions.js';
|
|
6
6
|
|
|
7
7
|
type DeliveryKind = 'webhook' | 'email';
|
package/dist/index.js
CHANGED
package/dist/internal.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Config, Database, EasyCMS, NavGroup, CollectionConfig, ID, RawDocument, Field, ResolvedConfig, ConfigIssue } from './index.js';
|
|
2
|
-
export { c$ as API_KEYS, d0 as API_KEY_GLOBAL_OPERATIONS, d1 as API_KEY_OPERATIONS, d2 as DEFAULT_MAX_VERSIONS, d3 as DEFAULT_PASSWORD_EMAILS, d4 as FIELD_TYPE_BASES, d5 as FOLDER_LEVELS, d6 as MediaFolders, d7 as SSO_COOKIE, d8 as Secrets, ck as TRIGRAM_LIKE_MIN, d9 as codeOfStatus, cP as hasRows, cR as isHasMany, da as isJsonLogger, db as keyAllows, dc as logFormat, cX as mimeAllowedBy, cY as rowFields, dd as secretsOf, c_ as uniqueWithinOf } from './config-
|
|
3
|
-
export { C as CONFIG_FILE_NAMES, g as CSRF_COOKIE, h as CSRF_HEADER, D as DEFAULT_ADMIN_PATH, i as DEFAULT_API_PATH, j as DEFAULT_MAX_FILE_SIZE, k as DEFAULT_TOKEN_EXPIRATION, m as applyDefaults, n as applyPlugins, o as createRootEndpointHandler, p as decryptBackup, q as fillMissing, t as findConfigFile, u as forwardedClientIp, v as generateSlugs, w as importConfig, x as isEmail, y as mergeForUpdate, z as parseId, E as platformClientIp, F as readCookie, G as validateFields, H as writeBackupFile } from './handler-
|
|
2
|
+
export { c$ as API_KEYS, d0 as API_KEY_GLOBAL_OPERATIONS, d1 as API_KEY_OPERATIONS, d2 as DEFAULT_MAX_VERSIONS, d3 as DEFAULT_PASSWORD_EMAILS, d4 as FIELD_TYPE_BASES, d5 as FOLDER_LEVELS, d6 as MediaFolders, d7 as SSO_COOKIE, d8 as Secrets, ck as TRIGRAM_LIKE_MIN, d9 as codeOfStatus, cP as hasRows, cR as isHasMany, da as isJsonLogger, db as keyAllows, dc as logFormat, cX as mimeAllowedBy, cY as rowFields, dd as secretsOf, c_ as uniqueWithinOf } from './config-U1mRwD4t.js';
|
|
3
|
+
export { C as CONFIG_FILE_NAMES, g as CSRF_COOKIE, h as CSRF_HEADER, D as DEFAULT_ADMIN_PATH, i as DEFAULT_API_PATH, j as DEFAULT_MAX_FILE_SIZE, k as DEFAULT_TOKEN_EXPIRATION, m as applyDefaults, n as applyPlugins, o as createRootEndpointHandler, p as decryptBackup, q as fillMissing, t as findConfigFile, u as forwardedClientIp, v as generateSlugs, w as importConfig, x as isEmail, y as mergeForUpdate, z as parseId, E as platformClientIp, F as readCookie, G as validateFields, H as writeBackupFile } from './handler-D2y4WSSM.js';
|
|
4
4
|
export { conditionIssues } from './conditions.js';
|
|
5
5
|
|
|
6
6
|
/** The session cookie the REST API sets at login. */
|
package/dist/internal.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { bh as Label, F as Field, I as ID, o as AdminLocale, x as AdminSwitcher, ch as SsoProviderRef } from './config-
|
|
1
|
+
import { bh as Label, F as Field, I as ID, o as AdminLocale, x as AdminSwitcher, ch as SsoProviderRef } from './config-U1mRwD4t.js';
|
|
2
2
|
import { FieldCondition } from './conditions.js';
|
|
3
3
|
|
|
4
4
|
/** A Web Component from an admin module, with its `props` (plain JSON). */
|
package/dist/plugin.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { e as ADMIN_ICONS, k as AdminComponent, n as AdminIcon, $ as AuthUser, ac as CliCommand, ad as CollectionAccess, af as CollectionConfig, C as Config, al as ConfigError, at as DashboardWidget, aD as EasyCMSError, aH as Endpoint, aI as EndpointRequest, aJ as ErrorCode, F as Field, aL as FieldAccess, a as FieldError, aQ as FieldTypeBase, aR as FieldTypeDefinition, aS as FieldTypeValidateContext, b2 as ForbiddenError, b4 as GlobalConfig, I as ID, be as JobConfig, bh as Label, bu as NavGroup, bv as NotFoundError, bx as OnRequest, by as OnRequestArgs, bB as PLUGIN_API_VERSION, bG as PayloadTooLargeError, bH as Plugin, bI as PluginInfo, bJ as PluginTypes, bM as QueryError, bR as RequestContext, co as TooManyRequestsError, cp as TypedPlugin, cq as UnauthorizedError, cy as ValidationError, cF as Where, cM as defineFieldType, cN as definePlugin } from './config-
|
|
2
|
-
export { A as ADMIN_API_VERSION, c as AdminElementProps, k as AdminPageRoute, S as SetFieldDetail, w as warnDeprecated } from './plugin-
|
|
1
|
+
export { e as ADMIN_ICONS, k as AdminComponent, n as AdminIcon, $ as AuthUser, ac as CliCommand, ad as CollectionAccess, af as CollectionConfig, C as Config, al as ConfigError, at as DashboardWidget, aD as EasyCMSError, aH as Endpoint, aI as EndpointRequest, aJ as ErrorCode, F as Field, aL as FieldAccess, a as FieldError, aQ as FieldTypeBase, aR as FieldTypeDefinition, aS as FieldTypeValidateContext, b2 as ForbiddenError, b4 as GlobalConfig, I as ID, be as JobConfig, bh as Label, bu as NavGroup, bv as NotFoundError, bx as OnRequest, by as OnRequestArgs, bB as PLUGIN_API_VERSION, bG as PayloadTooLargeError, bH as Plugin, bI as PluginInfo, bJ as PluginTypes, bM as QueryError, bR as RequestContext, co as TooManyRequestsError, cp as TypedPlugin, cq as UnauthorizedError, cy as ValidationError, cF as Where, cM as defineFieldType, cN as definePlugin } from './config-U1mRwD4t.js';
|
|
2
|
+
export { A as ADMIN_API_VERSION, c as AdminElementProps, k as AdminPageRoute, S as SetFieldDetail, w as warnDeprecated } from './plugin-DRV5HA4a.js';
|
|
3
3
|
import './conditions.js';
|