Make Cobble a local install: setup flow, bots-first admin, settings
Local, password-only auth: - No public pages; everything outside /admin and /auth redirects in - First run (no users) sends every page to /auth/signup, which creates the super admin (user #1) once and then locks - Login is email/username + password; removed the emailed-code flow, /auth/sso and email password reset - Google login kept for existing accounts only, never creates them - seed-super-admin now requires SEED_SUPER_ADMIN_PASSWORD Bots-first admin: - /admin and closed sections (people, logs, backups) redirect to /admin/bots; only bots and settings are live (AdminSections) - Removed the old admin layout; every /admin page uses the bots rail - Coordinator bot created at signup/seed and by /admin/bots (ensureCoordinatorBot), which redirects to its chat - bots.system_prompt (markdown) with a default coordinator prompt - seed-bots reuses the existing coordinator Settings: - Sub pages general (default), profile, change-password, listed in the rail with a back link; unknown settings paths redirect to general - Redesigned settings UI: pane header, grouped rows, sticky save bar - General: System/Light/Dark theme, saved per device Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -1,17 +0,0 @@
|
||||
import { AppData } from "@/src/data/app-data";
|
||||
import type { SSOPendingLogin } from "@/src/types";
|
||||
import EJSON from "@/src/utils/ejson";
|
||||
|
||||
export default function readSSOPendingLogin(): SSOPendingLogin | undefined {
|
||||
try {
|
||||
const stored = sessionStorage.getItem(
|
||||
AppData["SSOPendingLoginStorageKey"],
|
||||
);
|
||||
|
||||
return stored
|
||||
? (EJSON.parse(stored) as SSOPendingLogin | undefined)
|
||||
: undefined;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
import fetchApi from "@moduletrace/twui/utils/fetch/fetchApi";
|
||||
import type useFormInit from "@/src/hooks/use-form-init";
|
||||
import type { ApiReqParams } from "@/src/types";
|
||||
import type { APIResponseObject } from "@moduletrace/bunext/types";
|
||||
|
||||
type Params = Pick<ReturnType<typeof useFormInit>, "setLoading" | "setStatus">;
|
||||
|
||||
export default async function resendLoginCode({
|
||||
setLoading,
|
||||
setStatus,
|
||||
}: Params) {
|
||||
setLoading(true);
|
||||
|
||||
const res = await fetchApi<ApiReqParams, APIResponseObject>(
|
||||
`/api/auth/resend-login-code`,
|
||||
{
|
||||
method: "POST",
|
||||
body: {},
|
||||
},
|
||||
);
|
||||
|
||||
setStatus(
|
||||
res.success
|
||||
? {
|
||||
success: true,
|
||||
msg: "A new code is on its way. Previous codes no longer work.",
|
||||
}
|
||||
: {
|
||||
error: true,
|
||||
msg: res.msg || "Couldn't resend the code. Please try again.",
|
||||
},
|
||||
);
|
||||
setLoading(false);
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
import { AppData } from "@/src/data/app-data";
|
||||
import type { SSOPendingLogin } from "@/src/types";
|
||||
import EJSON from "@/src/utils/ejson";
|
||||
|
||||
/**
|
||||
* Remembers which login is waiting for a code, so the SSO page can word
|
||||
* itself to match. Best effort only.
|
||||
*/
|
||||
export default function saveSSOPendingLogin(pending: SSOPendingLogin) {
|
||||
try {
|
||||
sessionStorage.setItem(
|
||||
AppData["SSOPendingLoginStorageKey"],
|
||||
EJSON.stringify(pending) || "",
|
||||
);
|
||||
} catch {}
|
||||
}
|
||||
Reference in New Issue
Block a user