@easy-cms/core 0.64.0 → 0.65.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-JZW6G6XI.js → chunk-BGGQ36LR.js} +95 -17
- package/dist/{config-Dgs6FE0S.d.ts → config-DE8ez-a9.d.ts} +12 -1
- package/dist/{handler-CcmsrLs8.d.ts → handler-Cm1ehtkm.d.ts} +4 -2
- package/dist/index.d.ts +4 -4
- package/dist/index.js +1 -1
- package/dist/internal.d.ts +3 -3
- package/dist/internal.js +3 -1
- package/dist/{plugin-8hrkYMuR.d.ts → plugin-CX7E7RZZ.d.ts} +1 -1
- package/dist/plugin.d.ts +2 -2
- package/package.json +1 -1
|
@@ -522,6 +522,7 @@ var CSV_LIMIT = 1e4;
|
|
|
522
522
|
var DAY = 864e5;
|
|
523
523
|
var BULKY = /* @__PURE__ */ new Set(["richText", "blocks", "array", "json"]);
|
|
524
524
|
var auditContext = new AsyncLocalStorage();
|
|
525
|
+
var SIGN_IN_FAILURES = /* @__PURE__ */ new Set(["login.failed", "login.locked", "sso.failed"]);
|
|
525
526
|
function stable(value) {
|
|
526
527
|
if (value === void 0 || value === null) return "null";
|
|
527
528
|
if (Array.isArray(value)) return `[${value.map(stable).join(",")}]`;
|
|
@@ -578,7 +579,15 @@ var AuditLog = class {
|
|
|
578
579
|
* counted, and the dashboard says so.
|
|
579
580
|
*/
|
|
580
581
|
async record(entry) {
|
|
581
|
-
if (!this.enabled)
|
|
582
|
+
if (!this.enabled) {
|
|
583
|
+
if (SIGN_IN_FAILURES.has(entry.action)) {
|
|
584
|
+
const ip = auditContext.getStore()?.ip;
|
|
585
|
+
this.cms.logger.warn(
|
|
586
|
+
`${entry.action}: ${entry.email ?? entry.user?.email ?? "unknown"}${ip ? ` from ${ip}` : ""}`
|
|
587
|
+
);
|
|
588
|
+
}
|
|
589
|
+
return;
|
|
590
|
+
}
|
|
582
591
|
try {
|
|
583
592
|
const context = auditContext.getStore();
|
|
584
593
|
const user = entry.user !== void 0 ? entry.user : context?.user ?? null;
|
|
@@ -731,8 +740,11 @@ var AuditLog = class {
|
|
|
731
740
|
await this.record({
|
|
732
741
|
action: "audit.verify",
|
|
733
742
|
target: "audit",
|
|
734
|
-
detail: { checked, invalid: invalid.length, gaps }
|
|
743
|
+
detail: { checked, invalid: invalid.length, gaps, lastId: previous ?? null }
|
|
735
744
|
});
|
|
745
|
+
this.cms.logger.info(
|
|
746
|
+
`Audit log checked: ${checked} entries, last #${previous ?? "-"}; ${invalid.length} changed, ${gaps} missing`
|
|
747
|
+
);
|
|
736
748
|
return verification;
|
|
737
749
|
}
|
|
738
750
|
/**
|
|
@@ -2832,12 +2844,38 @@ function diskStorage(options = {}) {
|
|
|
2832
2844
|
}
|
|
2833
2845
|
|
|
2834
2846
|
// src/backups.ts
|
|
2847
|
+
import { createCipheriv, createDecipheriv, createHash as createHash3, randomBytes as randomBytes5 } from "crypto";
|
|
2835
2848
|
import { mkdtemp, readFile as readFile2, rm as rm2 } from "fs/promises";
|
|
2836
2849
|
import { tmpdir } from "os";
|
|
2837
2850
|
import { join as join2 } from "path";
|
|
2838
2851
|
import { promisify } from "util";
|
|
2839
2852
|
import { gzip } from "zlib";
|
|
2840
2853
|
var gzipAsync = promisify(gzip);
|
|
2854
|
+
var MAGIC = Buffer.from("ECMSBAK1");
|
|
2855
|
+
var IV_BYTES = 12;
|
|
2856
|
+
var TAG_BYTES = 16;
|
|
2857
|
+
var keyOf = (encryptionKey) => createHash3("sha256").update(encryptionKey).digest();
|
|
2858
|
+
function encryptBackup(data, encryptionKey) {
|
|
2859
|
+
const iv = randomBytes5(IV_BYTES);
|
|
2860
|
+
const cipher = createCipheriv("aes-256-gcm", keyOf(encryptionKey), iv);
|
|
2861
|
+
const body = Buffer.concat([cipher.update(data), cipher.final()]);
|
|
2862
|
+
return new Uint8Array(Buffer.concat([MAGIC, iv, body, cipher.getAuthTag()]));
|
|
2863
|
+
}
|
|
2864
|
+
function decryptBackup(data, encryptionKey) {
|
|
2865
|
+
const buffer = Buffer.from(data);
|
|
2866
|
+
if (buffer.length < MAGIC.length + IV_BYTES + TAG_BYTES || !buffer.subarray(0, 8).equals(MAGIC))
|
|
2867
|
+
throw new EasyCMSError("Not an encrypted Easy CMS backup", 400);
|
|
2868
|
+
const iv = buffer.subarray(MAGIC.length, MAGIC.length + IV_BYTES);
|
|
2869
|
+
const tag = buffer.subarray(buffer.length - TAG_BYTES);
|
|
2870
|
+
const body = buffer.subarray(MAGIC.length + IV_BYTES, buffer.length - TAG_BYTES);
|
|
2871
|
+
const decipher = createDecipheriv("aes-256-gcm", keyOf(encryptionKey), iv);
|
|
2872
|
+
decipher.setAuthTag(tag);
|
|
2873
|
+
try {
|
|
2874
|
+
return new Uint8Array(Buffer.concat([decipher.update(body), decipher.final()]));
|
|
2875
|
+
} catch {
|
|
2876
|
+
throw new EasyCMSError("The backup could not be decrypted: wrong key, or a changed file", 400);
|
|
2877
|
+
}
|
|
2878
|
+
}
|
|
2841
2879
|
var DEFAULT_BACKUP_TIME = "03:00";
|
|
2842
2880
|
var DEFAULT_BACKUP_KEEP = 7;
|
|
2843
2881
|
var DEFAULT_DIR = "backups";
|
|
@@ -2982,11 +3020,15 @@ async function runBackup(cms, record) {
|
|
|
2982
3020
|
try {
|
|
2983
3021
|
const file = join2(dir, "backup.db");
|
|
2984
3022
|
await writeBackupFile(cms, file);
|
|
2985
|
-
const
|
|
3023
|
+
const encryptionKey = cms.config.backups?.encryptionKey;
|
|
3024
|
+
const gzipped = new Uint8Array(await gzipAsync(await readFile2(file)));
|
|
3025
|
+
const data = encryptionKey ? encryptBackup(gzipped, encryptionKey) : gzipped;
|
|
2986
3026
|
const storage = await backupStorage(cms);
|
|
2987
|
-
const filename = filenameFor(cms, started)
|
|
2988
|
-
const key = await storage.get(filename) ? filename.replace(/\.db\.gz
|
|
2989
|
-
await storage.put(key, data, {
|
|
3027
|
+
const filename = `${filenameFor(cms, started)}${encryptionKey ? ".enc" : ""}`;
|
|
3028
|
+
const key = await storage.get(filename) ? filename.replace(/\.db\.gz(\.enc)?$/, `-${row.id}.db.gz$1`) : filename;
|
|
3029
|
+
await storage.put(key, data, {
|
|
3030
|
+
contentType: encryptionKey ? "application/octet-stream" : "application/gzip"
|
|
3031
|
+
});
|
|
2990
3032
|
await pruneBackups(cms, 1);
|
|
2991
3033
|
row = await update(cms, row, {
|
|
2992
3034
|
state: "done",
|
|
@@ -3113,8 +3155,20 @@ async function downloadBackup(cms, id, by) {
|
|
|
3113
3155
|
const file = await (await backupStorage(cms)).get(row.filename);
|
|
3114
3156
|
if (!file)
|
|
3115
3157
|
throw new EasyCMSError(`The file ${row.filename} is no longer in the backup storage`, 404);
|
|
3158
|
+
let { filename } = row;
|
|
3159
|
+
let body = file.body;
|
|
3160
|
+
if (filename.endsWith(".enc")) {
|
|
3161
|
+
const encryptionKey = cms.config.backups?.encryptionKey;
|
|
3162
|
+
if (!encryptionKey)
|
|
3163
|
+
throw new EasyCMSError(
|
|
3164
|
+
"This backup is encrypted: set backups.encryptionKey to download it",
|
|
3165
|
+
400
|
|
3166
|
+
);
|
|
3167
|
+
body = decryptBackup(body, encryptionKey);
|
|
3168
|
+
filename = filename.slice(0, -".enc".length);
|
|
3169
|
+
}
|
|
3116
3170
|
await update(cms, row, { downloadedBy: by, downloadedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
3117
|
-
return { filename
|
|
3171
|
+
return { filename, body };
|
|
3118
3172
|
}
|
|
3119
3173
|
async function deleteBackup(cms, id) {
|
|
3120
3174
|
const row = await cms.db.findById({ collection: DATABASE_BACKUPS, id });
|
|
@@ -4207,7 +4261,7 @@ var AUTH = keys(`roles rbac tokenExpiration maxLoginAttempts lockWindow trustedO
|
|
|
4207
4261
|
resetPasswordExpiration inviteExpiration providers providerSignUp password setupCode members emails`);
|
|
4208
4262
|
var MEMBERS = keys("roles signUp pages emails");
|
|
4209
4263
|
var UPLOAD = keys("dir maxFileSize mimeTypes storage imageSizes fromURL folders privateStorage");
|
|
4210
|
-
var BACKUPS = keys("frequency at keep dir storage sqlite");
|
|
4264
|
+
var BACKUPS = keys("frequency at keep dir storage sqlite encryptionKey");
|
|
4211
4265
|
var AUDIT = keys("keepDays values failedLogins scope");
|
|
4212
4266
|
var COLLECTION = keys(`slug labels fields useAsTitle drafts versions schedule preview access hooks
|
|
4213
4267
|
admin`);
|
|
@@ -4649,7 +4703,7 @@ function validateConfig(config) {
|
|
|
4649
4703
|
validateAdmin(config, add);
|
|
4650
4704
|
validateAdminViews(config, add);
|
|
4651
4705
|
validateUpload(config, add);
|
|
4652
|
-
validateBackups(config, add);
|
|
4706
|
+
validateBackups(config, add, (issue) => issues.push(issue));
|
|
4653
4707
|
validateAudit(config, add);
|
|
4654
4708
|
validateAuth(config, add);
|
|
4655
4709
|
validateCors(config.cors, add);
|
|
@@ -4737,6 +4791,14 @@ function validateCronSecret(value, push) {
|
|
|
4737
4791
|
severity: "warning"
|
|
4738
4792
|
});
|
|
4739
4793
|
}
|
|
4794
|
+
function publicURLs(storage) {
|
|
4795
|
+
const url = storage.url;
|
|
4796
|
+
try {
|
|
4797
|
+
return typeof url === "function" && url.call(storage, "backup.db.gz") !== void 0;
|
|
4798
|
+
} catch {
|
|
4799
|
+
return false;
|
|
4800
|
+
}
|
|
4801
|
+
}
|
|
4740
4802
|
function guessable(secret) {
|
|
4741
4803
|
return /change[-_ ]?me|example|placeholder|secret-?key/i.test(secret) || new Set(secret).size < 8;
|
|
4742
4804
|
}
|
|
@@ -5254,14 +5316,21 @@ function validateAudit(config, add) {
|
|
|
5254
5316
|
}
|
|
5255
5317
|
}
|
|
5256
5318
|
}
|
|
5257
|
-
function validateBackups(config, add) {
|
|
5319
|
+
function validateBackups(config, add, push) {
|
|
5320
|
+
const pushWarning = (path, message2, hint) => push({ path, message: message2, hint, severity: "warning" });
|
|
5258
5321
|
const backups = config.backups;
|
|
5259
5322
|
if (backups === void 0) return;
|
|
5260
5323
|
if (typeof backups !== "object" || backups === null) {
|
|
5261
5324
|
add("backups", "must be an object", "e.g. backups: { frequency: 'daily', keep: 7 }");
|
|
5262
5325
|
return;
|
|
5263
5326
|
}
|
|
5264
|
-
const { frequency, at, keep, dir, storage, sqlite } = backups;
|
|
5327
|
+
const { frequency, at, keep, dir, storage, sqlite, encryptionKey } = backups;
|
|
5328
|
+
if (encryptionKey !== void 0 && (typeof encryptionKey !== "string" || encryptionKey.length < MIN_SECRET_LENGTH))
|
|
5329
|
+
add(
|
|
5330
|
+
"backups.encryptionKey",
|
|
5331
|
+
`must be at least ${MIN_SECRET_LENGTH} characters`,
|
|
5332
|
+
"e.g. `openssl rand -hex 32`, kept somewhere other than the backups"
|
|
5333
|
+
);
|
|
5265
5334
|
if (frequency !== void 0 && frequency !== "daily" && frequency !== "weekly")
|
|
5266
5335
|
add("backups.frequency", 'must be "daily" or "weekly"');
|
|
5267
5336
|
if (at !== void 0 && (typeof at !== "string" || !/^([01]\d|2[0-3]):[0-5]\d$/.test(at)))
|
|
@@ -5274,6 +5343,14 @@ function validateBackups(config, add) {
|
|
|
5274
5343
|
add("backups.dir", "must not be the uploads folder: uploads are served publicly");
|
|
5275
5344
|
if (storage !== void 0 && (typeof storage !== "object" || storage === null || typeof storage.put !== "function"))
|
|
5276
5345
|
add("backups.storage", "must be a storage adapter, e.g. s3Storage()");
|
|
5346
|
+
else if (storage !== void 0 && publicURLs(storage)) {
|
|
5347
|
+
const message2 = encryptionKey ? "gives files public URLs; the backups are encrypted, but keep them in a private bucket" : "gives files public URLs: anyone with the address of a backup could download the whole database";
|
|
5348
|
+
pushWarning(
|
|
5349
|
+
"backups.storage",
|
|
5350
|
+
message2,
|
|
5351
|
+
"use a private bucket (no publicURL), or set backups.encryptionKey"
|
|
5352
|
+
);
|
|
5353
|
+
}
|
|
5277
5354
|
if (sqlite !== void 0 && typeof sqlite !== "function")
|
|
5278
5355
|
add(
|
|
5279
5356
|
"backups.sqlite",
|
|
@@ -6069,7 +6146,7 @@ function resolveAudit(audit) {
|
|
|
6069
6146
|
}
|
|
6070
6147
|
|
|
6071
6148
|
// src/local-api.ts
|
|
6072
|
-
import { createHmac as createHmac6, randomBytes as
|
|
6149
|
+
import { createHmac as createHmac6, randomBytes as randomBytes6, timingSafeEqual as timingSafeEqual5 } from "crypto";
|
|
6073
6150
|
|
|
6074
6151
|
// src/auth/common-passwords.ts
|
|
6075
6152
|
var LIST = `
|
|
@@ -6833,7 +6910,7 @@ var EasyCMS = class {
|
|
|
6833
6910
|
}
|
|
6834
6911
|
]);
|
|
6835
6912
|
}
|
|
6836
|
-
const random2 =
|
|
6913
|
+
const random2 = randomBytes6(4).toString("hex");
|
|
6837
6914
|
const isPrivate = await this.folders.isPrivate(folderOf(MEDIA, data));
|
|
6838
6915
|
const storage = this.storageFor(isPrivate);
|
|
6839
6916
|
const filename = withPrivacy(storageKey(file.name, mimeType, random2), isPrivate);
|
|
@@ -6901,7 +6978,7 @@ var EasyCMS = class {
|
|
|
6901
6978
|
]);
|
|
6902
6979
|
const isPrivate = await this.folders.isPrivate(folder);
|
|
6903
6980
|
const storage = this.storageFor(isPrivate);
|
|
6904
|
-
const key = withPrivacy(storageKey(name, type,
|
|
6981
|
+
const key = withPrivacy(storageKey(name, type, randomBytes6(4).toString("hex")), isPrivate);
|
|
6905
6982
|
const upload = storage.uploadURL ? await storage.uploadURL(key, { contentType: type, size, expiresIn: UPLOAD_URL_SECONDS }) : null;
|
|
6906
6983
|
const ticket = this.sign("upload", {
|
|
6907
6984
|
key,
|
|
@@ -9060,7 +9137,7 @@ function durationSeconds(value) {
|
|
|
9060
9137
|
}
|
|
9061
9138
|
|
|
9062
9139
|
// src/rest/admin-modules.ts
|
|
9063
|
-
import { createHash as
|
|
9140
|
+
import { createHash as createHash4 } from "crypto";
|
|
9064
9141
|
import { readFile as readFile3 } from "fs/promises";
|
|
9065
9142
|
import { createRequire } from "module";
|
|
9066
9143
|
import { join as join3 } from "path";
|
|
@@ -9101,11 +9178,11 @@ async function readAdminModule(cms, index) {
|
|
|
9101
9178
|
if (!file) return void 0;
|
|
9102
9179
|
const body = await readFile3(file, "utf8").catch(() => void 0);
|
|
9103
9180
|
if (body === void 0) return void 0;
|
|
9104
|
-
return { body, etag: `"${
|
|
9181
|
+
return { body, etag: `"${createHash4("sha1").update(body).digest("base64url")}"` };
|
|
9105
9182
|
}
|
|
9106
9183
|
|
|
9107
9184
|
// src/version.ts
|
|
9108
|
-
var VERSION = true ? "0.
|
|
9185
|
+
var VERSION = true ? "0.65.0" : "0.0.0-dev";
|
|
9109
9186
|
|
|
9110
9187
|
// src/rest/admin-deliveries.ts
|
|
9111
9188
|
var PER_PAGE = 50;
|
|
@@ -11376,6 +11453,7 @@ export {
|
|
|
11376
11453
|
configSignature,
|
|
11377
11454
|
copyDatabase,
|
|
11378
11455
|
diskStorage,
|
|
11456
|
+
decryptBackup,
|
|
11379
11457
|
writeBackupFile,
|
|
11380
11458
|
consoleLogger,
|
|
11381
11459
|
silentLogger,
|
|
@@ -2148,7 +2148,11 @@ interface AuditVerification {
|
|
|
2148
2148
|
checked: number;
|
|
2149
2149
|
/** Entries whose signature does not match: changed after they were written. */
|
|
2150
2150
|
invalid: ID[];
|
|
2151
|
-
/**
|
|
2151
|
+
/**
|
|
2152
|
+
* Missing ids between entries: deleted entries, or (rarely) inserts that failed. Ids are never
|
|
2153
|
+
* reused, so the newest entries deleted show up here once anything is written after them (a
|
|
2154
|
+
* check writes an entry itself). The server's log has each check's last id, to compare with.
|
|
2155
|
+
*/
|
|
2152
2156
|
gaps: number;
|
|
2153
2157
|
at: string;
|
|
2154
2158
|
}
|
|
@@ -3102,6 +3106,13 @@ interface BackupsConfig {
|
|
|
3102
3106
|
readonly dir?: string;
|
|
3103
3107
|
/** Where backups are stored instead, e.g. `s3Storage()` with a private bucket. */
|
|
3104
3108
|
readonly storage?: StorageAdapter;
|
|
3109
|
+
/**
|
|
3110
|
+
* Encrypts the backup files (AES-256-GCM), so a leaked bucket or disk holds nothing readable.
|
|
3111
|
+
* At least 32 characters, e.g. from `process.env.EASY_CMS_BACKUP_KEY`; keep a copy somewhere
|
|
3112
|
+
* other than the backups: without it they can't be restored. Downloads from the admin are
|
|
3113
|
+
* decrypted; `easy-cms backup:decrypt <file>` decrypts one by hand.
|
|
3114
|
+
*/
|
|
3115
|
+
readonly encryptionKey?: string;
|
|
3105
3116
|
/**
|
|
3106
3117
|
* For Postgres: the SQLite adapter that writes the backup file, `sqlite` from
|
|
3107
3118
|
* `@easy-cms/db-sqlite`. SQLite databases back themselves up and don't need it.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { I as ID, ab as Config, au as EasyCMS, bd as LocalizationConfig, aD as Field, aH as FieldError, aS as FilterOptions, af as CreateEasyCMSOptions, bI as ResolvedConfig } from './config-
|
|
1
|
+
import { I as ID, ab as Config, au as EasyCMS, bd as LocalizationConfig, aD as Field, aH as FieldError, aS as FilterOptions, af as CreateEasyCMSOptions, bI as ResolvedConfig } from './config-DE8ez-a9.js';
|
|
2
2
|
|
|
3
|
+
/** Decrypts a file from `encryptBackup`; throws for another key or a changed file. */
|
|
4
|
+
declare function decryptBackup(data: Uint8Array, encryptionKey: string): Uint8Array;
|
|
3
5
|
type BackupState = 'pending' | 'running' | 'done' | 'failed';
|
|
4
6
|
/** One backup as the admin shows it (`GET <api>/admin/backups`). */
|
|
5
7
|
interface AdminBackup {
|
|
@@ -191,4 +193,4 @@ declare function createRootEndpointHandler<C extends Config>(instance: EasyCMS<C
|
|
|
191
193
|
/** A cookie of the request; the `__Host-` one (set over HTTPS) first. */
|
|
192
194
|
declare function readCookie(request: Request, name: string): string | undefined;
|
|
193
195
|
|
|
194
|
-
export { type AdminBackup as A, type BackupState as B, CONFIG_FILE_NAMES as C, DEFAULT_ADMIN_PATH as D,
|
|
196
|
+
export { type AdminBackup as A, type BackupState as B, CONFIG_FILE_NAMES as C, DEFAULT_ADMIN_PATH as D, readCookie as E, validateFields as F, writeBackupFile as G, type LoadConfigOptions as L, type RestHandler as R, type AdminBackups as a, type ApiHandlerOptions as b, type RestHandlerOptions as c, createApiHandler as d, createRestHandler as e, slugify as f, CSRF_COOKIE as g, CSRF_HEADER as h, DEFAULT_API_PATH as i, DEFAULT_MAX_FILE_SIZE as j, DEFAULT_TOKEN_EXPIRATION as k, loadConfig as l, applyDefaults as m, applyPlugins as n, createRootEndpointHandler as o, decryptBackup as p, fillMissing as q, resolveConfig as r, sharedEasyCMS as s, findConfigFile as t, forwardedClientIp as u, generateSlugs as v, importConfig as w, mergeForUpdate as x, parseId as y, platformClientIp as z };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { P as PaginatedDocs, I as ID, E as EmailSetting } from './config-
|
|
2
|
-
export { A as ADAPTER_API_VERSION, a as ADMIN_ICONS, b as Access, c as AccessArgs, d as AccessOptions, e as AdminBrand, f as AdminCommand, g as AdminComponent, h as AdminConfig, i as AdminFieldArgs, j as AdminIcon, k as AdminLocale, l as AdminPage, m as AdminRole, n as AdminRoleChange, o as AdminRoleField, p as AdminRoleTarget, q as AdminRoleView, r as AdminRoles, s as AdminSso, t as AdminSwitcher, u as AdminViewAccess, v as AfterChangeHook, w as AfterDeleteHook, x as AfterReadHook, y as ApiKeyContext, z as ApiKeyGlobalOperation, B as ApiKeyOperation, C as ApiKeyPermissions, D as ArrayField, F as AuditChange, G as AuditConfig, H as AuditEntry, J as AuditLog, K as AuditPage, L as AuditVerification, M as Auth, N as AuthConfig, O as AuthProvider, Q as AuthProviderProfile, R as AuthProviderRequest, S as AuthUser, T as BackupsConfig, U as BeforeChangeHook, V as BeforeDeleteHook, W as BeforeValidateHook, X as Block, Y as BlocksField, Z as BooleanField, _ as BuiltinApiKeysCollection, $ as BuiltinMediaCollection, a0 as BuiltinMediaFoldersCollection, a1 as BuiltinUsersCollection, a2 as BundleHints, a3 as CliCommand, a4 as CollectionAccess, a5 as CollectionAdmin, a6 as CollectionConfig, a7 as CollectionDocument, a8 as CollectionHooks, a9 as CollectionListAdmin, aa as CollectionSlug, ab as Config, ac as ConfigError, ad as ConfigIssue, ae as ContainerAdmin, af as CreateEasyCMSOptions, ag as CreateInput, ah as CreateMigrationResult, ai as CustomField, aj as CustomFieldTypes, ak as DashboardWidget, al as Database, am as DatabaseAdapter, an as DatabaseInitArgs, ao as DatabaseTransfer, ap as DateField, aq as DepthOptions, ar as DirectUpload, as as DiskStorageOptions, at as DocumentOf, au as EasyCMS, av as EasyCMSError, aw as EmailAdapter, ax as EmailField, ay as EmailMessage, az as Endpoint, aA as EndpointRequest, aB as ErrorCode, aC as FIELD_TYPES, aD as Field, aE as FieldAccess, aF as FieldAccessFn, aG as FieldAdmin, aH as FieldError, aI as FieldRule, aJ as FieldType, aK as FieldTypeBase, aL as FieldTypeDefinition, aM as FieldTypeValidateContext, aN as FieldValidate, aO as FieldValidateContext, aP as FieldValue, aQ as FieldsInput, aR as FieldsValue, aS as FilterOptions, aT as FilterOptionsArgs, aU as FindArgs, aV as FindOptions, aW as FolderLevel, aX as FolderPermissions, aY as ForbiddenError, aZ as GlobalAccess, a_ as GlobalConfig, a$ as GlobalDocument, b0 as GlobalHooks, b1 as GlobalInput, b2 as GlobalSlug, b3 as GroupField, b4 as ImageSize, b5 as IncrementOptions, b6 as InferCollection, b7 as InferGlobal, b8 as JobConfig, b9 as JsonField, ba as Label, bb as LayoutNode, bc as LivePreview, bd as LocalizationConfig, be as Logger, bf as LoginArgs, bg as MediaDocument, bh as MediaSize, bi as MembersConfig, bj as MembersSignup, bk as MigrationInfo, bl as NavGroup, bm as NotFoundError, bn as NumberField, bo as OnRequest, bp as OnRequestArgs, bq as Operation, br as PLUGIN_API_VERSION, bs as PasswordEmail, bt as PasswordEmailArgs, bu as PasswordEmailFn, bv as PasswordLinkOptions, bw as PayloadTooLargeError, bx as Plugin, by as PluginInfo, bz as PluginTypes, bA as PreviewTarget, bB as PreviewURL, bC as QueryError, bD as ROLE_OPERATIONS, bE as RawDocument, bF as ReadOptions, bG as RelationshipField, bH as RequestContext, bI as ResolvedConfig, bJ as RichTextDocument, bK as RichTextField, bL as Role, bM as RoleOperation, bN as RolePermissions, bO as Roles, bP as RoutesConfig, bQ as ScheduledPublish, bR as SchemaError, bS as SchemaMode, bT as SelectField, bU as SelectOption, bV as Session, bW as SidebarPanel, bX as SignupArgs, bY as SignupResult, bZ as SingleSignOn, b_ as SlugField, b$ as SlugOf, c0 as SsoOutcome, c1 as SsoProviderRef, c2 as StorageAdapter, c3 as StoredFile, c4 as TextField, c5 as TextareaField, c6 as TooManyRequestsError, c7 as TypedPlugin, c8 as UnauthorizedError, c9 as UpdateInput, ca as UpdateOptions, cb as UploadConfig, cc as UploadField, cd as UploadFromURLConfig, ce as UserIdentity, cf as ValidationError, cg as Version, ch as VersionSummary, ci as VersionsConfig, cj as WEBHOOK_EVENTS, ck as WebhookConfig, cl as WebhookEvent, cm as WebhookPayload, cn as Where, co as WhereOperators, cp as anyone, cq as consoleEmail, cr as consoleLogger, cs as createEasyCMS, ct as defineConfig, cu as defineFieldType, cv as definePlugin, cw as diskStorage, cx as hasRows, cy as isAdmin, cz as isHasMany, cA as isSignedIn, cB as isStaff, cC as isSystemAdmin, cD as mimeAllowedBy, cE as rowFields, cF as silentLogger, cG 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, E as EmailSetting } from './config-DE8ez-a9.js';
|
|
2
|
+
export { A as ADAPTER_API_VERSION, a as ADMIN_ICONS, b as Access, c as AccessArgs, d as AccessOptions, e as AdminBrand, f as AdminCommand, g as AdminComponent, h as AdminConfig, i as AdminFieldArgs, j as AdminIcon, k as AdminLocale, l as AdminPage, m as AdminRole, n as AdminRoleChange, o as AdminRoleField, p as AdminRoleTarget, q as AdminRoleView, r as AdminRoles, s as AdminSso, t as AdminSwitcher, u as AdminViewAccess, v as AfterChangeHook, w as AfterDeleteHook, x as AfterReadHook, y as ApiKeyContext, z as ApiKeyGlobalOperation, B as ApiKeyOperation, C as ApiKeyPermissions, D as ArrayField, F as AuditChange, G as AuditConfig, H as AuditEntry, J as AuditLog, K as AuditPage, L as AuditVerification, M as Auth, N as AuthConfig, O as AuthProvider, Q as AuthProviderProfile, R as AuthProviderRequest, S as AuthUser, T as BackupsConfig, U as BeforeChangeHook, V as BeforeDeleteHook, W as BeforeValidateHook, X as Block, Y as BlocksField, Z as BooleanField, _ as BuiltinApiKeysCollection, $ as BuiltinMediaCollection, a0 as BuiltinMediaFoldersCollection, a1 as BuiltinUsersCollection, a2 as BundleHints, a3 as CliCommand, a4 as CollectionAccess, a5 as CollectionAdmin, a6 as CollectionConfig, a7 as CollectionDocument, a8 as CollectionHooks, a9 as CollectionListAdmin, aa as CollectionSlug, ab as Config, ac as ConfigError, ad as ConfigIssue, ae as ContainerAdmin, af as CreateEasyCMSOptions, ag as CreateInput, ah as CreateMigrationResult, ai as CustomField, aj as CustomFieldTypes, ak as DashboardWidget, al as Database, am as DatabaseAdapter, an as DatabaseInitArgs, ao as DatabaseTransfer, ap as DateField, aq as DepthOptions, ar as DirectUpload, as as DiskStorageOptions, at as DocumentOf, au as EasyCMS, av as EasyCMSError, aw as EmailAdapter, ax as EmailField, ay as EmailMessage, az as Endpoint, aA as EndpointRequest, aB as ErrorCode, aC as FIELD_TYPES, aD as Field, aE as FieldAccess, aF as FieldAccessFn, aG as FieldAdmin, aH as FieldError, aI as FieldRule, aJ as FieldType, aK as FieldTypeBase, aL as FieldTypeDefinition, aM as FieldTypeValidateContext, aN as FieldValidate, aO as FieldValidateContext, aP as FieldValue, aQ as FieldsInput, aR as FieldsValue, aS as FilterOptions, aT as FilterOptionsArgs, aU as FindArgs, aV as FindOptions, aW as FolderLevel, aX as FolderPermissions, aY as ForbiddenError, aZ as GlobalAccess, a_ as GlobalConfig, a$ as GlobalDocument, b0 as GlobalHooks, b1 as GlobalInput, b2 as GlobalSlug, b3 as GroupField, b4 as ImageSize, b5 as IncrementOptions, b6 as InferCollection, b7 as InferGlobal, b8 as JobConfig, b9 as JsonField, ba as Label, bb as LayoutNode, bc as LivePreview, bd as LocalizationConfig, be as Logger, bf as LoginArgs, bg as MediaDocument, bh as MediaSize, bi as MembersConfig, bj as MembersSignup, bk as MigrationInfo, bl as NavGroup, bm as NotFoundError, bn as NumberField, bo as OnRequest, bp as OnRequestArgs, bq as Operation, br as PLUGIN_API_VERSION, bs as PasswordEmail, bt as PasswordEmailArgs, bu as PasswordEmailFn, bv as PasswordLinkOptions, bw as PayloadTooLargeError, bx as Plugin, by as PluginInfo, bz as PluginTypes, bA as PreviewTarget, bB as PreviewURL, bC as QueryError, bD as ROLE_OPERATIONS, bE as RawDocument, bF as ReadOptions, bG as RelationshipField, bH as RequestContext, bI as ResolvedConfig, bJ as RichTextDocument, bK as RichTextField, bL as Role, bM as RoleOperation, bN as RolePermissions, bO as Roles, bP as RoutesConfig, bQ as ScheduledPublish, bR as SchemaError, bS as SchemaMode, bT as SelectField, bU as SelectOption, bV as Session, bW as SidebarPanel, bX as SignupArgs, bY as SignupResult, bZ as SingleSignOn, b_ as SlugField, b$ as SlugOf, c0 as SsoOutcome, c1 as SsoProviderRef, c2 as StorageAdapter, c3 as StoredFile, c4 as TextField, c5 as TextareaField, c6 as TooManyRequestsError, c7 as TypedPlugin, c8 as UnauthorizedError, c9 as UpdateInput, ca as UpdateOptions, cb as UploadConfig, cc as UploadField, cd as UploadFromURLConfig, ce as UserIdentity, cf as ValidationError, cg as Version, ch as VersionSummary, ci as VersionsConfig, cj as WEBHOOK_EVENTS, ck as WebhookConfig, cl as WebhookEvent, cm as WebhookPayload, cn as Where, co as WhereOperators, cp as anyone, cq as consoleEmail, cr as consoleLogger, cs as createEasyCMS, ct as defineConfig, cu as defineFieldType, cv as definePlugin, cw as diskStorage, cx as hasRows, cy as isAdmin, cz as isHasMany, cA as isSignedIn, cB as isStaff, cC as isSystemAdmin, cD as mimeAllowedBy, cE as rowFields, cF as silentLogger, cG as uniqueWithinOf } from './config-DE8ez-a9.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-CX7E7RZZ.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-Cm1ehtkm.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
|
-
import { ab as Config, al as Database, bl as NavGroup, a6 as CollectionConfig, I as ID, bE as RawDocument, aD as Field, bI as ResolvedConfig, ad as ConfigIssue } from './config-
|
|
2
|
-
export { cH as API_KEYS, cI as API_KEY_GLOBAL_OPERATIONS, cJ as API_KEY_OPERATIONS, cK as DEFAULT_MAX_VERSIONS, cL as DEFAULT_PASSWORD_EMAILS, cM as FIELD_TYPE_BASES, cN as FOLDER_LEVELS, cO as MediaFolders, cP as SSO_COOKIE, cQ as codeOfStatus, cx as hasRows, cz as isHasMany, cR as keyAllows, cD as mimeAllowedBy, cE as rowFields, cG 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
|
|
1
|
+
import { ab as Config, al as Database, bl as NavGroup, a6 as CollectionConfig, I as ID, bE as RawDocument, aD as Field, bI as ResolvedConfig, ad as ConfigIssue } from './config-DE8ez-a9.js';
|
|
2
|
+
export { cH as API_KEYS, cI as API_KEY_GLOBAL_OPERATIONS, cJ as API_KEY_OPERATIONS, cK as DEFAULT_MAX_VERSIONS, cL as DEFAULT_PASSWORD_EMAILS, cM as FIELD_TYPE_BASES, cN as FOLDER_LEVELS, cO as MediaFolders, cP as SSO_COOKIE, cQ as codeOfStatus, cx as hasRows, cz as isHasMany, cR as keyAllows, cD as mimeAllowedBy, cE as rowFields, cG as uniqueWithinOf } from './config-DE8ez-a9.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 mergeForUpdate, y as parseId, z as platformClientIp, E as readCookie, F as validateFields, G as writeBackupFile } from './handler-Cm1ehtkm.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
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
configSignature,
|
|
32
32
|
copyDatabase,
|
|
33
33
|
createRootEndpointHandler,
|
|
34
|
+
decryptBackup,
|
|
34
35
|
fillMissing,
|
|
35
36
|
findConfigFile,
|
|
36
37
|
formToken,
|
|
@@ -52,7 +53,7 @@ import {
|
|
|
52
53
|
verifyPassword,
|
|
53
54
|
verifyTurnstile,
|
|
54
55
|
writeBackupFile
|
|
55
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-BGGQ36LR.js";
|
|
56
57
|
import {
|
|
57
58
|
conditionIssues
|
|
58
59
|
} from "./chunk-U266LV4M.js";
|
|
@@ -275,6 +276,7 @@ export {
|
|
|
275
276
|
configSignature,
|
|
276
277
|
copyDatabase,
|
|
277
278
|
createRootEndpointHandler,
|
|
279
|
+
decryptBackup,
|
|
278
280
|
expandMimeTypes,
|
|
279
281
|
fillMissing,
|
|
280
282
|
findConfigFile,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ba as Label, aD as Field, I as ID, k as AdminLocale, t as AdminSwitcher, c1 as SsoProviderRef } from './config-
|
|
1
|
+
import { ba as Label, aD as Field, I as ID, k as AdminLocale, t as AdminSwitcher, c1 as SsoProviderRef } from './config-DE8ez-a9.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 { a as ADMIN_ICONS, g as AdminComponent, j as AdminIcon, S as AuthUser, a3 as CliCommand, a4 as CollectionAccess, a6 as CollectionConfig, ab as Config, ac as ConfigError, ak as DashboardWidget, av as EasyCMSError, az as Endpoint, aA as EndpointRequest, aB as ErrorCode, aD as Field, aE as FieldAccess, aH as FieldError, aK as FieldTypeBase, aL as FieldTypeDefinition, aM as FieldTypeValidateContext, aY as ForbiddenError, a_ as GlobalConfig, I as ID, b8 as JobConfig, ba as Label, bl as NavGroup, bm as NotFoundError, bo as OnRequest, bp as OnRequestArgs, br as PLUGIN_API_VERSION, bw as PayloadTooLargeError, bx as Plugin, by as PluginInfo, bz as PluginTypes, bC as QueryError, bH as RequestContext, c6 as TooManyRequestsError, c7 as TypedPlugin, c8 as UnauthorizedError, cf as ValidationError, cn as Where, cu as defineFieldType, cv 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 { a as ADMIN_ICONS, g as AdminComponent, j as AdminIcon, S as AuthUser, a3 as CliCommand, a4 as CollectionAccess, a6 as CollectionConfig, ab as Config, ac as ConfigError, ak as DashboardWidget, av as EasyCMSError, az as Endpoint, aA as EndpointRequest, aB as ErrorCode, aD as Field, aE as FieldAccess, aH as FieldError, aK as FieldTypeBase, aL as FieldTypeDefinition, aM as FieldTypeValidateContext, aY as ForbiddenError, a_ as GlobalConfig, I as ID, b8 as JobConfig, ba as Label, bl as NavGroup, bm as NotFoundError, bo as OnRequest, bp as OnRequestArgs, br as PLUGIN_API_VERSION, bw as PayloadTooLargeError, bx as Plugin, by as PluginInfo, bz as PluginTypes, bC as QueryError, bH as RequestContext, c6 as TooManyRequestsError, c7 as TypedPlugin, c8 as UnauthorizedError, cf as ValidationError, cn as Where, cu as defineFieldType, cv as definePlugin } from './config-DE8ez-a9.js';
|
|
2
|
+
export { A as ADMIN_API_VERSION, c as AdminElementProps, k as AdminPageRoute, S as SetFieldDetail, w as warnDeprecated } from './plugin-CX7E7RZZ.js';
|
|
3
3
|
import './conditions.js';
|