@insforge/cli 0.1.78 → 0.1.79
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/index.js +359 -73
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1172,7 +1172,7 @@ import * as clack5 from "@clack/prompts";
|
|
|
1172
1172
|
|
|
1173
1173
|
// src/lib/analytics.ts
|
|
1174
1174
|
import { PostHog } from "posthog-node";
|
|
1175
|
-
var POSTHOG_API_KEY = "";
|
|
1175
|
+
var POSTHOG_API_KEY = "phc_ueV1ii62wdBTkH7E70ugyeqHIHu8dFDdjs0qq3TZhJz";
|
|
1176
1176
|
var POSTHOG_HOST = process.env.POSTHOG_HOST || "https://us.i.posthog.com";
|
|
1177
1177
|
var client = null;
|
|
1178
1178
|
function getClient() {
|
|
@@ -6961,7 +6961,7 @@ function registerDiagnoseCommands(diagnoseCmd2) {
|
|
|
6961
6961
|
const s = !json ? clack15.spinner() : null;
|
|
6962
6962
|
s?.start("Collecting diagnostic data...");
|
|
6963
6963
|
const data2 = await collectDiagnosticData(projectId, ossMode, apiUrl);
|
|
6964
|
-
const cliVersion = "0.1.
|
|
6964
|
+
const cliVersion = "0.1.79";
|
|
6965
6965
|
s?.stop("Data collected");
|
|
6966
6966
|
if (!json) {
|
|
6967
6967
|
console.log(`
|
|
@@ -9190,9 +9190,67 @@ function validateAuth(input) {
|
|
|
9190
9190
|
}
|
|
9191
9191
|
out.allowed_redirect_urls = v;
|
|
9192
9192
|
}
|
|
9193
|
+
if ("require_email_verification" in obj) {
|
|
9194
|
+
if (typeof obj.require_email_verification !== "boolean") {
|
|
9195
|
+
throw new ConfigValidationError(
|
|
9196
|
+
"auth.require_email_verification",
|
|
9197
|
+
"must be a boolean"
|
|
9198
|
+
);
|
|
9199
|
+
}
|
|
9200
|
+
out.require_email_verification = obj.require_email_verification;
|
|
9201
|
+
}
|
|
9202
|
+
if ("verify_email_method" in obj) {
|
|
9203
|
+
out.verify_email_method = validateVerificationMethod(
|
|
9204
|
+
"auth.verify_email_method",
|
|
9205
|
+
obj.verify_email_method
|
|
9206
|
+
);
|
|
9207
|
+
}
|
|
9208
|
+
if ("reset_password_method" in obj) {
|
|
9209
|
+
out.reset_password_method = validateVerificationMethod(
|
|
9210
|
+
"auth.reset_password_method",
|
|
9211
|
+
obj.reset_password_method
|
|
9212
|
+
);
|
|
9213
|
+
}
|
|
9214
|
+
if ("password" in obj) out.password = validatePassword(obj.password);
|
|
9193
9215
|
if ("smtp" in obj) out.smtp = validateSmtp(obj.smtp);
|
|
9194
9216
|
return out;
|
|
9195
9217
|
}
|
|
9218
|
+
function validateVerificationMethod(path6, value) {
|
|
9219
|
+
if (value !== "code" && value !== "link") {
|
|
9220
|
+
throw new ConfigValidationError(path6, 'must be "code" or "link"');
|
|
9221
|
+
}
|
|
9222
|
+
return value;
|
|
9223
|
+
}
|
|
9224
|
+
function validatePassword(input) {
|
|
9225
|
+
if (input === null || typeof input !== "object" || Array.isArray(input)) {
|
|
9226
|
+
throw new ConfigValidationError("auth.password", "must be a table");
|
|
9227
|
+
}
|
|
9228
|
+
const obj = input;
|
|
9229
|
+
const out = {};
|
|
9230
|
+
if ("min_length" in obj) {
|
|
9231
|
+
if (typeof obj.min_length !== "number" || !Number.isInteger(obj.min_length) || obj.min_length < 4 || obj.min_length > 128) {
|
|
9232
|
+
throw new ConfigValidationError(
|
|
9233
|
+
"auth.password.min_length",
|
|
9234
|
+
"must be an integer between 4 and 128"
|
|
9235
|
+
);
|
|
9236
|
+
}
|
|
9237
|
+
out.min_length = obj.min_length;
|
|
9238
|
+
}
|
|
9239
|
+
for (const key of [
|
|
9240
|
+
"require_number",
|
|
9241
|
+
"require_lowercase",
|
|
9242
|
+
"require_uppercase",
|
|
9243
|
+
"require_special_char"
|
|
9244
|
+
]) {
|
|
9245
|
+
if (key in obj) {
|
|
9246
|
+
if (typeof obj[key] !== "boolean") {
|
|
9247
|
+
throw new ConfigValidationError(`auth.password.${key}`, "must be a boolean");
|
|
9248
|
+
}
|
|
9249
|
+
out[key] = obj[key];
|
|
9250
|
+
}
|
|
9251
|
+
}
|
|
9252
|
+
return out;
|
|
9253
|
+
}
|
|
9196
9254
|
function validateSmtp(input) {
|
|
9197
9255
|
if (input === null || typeof input !== "object" || Array.isArray(input)) {
|
|
9198
9256
|
throw new ConfigValidationError("auth.smtp", "must be a table");
|
|
@@ -9275,11 +9333,13 @@ function stringifyConfigToml(config) {
|
|
|
9275
9333
|
}
|
|
9276
9334
|
if (config.auth) {
|
|
9277
9335
|
lines.push("[auth]");
|
|
9278
|
-
|
|
9279
|
-
const urls = config.auth.allowed_redirect_urls.map((u) => JSON.stringify(u)).join(", ");
|
|
9280
|
-
lines.push(`allowed_redirect_urls = [${urls}]`);
|
|
9281
|
-
}
|
|
9336
|
+
renderAuthFlatFields(config.auth, lines);
|
|
9282
9337
|
lines.push("");
|
|
9338
|
+
if (config.auth.password !== void 0) {
|
|
9339
|
+
lines.push("[auth.password]");
|
|
9340
|
+
renderPasswordFields(config.auth.password, lines);
|
|
9341
|
+
lines.push("");
|
|
9342
|
+
}
|
|
9283
9343
|
if (config.auth.smtp !== void 0) {
|
|
9284
9344
|
lines.push("[auth.smtp]");
|
|
9285
9345
|
renderSmtpFields(config.auth.smtp, lines);
|
|
@@ -9295,6 +9355,34 @@ function stringifyConfigToml(config) {
|
|
|
9295
9355
|
}
|
|
9296
9356
|
return lines.join("\n").replace(/\n+$/, "\n");
|
|
9297
9357
|
}
|
|
9358
|
+
function renderAuthFlatFields(auth, lines) {
|
|
9359
|
+
if (auth.allowed_redirect_urls !== void 0) {
|
|
9360
|
+
const urls = auth.allowed_redirect_urls.map((u) => JSON.stringify(u)).join(", ");
|
|
9361
|
+
lines.push(`allowed_redirect_urls = [${urls}]`);
|
|
9362
|
+
}
|
|
9363
|
+
if (auth.require_email_verification !== void 0) {
|
|
9364
|
+
lines.push(`require_email_verification = ${auth.require_email_verification}`);
|
|
9365
|
+
}
|
|
9366
|
+
if (auth.verify_email_method !== void 0) {
|
|
9367
|
+
lines.push(`verify_email_method = ${JSON.stringify(auth.verify_email_method)}`);
|
|
9368
|
+
}
|
|
9369
|
+
if (auth.reset_password_method !== void 0) {
|
|
9370
|
+
lines.push(`reset_password_method = ${JSON.stringify(auth.reset_password_method)}`);
|
|
9371
|
+
}
|
|
9372
|
+
}
|
|
9373
|
+
function renderPasswordFields(pw, lines) {
|
|
9374
|
+
if (pw.min_length !== void 0) lines.push(`min_length = ${pw.min_length}`);
|
|
9375
|
+
if (pw.require_number !== void 0) lines.push(`require_number = ${pw.require_number}`);
|
|
9376
|
+
if (pw.require_lowercase !== void 0) {
|
|
9377
|
+
lines.push(`require_lowercase = ${pw.require_lowercase}`);
|
|
9378
|
+
}
|
|
9379
|
+
if (pw.require_uppercase !== void 0) {
|
|
9380
|
+
lines.push(`require_uppercase = ${pw.require_uppercase}`);
|
|
9381
|
+
}
|
|
9382
|
+
if (pw.require_special_char !== void 0) {
|
|
9383
|
+
lines.push(`require_special_char = ${pw.require_special_char}`);
|
|
9384
|
+
}
|
|
9385
|
+
}
|
|
9298
9386
|
function renderSmtpFields(smtp, lines) {
|
|
9299
9387
|
if (smtp.enabled !== void 0) lines.push(`enabled = ${smtp.enabled}`);
|
|
9300
9388
|
if (smtp.host !== void 0) lines.push(`host = ${JSON.stringify(smtp.host)}`);
|
|
@@ -9318,6 +9406,132 @@ function renderSmtpFields(smtp, lines) {
|
|
|
9318
9406
|
}
|
|
9319
9407
|
}
|
|
9320
9408
|
|
|
9409
|
+
// src/lib/config-metadata.ts
|
|
9410
|
+
function liveFromMetadata(raw) {
|
|
9411
|
+
const live = { auth: {} };
|
|
9412
|
+
const a = isPlainObject(raw.auth) ? raw.auth : void 0;
|
|
9413
|
+
if (a && "allowedRedirectUrls" in a) {
|
|
9414
|
+
live.auth.allowed_redirect_urls = asStringArray(a.allowedRedirectUrls) ?? [];
|
|
9415
|
+
}
|
|
9416
|
+
if (a && "requireEmailVerification" in a) {
|
|
9417
|
+
live.auth.require_email_verification = a.requireEmailVerification ?? false;
|
|
9418
|
+
}
|
|
9419
|
+
if (a && "verifyEmailMethod" in a && (a.verifyEmailMethod === "code" || a.verifyEmailMethod === "link")) {
|
|
9420
|
+
live.auth.verify_email_method = a.verifyEmailMethod;
|
|
9421
|
+
}
|
|
9422
|
+
if (a && "resetPasswordMethod" in a && (a.resetPasswordMethod === "code" || a.resetPasswordMethod === "link")) {
|
|
9423
|
+
live.auth.reset_password_method = a.resetPasswordMethod;
|
|
9424
|
+
}
|
|
9425
|
+
if (a && ("passwordMinLength" in a || "requireNumber" in a || "requireLowercase" in a || "requireUppercase" in a || "requireSpecialChar" in a)) {
|
|
9426
|
+
live.auth.password = {
|
|
9427
|
+
min_length: a.passwordMinLength ?? 8,
|
|
9428
|
+
require_number: a.requireNumber ?? false,
|
|
9429
|
+
require_lowercase: a.requireLowercase ?? false,
|
|
9430
|
+
require_uppercase: a.requireUppercase ?? false,
|
|
9431
|
+
require_special_char: a.requireSpecialChar ?? false
|
|
9432
|
+
};
|
|
9433
|
+
}
|
|
9434
|
+
if (isPlainObject(a?.smtpConfig)) {
|
|
9435
|
+
const s = a.smtpConfig;
|
|
9436
|
+
live.auth.smtp = {
|
|
9437
|
+
enabled: s.enabled ?? false,
|
|
9438
|
+
host: s.host ?? "",
|
|
9439
|
+
port: s.port ?? 587,
|
|
9440
|
+
username: s.username ?? "",
|
|
9441
|
+
hasPassword: s.hasPassword ?? false,
|
|
9442
|
+
sender_email: s.senderEmail ?? "",
|
|
9443
|
+
sender_name: s.senderName ?? "",
|
|
9444
|
+
min_interval_seconds: s.minIntervalSeconds ?? 60
|
|
9445
|
+
};
|
|
9446
|
+
}
|
|
9447
|
+
const d = isPlainObject(raw.deployments) ? raw.deployments : void 0;
|
|
9448
|
+
if (d) {
|
|
9449
|
+
live.deployments = {
|
|
9450
|
+
subdomain: typeof d.customSlug === "string" && d.customSlug ? d.customSlug : null
|
|
9451
|
+
};
|
|
9452
|
+
}
|
|
9453
|
+
return live;
|
|
9454
|
+
}
|
|
9455
|
+
function isPlainObject(v) {
|
|
9456
|
+
return v !== null && typeof v === "object" && !Array.isArray(v);
|
|
9457
|
+
}
|
|
9458
|
+
function asStringArray(v) {
|
|
9459
|
+
return Array.isArray(v) && v.every((x) => typeof x === "string") ? v : null;
|
|
9460
|
+
}
|
|
9461
|
+
function configFromMetadata(raw) {
|
|
9462
|
+
const config = {};
|
|
9463
|
+
const skipped = [];
|
|
9464
|
+
const a = isPlainObject(raw.auth) ? raw.auth : void 0;
|
|
9465
|
+
if (a && "allowedRedirectUrls" in a) {
|
|
9466
|
+
config.auth = config.auth ?? {};
|
|
9467
|
+
config.auth.allowed_redirect_urls = asStringArray(a.allowedRedirectUrls) ?? [];
|
|
9468
|
+
} else {
|
|
9469
|
+
skipped.push("auth.allowed_redirect_urls");
|
|
9470
|
+
}
|
|
9471
|
+
if (a && "requireEmailVerification" in a) {
|
|
9472
|
+
config.auth = config.auth ?? {};
|
|
9473
|
+
config.auth.require_email_verification = a.requireEmailVerification ?? false;
|
|
9474
|
+
} else {
|
|
9475
|
+
skipped.push("auth.require_email_verification");
|
|
9476
|
+
}
|
|
9477
|
+
if (a && "verifyEmailMethod" in a && (a.verifyEmailMethod === "code" || a.verifyEmailMethod === "link")) {
|
|
9478
|
+
config.auth = config.auth ?? {};
|
|
9479
|
+
config.auth.verify_email_method = a.verifyEmailMethod;
|
|
9480
|
+
} else {
|
|
9481
|
+
skipped.push("auth.verify_email_method");
|
|
9482
|
+
}
|
|
9483
|
+
if (a && "resetPasswordMethod" in a && (a.resetPasswordMethod === "code" || a.resetPasswordMethod === "link")) {
|
|
9484
|
+
config.auth = config.auth ?? {};
|
|
9485
|
+
config.auth.reset_password_method = a.resetPasswordMethod;
|
|
9486
|
+
} else {
|
|
9487
|
+
skipped.push("auth.reset_password_method");
|
|
9488
|
+
}
|
|
9489
|
+
if (a && ("passwordMinLength" in a || "requireNumber" in a || "requireLowercase" in a || "requireUppercase" in a || "requireSpecialChar" in a)) {
|
|
9490
|
+
config.auth = config.auth ?? {};
|
|
9491
|
+
config.auth.password = {};
|
|
9492
|
+
if ("passwordMinLength" in a) config.auth.password.min_length = a.passwordMinLength ?? 8;
|
|
9493
|
+
if ("requireNumber" in a) config.auth.password.require_number = a.requireNumber ?? false;
|
|
9494
|
+
if ("requireLowercase" in a) config.auth.password.require_lowercase = a.requireLowercase ?? false;
|
|
9495
|
+
if ("requireUppercase" in a) config.auth.password.require_uppercase = a.requireUppercase ?? false;
|
|
9496
|
+
if ("requireSpecialChar" in a) {
|
|
9497
|
+
config.auth.password.require_special_char = a.requireSpecialChar ?? false;
|
|
9498
|
+
}
|
|
9499
|
+
} else {
|
|
9500
|
+
skipped.push("auth.password");
|
|
9501
|
+
}
|
|
9502
|
+
if (a && "smtpConfig" in a) {
|
|
9503
|
+
const s = a.smtpConfig;
|
|
9504
|
+
if (isPlainObject(s)) {
|
|
9505
|
+
config.auth = config.auth ?? {};
|
|
9506
|
+
config.auth.smtp = {
|
|
9507
|
+
enabled: s.enabled ?? false,
|
|
9508
|
+
host: s.host ?? "",
|
|
9509
|
+
port: s.port ?? 587,
|
|
9510
|
+
username: s.username ?? "",
|
|
9511
|
+
// When backend has a password set, emit a deterministic env() placeholder
|
|
9512
|
+
// so the user knows which secret to define. We do NOT round-trip the
|
|
9513
|
+
// value (it never leaves the backend). Re-applying this TOML force-resends
|
|
9514
|
+
// from the secrets store — see config-diff.ts for the force-resend rationale.
|
|
9515
|
+
...s.hasPassword ? { password: "env(SMTP_PASSWORD)" } : {},
|
|
9516
|
+
sender_email: s.senderEmail ?? "",
|
|
9517
|
+
sender_name: s.senderName ?? "",
|
|
9518
|
+
min_interval_seconds: s.minIntervalSeconds ?? 60
|
|
9519
|
+
};
|
|
9520
|
+
}
|
|
9521
|
+
} else {
|
|
9522
|
+
skipped.push("auth.smtp");
|
|
9523
|
+
}
|
|
9524
|
+
const d = isPlainObject(raw.deployments) ? raw.deployments : void 0;
|
|
9525
|
+
if (d) {
|
|
9526
|
+
if (typeof d.customSlug === "string" && d.customSlug) {
|
|
9527
|
+
config.deployments = { subdomain: d.customSlug };
|
|
9528
|
+
}
|
|
9529
|
+
} else {
|
|
9530
|
+
skipped.push("deployments.subdomain");
|
|
9531
|
+
}
|
|
9532
|
+
return { config, skipped };
|
|
9533
|
+
}
|
|
9534
|
+
|
|
9321
9535
|
// src/commands/config/export.ts
|
|
9322
9536
|
function registerConfigExportCommand(cfg) {
|
|
9323
9537
|
cfg.command("export").description("Pull live project config and write insforge.toml").option("--out <path>", "output path", "insforge.toml").option("--force", "overwrite without confirmation").action(async (opts, cmd) => {
|
|
@@ -9344,44 +9558,7 @@ function registerConfigExportCommand(cfg) {
|
|
|
9344
9558
|
}
|
|
9345
9559
|
const res = await ossFetch("/api/metadata");
|
|
9346
9560
|
const raw = await res.json();
|
|
9347
|
-
const config =
|
|
9348
|
-
const skipped = [];
|
|
9349
|
-
const authSlice = raw?.auth;
|
|
9350
|
-
if (authSlice && typeof authSlice === "object" && "allowedRedirectUrls" in authSlice) {
|
|
9351
|
-
config.auth = config.auth ?? {};
|
|
9352
|
-
config.auth.allowed_redirect_urls = authSlice.allowedRedirectUrls ?? [];
|
|
9353
|
-
} else {
|
|
9354
|
-
skipped.push("auth.allowed_redirect_urls");
|
|
9355
|
-
}
|
|
9356
|
-
if (authSlice && typeof authSlice === "object" && "smtpConfig" in authSlice && authSlice.smtpConfig) {
|
|
9357
|
-
const s = authSlice.smtpConfig;
|
|
9358
|
-
config.auth = config.auth ?? {};
|
|
9359
|
-
config.auth.smtp = {
|
|
9360
|
-
enabled: s.enabled ?? false,
|
|
9361
|
-
host: s.host ?? "",
|
|
9362
|
-
port: s.port ?? 587,
|
|
9363
|
-
username: s.username ?? "",
|
|
9364
|
-
// When backend has a password set, emit a deterministic env()
|
|
9365
|
-
// placeholder so the user knows which secret to define. We do
|
|
9366
|
-
// NOT round-trip the value (it never leaves the backend).
|
|
9367
|
-
// Re-applying this TOML force-resends from the secrets store
|
|
9368
|
-
// — see config-diff.ts for the force-resend rationale.
|
|
9369
|
-
...s.hasPassword ? { password: "env(SMTP_PASSWORD)" } : {},
|
|
9370
|
-
sender_email: s.senderEmail ?? "",
|
|
9371
|
-
sender_name: s.senderName ?? "",
|
|
9372
|
-
min_interval_seconds: s.minIntervalSeconds ?? 60
|
|
9373
|
-
};
|
|
9374
|
-
} else {
|
|
9375
|
-
skipped.push("auth.smtp");
|
|
9376
|
-
}
|
|
9377
|
-
const deploymentsSlice = raw?.deployments;
|
|
9378
|
-
if (deploymentsSlice && typeof deploymentsSlice === "object") {
|
|
9379
|
-
if (typeof deploymentsSlice.customSlug === "string" && deploymentsSlice.customSlug) {
|
|
9380
|
-
config.deployments = { subdomain: deploymentsSlice.customSlug };
|
|
9381
|
-
}
|
|
9382
|
-
} else {
|
|
9383
|
-
skipped.push("deployments.subdomain");
|
|
9384
|
-
}
|
|
9561
|
+
const { config, skipped } = configFromMetadata(raw);
|
|
9385
9562
|
const toml = stringifyConfigToml(config);
|
|
9386
9563
|
writeFileSync9(target, toml, "utf8");
|
|
9387
9564
|
if (json) {
|
|
@@ -9427,6 +9604,48 @@ function diffConfig({ live, file }) {
|
|
|
9427
9604
|
});
|
|
9428
9605
|
}
|
|
9429
9606
|
}
|
|
9607
|
+
if (fileAuth && "require_email_verification" in fileAuth) {
|
|
9608
|
+
const fromV = liveAuth.require_email_verification ?? false;
|
|
9609
|
+
const toV = fileAuth.require_email_verification ?? false;
|
|
9610
|
+
if (fromV !== toV) {
|
|
9611
|
+
changes.push({
|
|
9612
|
+
section: "auth",
|
|
9613
|
+
op: "modify",
|
|
9614
|
+
key: "require_email_verification",
|
|
9615
|
+
from: fromV,
|
|
9616
|
+
to: toV
|
|
9617
|
+
});
|
|
9618
|
+
}
|
|
9619
|
+
}
|
|
9620
|
+
if (fileAuth && "verify_email_method" in fileAuth && fileAuth.verify_email_method) {
|
|
9621
|
+
const fromV = liveAuth.verify_email_method ?? "code";
|
|
9622
|
+
const toV = fileAuth.verify_email_method;
|
|
9623
|
+
if (fromV !== toV) {
|
|
9624
|
+
changes.push({
|
|
9625
|
+
section: "auth",
|
|
9626
|
+
op: "modify",
|
|
9627
|
+
key: "verify_email_method",
|
|
9628
|
+
from: fromV,
|
|
9629
|
+
to: toV
|
|
9630
|
+
});
|
|
9631
|
+
}
|
|
9632
|
+
}
|
|
9633
|
+
if (fileAuth && "reset_password_method" in fileAuth && fileAuth.reset_password_method) {
|
|
9634
|
+
const fromV = liveAuth.reset_password_method ?? "code";
|
|
9635
|
+
const toV = fileAuth.reset_password_method;
|
|
9636
|
+
if (fromV !== toV) {
|
|
9637
|
+
changes.push({
|
|
9638
|
+
section: "auth",
|
|
9639
|
+
op: "modify",
|
|
9640
|
+
key: "reset_password_method",
|
|
9641
|
+
from: fromV,
|
|
9642
|
+
to: toV
|
|
9643
|
+
});
|
|
9644
|
+
}
|
|
9645
|
+
}
|
|
9646
|
+
if (fileAuth?.password) {
|
|
9647
|
+
diffPassword(liveAuth.password, fileAuth.password, changes);
|
|
9648
|
+
}
|
|
9430
9649
|
if (fileAuth?.smtp !== void 0) {
|
|
9431
9650
|
const smtpChange = diffSmtp(liveAuth.smtp, fileAuth.smtp);
|
|
9432
9651
|
if (smtpChange) changes.push(smtpChange);
|
|
@@ -9436,7 +9655,7 @@ function diffConfig({ live, file }) {
|
|
|
9436
9655
|
if (fileDeployments && "subdomain" in fileDeployments) {
|
|
9437
9656
|
const fromV = liveDeployments.subdomain ?? null;
|
|
9438
9657
|
const rawTo = fileDeployments.subdomain;
|
|
9439
|
-
const toV = rawTo === null || rawTo === "" ? null : rawTo;
|
|
9658
|
+
const toV = rawTo === null || rawTo === void 0 || rawTo === "" ? null : rawTo;
|
|
9440
9659
|
if (fromV !== toV) {
|
|
9441
9660
|
changes.push({
|
|
9442
9661
|
section: "deployments",
|
|
@@ -9449,6 +9668,36 @@ function diffConfig({ live, file }) {
|
|
|
9449
9668
|
}
|
|
9450
9669
|
return { changes, summary: summarize(changes) };
|
|
9451
9670
|
}
|
|
9671
|
+
function diffPassword(live, file, changes) {
|
|
9672
|
+
const liveView = live ?? EMPTY_PASSWORD_POLICY;
|
|
9673
|
+
if (file.min_length !== void 0 && liveView.min_length !== file.min_length) {
|
|
9674
|
+
changes.push({
|
|
9675
|
+
section: "auth.password",
|
|
9676
|
+
op: "modify",
|
|
9677
|
+
key: "min_length",
|
|
9678
|
+
from: liveView.min_length,
|
|
9679
|
+
to: file.min_length
|
|
9680
|
+
});
|
|
9681
|
+
}
|
|
9682
|
+
for (const key of [
|
|
9683
|
+
"require_number",
|
|
9684
|
+
"require_lowercase",
|
|
9685
|
+
"require_uppercase",
|
|
9686
|
+
"require_special_char"
|
|
9687
|
+
]) {
|
|
9688
|
+
const fromV = liveView[key];
|
|
9689
|
+
const toV = file[key];
|
|
9690
|
+
if (toV !== void 0 && fromV !== toV) {
|
|
9691
|
+
changes.push({
|
|
9692
|
+
section: "auth.password",
|
|
9693
|
+
op: "modify",
|
|
9694
|
+
key,
|
|
9695
|
+
from: fromV,
|
|
9696
|
+
to: toV
|
|
9697
|
+
});
|
|
9698
|
+
}
|
|
9699
|
+
}
|
|
9700
|
+
}
|
|
9452
9701
|
function diffSmtp(live, fileSmtp) {
|
|
9453
9702
|
const livedView = renderLiveSmtp(live);
|
|
9454
9703
|
const tomlView = renderFileSmtp(fileSmtp);
|
|
@@ -9507,6 +9756,13 @@ var EMPTY_SMTP_VIEW = {
|
|
|
9507
9756
|
sender_name: "",
|
|
9508
9757
|
min_interval_seconds: 60
|
|
9509
9758
|
};
|
|
9759
|
+
var EMPTY_PASSWORD_POLICY = {
|
|
9760
|
+
min_length: 8,
|
|
9761
|
+
require_number: false,
|
|
9762
|
+
require_lowercase: false,
|
|
9763
|
+
require_uppercase: false,
|
|
9764
|
+
require_special_char: false
|
|
9765
|
+
};
|
|
9510
9766
|
function summarize(changes) {
|
|
9511
9767
|
const s = { add: 0, modify: 0, remove: 0, kept: 0 };
|
|
9512
9768
|
for (const c of changes) {
|
|
@@ -9582,10 +9838,22 @@ function formatChange(c) {
|
|
|
9582
9838
|
// src/lib/config-capabilities.ts
|
|
9583
9839
|
function metadataSupports(raw, change) {
|
|
9584
9840
|
if (change.section === "auth" && change.key === "allowed_redirect_urls") {
|
|
9585
|
-
return raw
|
|
9841
|
+
return hasAuthKey(raw, "allowedRedirectUrls");
|
|
9842
|
+
}
|
|
9843
|
+
if (change.section === "auth" && change.key === "require_email_verification") {
|
|
9844
|
+
return hasAuthKey(raw, "requireEmailVerification");
|
|
9845
|
+
}
|
|
9846
|
+
if (change.section === "auth" && change.key === "verify_email_method") {
|
|
9847
|
+
return hasAuthKey(raw, "verifyEmailMethod");
|
|
9848
|
+
}
|
|
9849
|
+
if (change.section === "auth" && change.key === "reset_password_method") {
|
|
9850
|
+
return hasAuthKey(raw, "resetPasswordMethod");
|
|
9851
|
+
}
|
|
9852
|
+
if (change.section === "auth.password") {
|
|
9853
|
+
return hasAuthKey(raw, AUTH_PASSWORD_WIRE_KEY[change.key]);
|
|
9586
9854
|
}
|
|
9587
9855
|
if (change.section === "auth.smtp") {
|
|
9588
|
-
return raw
|
|
9856
|
+
return hasAuthKey(raw, "smtpConfig");
|
|
9589
9857
|
}
|
|
9590
9858
|
if (change.section === "deployments" && change.key === "subdomain") {
|
|
9591
9859
|
return raw?.deployments !== void 0 && raw.deployments !== null && typeof raw.deployments === "object";
|
|
@@ -9594,10 +9862,24 @@ function metadataSupports(raw, change) {
|
|
|
9594
9862
|
void _exhaustive;
|
|
9595
9863
|
return false;
|
|
9596
9864
|
}
|
|
9865
|
+
function hasAuthKey(raw, key) {
|
|
9866
|
+
const auth = raw?.auth;
|
|
9867
|
+
return auth !== void 0 && auth !== null && typeof auth === "object" && key in auth;
|
|
9868
|
+
}
|
|
9869
|
+
var AUTH_PASSWORD_WIRE_KEY = {
|
|
9870
|
+
min_length: "passwordMinLength",
|
|
9871
|
+
require_number: "requireNumber",
|
|
9872
|
+
require_lowercase: "requireLowercase",
|
|
9873
|
+
require_uppercase: "requireUppercase",
|
|
9874
|
+
require_special_char: "requireSpecialChar"
|
|
9875
|
+
};
|
|
9597
9876
|
function changePath(change) {
|
|
9598
9877
|
if (change.section === "auth.smtp") return "auth.smtp";
|
|
9599
9878
|
return `${change.section}.${change.key}`;
|
|
9600
9879
|
}
|
|
9880
|
+
function authPasswordWireKey(key) {
|
|
9881
|
+
return AUTH_PASSWORD_WIRE_KEY[key];
|
|
9882
|
+
}
|
|
9601
9883
|
|
|
9602
9884
|
// src/commands/config/plan.ts
|
|
9603
9885
|
function registerConfigPlanCommand(cfg) {
|
|
@@ -9610,9 +9892,7 @@ function registerConfigPlanCommand(cfg) {
|
|
|
9610
9892
|
const file = parseConfigToml(tomlSource);
|
|
9611
9893
|
const res = await ossFetch("/api/metadata");
|
|
9612
9894
|
const raw = await res.json();
|
|
9613
|
-
const live =
|
|
9614
|
-
auth: { allowed_redirect_urls: raw.auth?.allowedRedirectUrls ?? [] }
|
|
9615
|
-
};
|
|
9895
|
+
const live = liveFromMetadata(raw);
|
|
9616
9896
|
const result = diffConfig({ live, file });
|
|
9617
9897
|
const skipped = result.changes.filter((c) => !metadataSupports(raw, c)).map((c) => changePath(c));
|
|
9618
9898
|
if (json) {
|
|
@@ -9722,29 +10002,6 @@ function registerConfigApplyCommand(cfg) {
|
|
|
9722
10002
|
}
|
|
9723
10003
|
});
|
|
9724
10004
|
}
|
|
9725
|
-
function liveFromMetadata(raw) {
|
|
9726
|
-
const live = { auth: {} };
|
|
9727
|
-
if (raw.auth?.allowedRedirectUrls !== void 0) {
|
|
9728
|
-
live.auth.allowed_redirect_urls = raw.auth.allowedRedirectUrls;
|
|
9729
|
-
}
|
|
9730
|
-
if (raw.auth?.smtpConfig) {
|
|
9731
|
-
const s = raw.auth.smtpConfig;
|
|
9732
|
-
live.auth.smtp = {
|
|
9733
|
-
enabled: s.enabled ?? false,
|
|
9734
|
-
host: s.host ?? "",
|
|
9735
|
-
port: s.port ?? 587,
|
|
9736
|
-
username: s.username ?? "",
|
|
9737
|
-
hasPassword: s.hasPassword ?? false,
|
|
9738
|
-
sender_email: s.senderEmail ?? "",
|
|
9739
|
-
sender_name: s.senderName ?? "",
|
|
9740
|
-
min_interval_seconds: s.minIntervalSeconds ?? 60
|
|
9741
|
-
};
|
|
9742
|
-
}
|
|
9743
|
-
if (raw.deployments) {
|
|
9744
|
-
live.deployments = { subdomain: raw.deployments.customSlug ?? null };
|
|
9745
|
-
}
|
|
9746
|
-
return live;
|
|
9747
|
-
}
|
|
9748
10005
|
async function applyChange(change) {
|
|
9749
10006
|
if (change.section === "auth" && change.key === "allowed_redirect_urls") {
|
|
9750
10007
|
await ossFetch("/api/auth/config", {
|
|
@@ -9753,6 +10010,35 @@ async function applyChange(change) {
|
|
|
9753
10010
|
});
|
|
9754
10011
|
return;
|
|
9755
10012
|
}
|
|
10013
|
+
if (change.section === "auth" && change.key === "require_email_verification") {
|
|
10014
|
+
await ossFetch("/api/auth/config", {
|
|
10015
|
+
method: "PUT",
|
|
10016
|
+
body: JSON.stringify({ requireEmailVerification: change.to })
|
|
10017
|
+
});
|
|
10018
|
+
return;
|
|
10019
|
+
}
|
|
10020
|
+
if (change.section === "auth" && change.key === "verify_email_method") {
|
|
10021
|
+
await ossFetch("/api/auth/config", {
|
|
10022
|
+
method: "PUT",
|
|
10023
|
+
body: JSON.stringify({ verifyEmailMethod: change.to })
|
|
10024
|
+
});
|
|
10025
|
+
return;
|
|
10026
|
+
}
|
|
10027
|
+
if (change.section === "auth" && change.key === "reset_password_method") {
|
|
10028
|
+
await ossFetch("/api/auth/config", {
|
|
10029
|
+
method: "PUT",
|
|
10030
|
+
body: JSON.stringify({ resetPasswordMethod: change.to })
|
|
10031
|
+
});
|
|
10032
|
+
return;
|
|
10033
|
+
}
|
|
10034
|
+
if (change.section === "auth.password") {
|
|
10035
|
+
const wireKey = authPasswordWireKey(change.key);
|
|
10036
|
+
await ossFetch("/api/auth/config", {
|
|
10037
|
+
method: "PUT",
|
|
10038
|
+
body: JSON.stringify({ [wireKey]: change.to })
|
|
10039
|
+
});
|
|
10040
|
+
return;
|
|
10041
|
+
}
|
|
9756
10042
|
if (change.section === "auth.smtp") {
|
|
9757
10043
|
const to = change.to;
|
|
9758
10044
|
const body = {
|